Add managed location to weather plugin API

This commit is contained in:
MM20
2024-05-03 13:02:17 +02:00
parent b0f9ffd473
commit 1d6688831c
19 changed files with 256 additions and 100 deletions
@@ -1,5 +1,20 @@
Search plugins have the following configuration properties:
- `storageStrategy`: Describes how the launcher should store a search result in its internal database. This is relevant when a user pins a search result to favorites, or when they assign a tag or custom label. In these situations, the launcher needs to be able to restore the search result from its database. There are two different strategies:
- **`StorageStrategy.StoreReference`**: The launcher only stores the ID of the search result, and the plugin that created it. To restore a result, the plugin is queried again. This strategy allows the plugin provider to update a search result at a later point in time. However, plugins that use this strategy must guarantee that a search result can be restored in a timely manner. In particular, the plugin provider must be able to restore a search result without any network requests.
- **`StorageStrategy.StoreCopy`** (default): The launcher stores all relevant information about this search result in its own internal database. The result can be restored without querying the plugin again. This strategy is very easy to implement. The downside is, that results cannot be updated at a later point in time.
- `storageStrategy`: Describes how the launcher should store a search result in its internal
database. This is relevant when a user pins a search result to favorites, or when they assign a
tag or custom label. In these situations, the launcher needs to be able to restore the search
result from its database. There are two different strategies:
- **`StorageStrategy.StoreReference`**: The launcher only stores the ID of the search result,
and the plugin that created it. To restore a result, the plugin is queried again. This
strategy allows the plugin provider to update a search result at a later point in time.
However, plugins that use this strategy must guarantee that a search result can be restored in
a timely manner. In particular, the plugin provider must be able to restore a search result
without any network requests.
- **`StorageStrategy.StoreCopy`** (default): The launcher stores all relevant information about
this search result in its own internal database. The result can be restored without querying
the plugin again. This strategy is very easy to implement. The downside is, that results
cannot be updated at a later point in time.
- **`StorageStrategy.Deferred`** (default): The launcher stores all relevant information in its
own internal database, like [StoreCopy]. A fresh copy is fetched from the plugin provider when
the user opens the search result's detail view. This allows the plugin provider to update the
search result at a later point in time, without the time constraints of [StoreReference].
@@ -1,6 +1,8 @@
# File Search
File search provider plugins need to extend the <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.files/-file-provider/index.html" target="_blank">`FileProvider`</a> class:
File search provider plugins need to extend
the <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.files/-file-provider/index.html" target="_blank">`FileProvider`</a>
class:
```kt
class MyFileSearchPlugin : FileProvider(
@@ -9,7 +11,9 @@ class MyFileSearchPlugin : FileProvider(
```
In the super constructor call, pass a <a href="/reference/core/shared/de.mm20.launcher2.plugin.config/-search-plugin-config/index.html" target="_blank">`SearchPluginConfig`</a> object.
In the super constructor call, pass
a <a href="/reference/core/shared/de.mm20.launcher2.plugin.config/-search-plugin-config/index.html" target="_blank">`SearchPluginConfig`</a>
object.
## Plugin config
@@ -24,7 +28,13 @@ suspend fun search(query: String, allowNetwork: Boolean): List<File>
```
- `query` is the search term
- `allowNetwork` is a flag that indicates whether the user has enabled online search for this query. Plugins are generally advised to respect this request. This flag exists mainly for privacy reasons: the majority of searches target offline results (like apps, or contacts). Sending every single search request to external servers is overkill and can be a privacy issue. (Besides, it's not very nice to overload servers with unnecessary requests.) To reduce the amount of data that is leaked to external servers, users can control, whether a search should include online results or not.
- `allowNetwork` is a flag that indicates whether the user has enabled online search for this query.
Plugins are generally advised to respect this request. This flag exists mainly for privacy
reasons: the majority of searches target offline results (like apps, or contacts). Sending every
single search request to external servers is overkill and can be a privacy issue. (Besides, it's
not very nice to overload servers with unnecessary requests.) To reduce the amount of data that is
leaked to external servers, users can control, whether a search should include online results or
not.
`search` returns a list of `File`s. The list can be empty if no results were found.
@@ -32,26 +42,36 @@ suspend fun search(query: String, allowNetwork: Boolean): List<File>
A `File` has the following properties:
- `id`: A unique and stable identifier for this file. This is used to track usage stats so if two files are identical, they must have the same ID, and if they are different, they need to have different IDs.
- `id`: A unique and stable identifier for this file. This is used to track usage stats so if two
files are identical, they must have the same ID, and if they are different, they need to have
different IDs.
- `uri`: A URI that is used to open the file.
- `displayName`: The name that is shown to the user
- `mimeType`: The MIME type of the file. This is only used for informational purposes, i.e. to determine the icon.
- `mimeType`: The MIME type of the file. This is only used for informational purposes, i.e. to
determine the icon.
- `size`: The file size in bytes.
- `path`: The file path. This is shown for informational purposes. It is not used to read or open the file.
- `path`: The file path. This is shown for informational purposes. It is not used to read or open
the file.
- `isDirectory`: Whether the file is a folder. If true, a folder icon is shown.
- `thumbnailUri`: An optional URI to a file thumbnail. Supported schemes are: `content`, `file`, `android.resource`, `http`, and `https`. If this is a `content` URI, make sure that the launcher has the permissions to access it.
- `owner`: The name of the owner of the file. This is mainly relevant for files that are stored in a cloud drive and are not owned by the user themselves, but shared with them.
- `thumbnailUri`: An optional URI to a file thumbnail. Supported schemes
are: `content`, `file`, `android.resource`, `http`, and `https`. If this is a `content` URI, make
sure that the launcher has the permissions to access it.
- `owner`: The name of the owner of the file. This is mainly relevant for files that are stored in a
cloud drive and are not owned by the user themselves, but shared with them.
- `metadata`: Additional file metadata.
## Get a file
If you have set `config.storageStrategy` to `StorageStrategy.StoreReference`, you must override
If you have set `config.storageStrategy` to `StorageStrategy.StoreReference`
or `StorageStrategy.Deferred`, you must override
```kt
suspend fun get(id: String): File?
```
This method is used to lookup a file by its `id`. If the file is no longer available, it should return `null`. In this case, the launcher will remove it from its database.
This method is used to lookup a file by its `id`. If the file is no longer available, it should
return `null`. In this case, the launcher will remove it from its database. If the file is
temporarily unavailable, an exception should be thrown.
## Plugin state
@@ -1,6 +1,8 @@
# Weather Provider Plugins
Weather provider plugins need to extend the <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-weather-provider/index.html" target="_blank">`WeatherProvider`</a> class:
Weather provider plugins need to extend
the <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-weather-provider/index.html" target="_blank">`WeatherProvider`</a>
class:
```kt
class MyWeatherProviderPlugin : WeatherProvider(
@@ -9,13 +11,20 @@ class MyWeatherProviderPlugin : WeatherProvider(
```
In the super constructor call, pass a <a href="/reference/core/shared/de.mm20.launcher2.plugin.config/-weather-plugin-config/index.html" target="_blank">`WeatherPluginConfig`</a> object.
In the super constructor call, pass
a <a href="/reference/core/shared/de.mm20.launcher2.plugin.config/-weather-plugin-config/index.html" target="_blank">`WeatherPluginConfig`</a>
object.
## Plugin config
In the plugin config, you can set the following properties:
- `minUpdateInterval`: Minimum time (in ms) that needs to pass before the provider can be queried again. The launcher respects this value as long as the user does not change the weather settings (provider or location).
- `minUpdateInterval`: Minimum time (in ms) that needs to pass before the provider can be queried
again. The launcher respects this value as long as the user does not change the weather settings (
provider or location).
- `managedLocation`: If true, the plugin will manage the location itself. This means that the user
cannot change the location settings in the launcher.
## Location search
@@ -25,18 +34,26 @@ If your weather provider service provides an API to lookup locations, you should
suspend fun findLocations(query: String, lang: String): List<WeatherLocation>
```
This method is called when a user has _Auto location_ disabled and they are trying to set a new location.
This method is called when a user has _Auto location_ disabled and they are trying to set a new
location.
The default implementation uses the Android Geocoder, but this API has the limitation that it relies on Google Play Services so you should use your own implementation whenever feasable.
The default implementation uses the Android Geocoder, but this API has the limitation that it relies
on Google Play Services so you should use your own implementation whenever feasable.
`findLocations` returns a list of <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-weather-location/index.html" target="_blank">`WeatherLocation`</a>s. Return an empty list if no location has been found.
`findLocations` returns a list
of <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-weather-location/index.html" target="_blank">`WeatherLocation`</a>
s. Return an empty list if no location has been found.
### Location types
There are two types of locations:
There are three types of locations:
- <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-weather-location/-lat-lon/index.html" target="_blank">`WeatherLocation.LatLon`</a>: use this if your weather service identifies locations by their geo coordinates.
- <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-weather-location/-id/index.html" target="_blank">`WeatherLocation.Id`</a>: use this if your weather service has an internal ID system to identify locations.
- <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-weather-location/-lat-lon/index.html" target="_blank">`WeatherLocation.LatLon`</a>:
use this if your weather service identifies locations by their geo coordinates.
- <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-weather-location/-id/index.html" target="_blank">`WeatherLocation.Id`</a>:
use this if your weather service has an internal ID system to identify locations.
- <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-weather-location/-managed/index.html" target="_blank">`WeatherLocation.Managed`</a>:
a special location that indicates that the plugin should determine the location itself.
## Featch weather data
@@ -50,16 +67,30 @@ suspend fun getWeatherData(lat: Double, lon: Double, lang: String?): List<Foreca
suspend fun getWeatherData(location: WeatherLocation, lang: String?): List<Forecast>?
```
The first method is called when the user has _Auto location_ enabled. `lat` and `lon` the last known coordinates of the user.
The first method is called when the user has _Auto location_ enabled. `lat` and `lon` the last known
coordinates of the user.
The second method is called when the user has set their location to a fixed location. `location` is guaranteed to be a value that has been returned by `findLocations` before. If you haven't overriden `findLocations`, this will always be a `WeatherLocation.LatLon`.
The second method is called when the user has set their location to a fixed location. In most cases,
`location` will be a value that has been returned by `findLocations` before, but it's possible that
`location` is a `WeatherLocation.LatLon` if the user has changed the provider after setting a fixed
location. If you haven't overridden `findLocations`, this will always be a `WeatherLocation.LatLon`.
If `managedLocation` is set to `true`, this method is called with `WeatherLocation.Managed`.
Both methods return a list of <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-forecast/index.html" target="_blank">`Forecast`</a>s. If an error occurs, you can throw an exception or return `null`, in this case the launcher will keep the old data and start another attempt at a later time.
Both methods return a list
of <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-forecast/index.html" target="_blank">`Forecast`</a>
s. If an error occurs, you can throw an exception or return `null`, in this case the launcher will
keep the old data and start another attempt at a later time.
`Forecast` objects need at least a `timestamp` (unix time in millis), a `temperature`, a `condition`, an `icon`, a `location` name, and a `provider` name.
`Forecast` objects need at least a `timestamp` (unix time in millis), a `temperature`,
a `condition`, an `icon`, a `location` name, and a `provider` name.
- The `condition` should preferably be localized in the user's language, which is provided by the `lang` parameter.
- To construct a <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-temperature/index.html" target="_blank">`Temperature`</a>, you can use the `Double.C`, `Double.F`, or `Double.K` helper functions, depending on whether the numeric value returned by your weather service API is in degrees celsius, degrees fahrenheit, or kelvin:
- The `condition` should preferably be localized in the user's language, which is provided by
the `lang` parameter.
- To construct
a <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-temperature/index.html" target="_blank">`Temperature`</a>,
you can use the `Double.C`, `Double.F`, or `Double.K` helper functions, depending on whether the
numeric value returned by your weather service API is in degrees celsius, degrees fahrenheit, or
kelvin:
```kt
val temp = tempValueInCelcius.C
@@ -69,12 +100,15 @@ Both methods return a list of <a href="/reference/plugins/sdk/de.mm20.launcher2.
Similar helper functions are available to construct
- `Pressure` (`Double.hPa`, and `Double.mbar`), and
- `WindSpeed` values (`Double.m_s`, `Double.km_h`, and `Double.mph`)
- `Pressure` (`Double.hPa`, and `Double.mbar`), and
- `WindSpeed` values (`Double.m_s`, `Double.km_h`, and `Double.mph`)
- `location` is the name of the location.
- In fixed location mode, you should read this value from the `location` parameter, to ensure that the name in the weather widget matches the name that the user has set in preferences.
- In auto location mode, if your weather service does not give you a location name, you can use the <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-weather-provider/get-location-name.html" target="_blank">`getLocationName`</a> method to reverse geocode the location name using Android's Geocoder API.
- In fixed location mode, you should read this value from the `location` parameter, to ensure
that the name in the weather widget matches the name that the user has set in preferences.
- In auto location mode, if your weather service does not give you a location name, you can use
the <a href="/reference/plugins/sdk/de.mm20.launcher2.sdk.weather/-weather-provider/get-location-name.html" target="_blank">`getLocationName`</a>
method to reverse geocode the location name using Android's Geocoder API.
## Plugin state