A Flutter plugin to allow updating Android. Based on the OTA Updater by LineageOS.
- Make a new Flutter app and add the following to dependencies in your
pubspec.yaml
.
android_flutter_updater:
git:
url: git://github.com/AgentFabulous/android_flutter_updater
- Open your .gitignore file and add:
**/android/libs
- Open
android/build.gradle
and add the following to yourallProjects
block:
afterEvaluate {
if (plugins.hasPlugin('android') ||
plugins.hasPlugin('com.android.application') ||
plugins.hasPlugin('com.android.library')) {
dependencies {
compileOnly fileTree(dir: 'libs/', include: ['*.jar'])
}
}
}
- Create a new directory under
android
calledlibs
and add up your project'sframework.jar
toandroid/libs
. This is necessary because this app accesses many hiddenapi of Android which aren't available on the default SDK jars. - Open
android/app/build.gradle
and changeminSdkVersion
to24
. - Add the following permissions to your
android/app/src/main/AndroidManifest.xml
:
<uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REBOOT" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.RECOVERY" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- Add the following lines to the
application
tag of yourandroid/app/src/main/AndroidManifest.xml
:
<service android:name="co.potatoproject.androidflutterupdater.controller.UpdaterService" />
<service android:name="co.potatoproject.androidflutterupdater.ExportUpdateService" />
<receiver android:name="co.potatoproject.androidflutterupdater.UpdaterReceiver" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<receiver android:name="co.potatoproject.androidflutterupdater.UpdatesCheckReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
You can now simply do:
import 'package:android_flutter_updater/android_flutter_updater.dart';
An example app can be found here.
The plugin reads numerous device props to be able to work with different implementations and OTA-APIs.
- Firstly, set your project name to
ro.build.project
. All other props will depend on the value of this prop. Example:PRODUCT_PROPERTY_OVERRIDES += ro.build.project=potato
The value of this prop will be used in place of{project}
this point on. ro.{project}.version
- Set this to your project's version string.ro.{project}.device
- Set this to your target device's codename.ro.{project}.ota_path
- Set this to the path you'd want to download files to. This path is relative to the default external storage. So, setting this toPotatoCenter
would normally mean/sdcard/PotatoCenter
.ro.{project}.type
- Set this to your build's release type. Can also be thought of as an OTA Channel (weekly, nightly, beta, etc).{project}.updater.uri
- Set this to your Server/API URL.{device}
and{type}
would be replaced by the current device and release-type/build-channel by the plugin as can be seen in the method and fallback/default value.
So, for POSP, it would look something like so:
PRODUCT_PROPERTY_OVERRIDES += \
ro.build.project=potato \
ro.potato.version=2.2 \
ro.potato.device=beryllium \
...
Of course, one would not hardcode values like version and device code-name to props directly. This is solely for demonstration purposes.
You can find the full example here.
NOTE: potato.updater.uri
and ro.potato.ota_path
props are not defined here because they are same as the plugin's fallback values and don't need to be overriden. If you plan on using the plugin, you WILL need to set these props.