Android11.0系统中添加OTA升级接口供应用层调用

编程入门 行业动态 更新时间:2024-10-26 14:29:51

Android11.0系统中添加OTA升级接口供<a href=https://www.elefans.com/category/jswz/34/1767742.html style=应用层调用"/>

Android11.0系统中添加OTA升级接口供应用层调用

Android11.0系统中添加OTA升级接口供应用层调用

  • 添加OTA升级接口
    • 参考及说明
    • Demo app中添加OTA功能
    • 应用请求进行OTA升级

添加OTA升级接口

本文主要描述在RK3568 Android11中通过在自已的系统App中添加OTA升级接口,上层应用开发者在自己的应用中调用此接口进行系统升级。
如何在系统源码中添加开发自己的系统App,可以查看: Android11.0系统中添加开发系统App

参考及说明

OTA系统升级主要分AB系统升级及非AB系统升级,本文实现的是非AB系统的升级,主要参考了services.devicepolicy源码的相关逻辑,路径为:/frameworks/base/services/devicepolicy。

  1. AB系统:主要是基于UpdateEngine及UpdateEngineCallback,路径:/frameworks/base/core/java/android/os/UpdateEngine.java /frameworks/base/core/java/android/os/UpdateEngineCallback.java
  2. 非AB系统,主要是调用RecoverySystem.installPackage(mContext, mCopiedUpdateFile)方法,路径为 /frameworks/base/core/java/android/os/RecoverySystem.java;
  3. RK3568 Android11.0中将OTA升级包adb上传到/storage/emulated/0/update.zip,重启系统,系统中的RKUpdateService服务也会自动检测到升级包,并提示固件升级。

Demo app中添加OTA功能

Demo应用通过其它应用传送的Uri获取OTA升级包文件,并保存为/storage/emulated/0/update.zip,之后调用RecoverySystem.installPackage()方法升级。

  1. 添加UpdateActivity,路径为 /vendor/yjz/demo/app/src/main/java/com/yjz/demo/update/UpdateActivity.java;

package com.yjz.demo.update;import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.WindowManager;import androidx.annotation.Nullable;
import com.yjz.demo.util.SpHelper;import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;public class UpdateActivity extends Activity {private static final String TAG = "UpdateActivity";private String mOtaFileSavePath;private int mOtaVersion;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {WindowManager.LayoutParams layoutParams = getWindow().getAttributes();layoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;super.onCreate(savedInstanceState);// 保存文件路径:/storage/emulated/0/update.zipmOtaFileSavePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "update.zip";Intent intent = getIntent();mOtaVersion = intent.getIntExtra("ota_version", -1);StagingAsyncAppTask mStagingTask = new StagingAsyncAppTask();mStagingTask.execute(getIntent().getData());}private void startInstall() {new Thread() {@Overridepublic void run() {UpdateManager.getInstance(UpdateActivity.this).startOTAUpdate(mOtaVersion, mOtaFileSavePath, new UpdateManager.OTAUpdateReadyListener() {@Overridepublic void onReady() {SpHelper.getInstance(UpdateActivity.this).setOTAVersion(Version.SYSTEM_OTA_VERSION);}});}}.start();}@SuppressLint("NewApi")private final class StagingAsyncAppTask extends AsyncTask<Uri, Void, File> {@Overrideprotected File doInBackground(Uri... params) {Log.d(TAG, "copy file from user app start");if (params == null || params.length <= 0) {return null;}Uri packageUri = params[0];if (null == packageUri) {return null;}try (InputStream in = getContentResolver().openInputStream(packageUri)) {// Despite the comments in ContentResolver#openInputStream the returned stream can// be null.if (in == null) {return null;}File mStagedFile = new File(mOtaFileSavePath);try (OutputStream out = new FileOutputStream(mStagedFile)) {byte[] buffer = new byte[1024 * 1024];int bytesRead;while ((bytesRead = in.read(buffer)) >= 0) {// Be nice and respond to a cancellationout.write(buffer, 0, bytesRead);}}return mStagedFile;} catch (IOException | SecurityException | IllegalStateException e) {Log.w(TAG, "Error staging apk from content URI", e);}return null;}@Overrideprotected void onPostExecute(File installFile) {if (null != installFile) {// Now start the installation again from a fileLog.d(TAG, "copy file from user app finish");startInstall();Log.d(TAG, "send to install");} else {Log.d(TAG, "copy file from user app fail");}finish();}}
}
  1. UpdateManager、Version,在源码中为了便于引包,一些逻辑类实现在/frameworks/base/core/java/com/yjz/study;
    注意:OTA升级包路径/storage/emulated/0/update.zip 在传入RecoverySystem.installPackage(Context context, File packageFile)方法时,需要将路径修改为/data/media/0/update.zip,否则系统重启进入recovery模式后会找不到升级包,recovery模式下路径是/data/media/0/

package com.yjz.study.core.update;import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Environment;
import android.os.RecoverySystem;
import android.util.Log;
import com.yjz.study.core.Version;
import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;public final class UpdateManager {private static final String TAG = "UpdateManager";private Context mContext;private Object mLock = new byte[0];private boolean mHasOTAUpdate;private static volatile UpdateManager INSTANCE;private UpdateManager(Context context) {mContext = context;}public static UpdateManager getInstance(Context context) {if (null == INSTANCE) {synchronized (UpdateManager.class) {if (null == INSTANCE) {INSTANCE = new UpdateManager(context.getApplicationContext());}}}return INSTANCE;}@SuppressLint("NewApi")public void startOTAUpdate(int otaVersion, String otaPath, OTAUpdateReadyListener listener) {Log.d(TAG, "startOTAUpdate--->" + otaPath);if (otaVersion < 1) {Log.e(TAG, "ota version not found");return;}if (otaVersion <= Version.SYSTEM_OTA_VERSION) {Log.e(TAG, "has new version, not need update");return;}File f = new File(otaPath);if (!f.exists()) {Log.e(TAG, "ota file not found");return;}if (!"update.zip".equals(f.getName())) {Log.e(TAG, "ota file name error");return;}if (!otaPath.contains(Environment.getExternalStorageDirectory().getAbsolutePath())) {Log.e(TAG, "ota file path error");return;}try {RecoverySystem.verifyPackage(f, new RecoverySystem.ProgressListener() {@Overridepublic void onProgress(int progress) {Log.d(TAG, "verifyPackage progress--->" + progress);}}, null);} catch (IOException e) {e.printStackTrace();} catch (GeneralSecurityException e) {Log.e(TAG, "ota升级包验证失败--->");e.printStackTrace();return;}String realPath = "/data/media/0/" + f.getName();synchronized (mLock) {if (mHasOTAUpdate) {Log.d(TAG, "OTA升级任务进行中");return;}mHasOTAUpdate = true;}if (null != listener) {listener.onReady();}//不是A/B系统,直接使用此方法升级try {RecoverySystem.installPackage(mContext, new File(realPath));} catch (IOException e) {Log.w(TAG, "IO error while trying to install non AB update.", e);return;}if (null != f && f.exists()) {f.delete();}}public interface OTAUpdateReadyListener {void onReady();}
}

package com.yjz.study.core;public interface Version {int SYSTEM_OTA_VERSION = 1;
}
  1. 在AndroidManifest.xml中注册UpdateActivity,路径为 /vendor/yjz/demo/app/src/main/AndroidManifest.xml;

    调用RecoverySystem.installPackage()必须要添加权限:
    android.permission.RECOVERY;
    android.permission.REBOOT;

    如果不需要用户看到OTA升级界面,想静默进行,UpdateActivity的主题设置为
    android:theme=“@android:style/Theme.Translucent.NoTitleBar”


//********省略代码******<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.RECOVERY" /><uses-permission android:name="android.permission.REBOOT" /><uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" /><uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" /><uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /><activityandroid:name=".update.UpdateActivity"android:theme="@android:style/Theme.Translucent.NoTitleBar"android:exported="true"><intent-filter android:priority="1"><action android:name="android.intent.action.OTA_UPDATE" /><category android:name="android.intent.category.DEFAULT" /></intent-filter><intent-filter android:priority="1"><action android:name="android.intent.action.OTA_UPDATE" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="content" /><data android:mimeType="application/vnd.android.package-archive" /></intent-filter></activity>//********省略代码******

应用请求进行OTA升级

  1. 开发者在应用可以通过requestOTAUpdate()方法示例进行升级请求。
public int requestOTAUpdate(Context context, Uri uri, int otaVersion, int currentOtaVersion) {if (otaVersion <= currentOtaVersion) {return ERROR_CODE_NOT_UPDATE;}try {PackageInfo packinfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);String[] list = packinfo.requestedPermissions;boolean hasPermission = false;if (null != list) {for (int i = 0; i < list.length; i++) {if (Manifest.permission.QUERY_ALL_PACKAGES.equals(list[i])) {hasPermission = true;break;}}}if (!hasPermission) {throw new RuntimeException("need permission " + Manifest.permission.QUERY_ALL_PACKAGES);}} catch (PackageManager.NameNotFoundException e) {throw new RuntimeException(e);}if (!checkExistForApp(context, "com.yjz.demo")) {return ERROR_CODE_NOT_SUPPORTED;}Intent intent = new Intent("android.intent.action.OTA_UPDATE");intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);intent.setDataAndType(uri, "application/vnd.android.package-archive");intent.putExtra("ota_version", otaVersion);intent.putExtra("allowed_Background", true);context.startActivity(intent);return CODE_SUCCESS;}

更多推荐

Android11.0系统中添加OTA升级接口供应用层调用

本文发布于:2024-02-11 14:13:36,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1681413.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:应用层   接口   系统   OTA

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!