1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          Android AB升級 - Demo APP應用流程

          來源:互聯網轉載 時間:2024-01-29 07:41:47

          My Table

          • 1. demo app目錄結構
            • 1.1. 文件目錄
            • 1.2. Android.mk
            • 1.3. AndroidManifest.xml
          • 2. applyPayload觸發流程
            • 2.1. SystemUpdaterActivity啟動
            • 2.2. DeviceListFragment開始升級準備
              • 2.2.1. UpdateParser.parse解析升級文件
              • 2.2.2. applyPayload請求升級
              • 2.2.3. 序列圖
          • 3. 綁定回調流程
            • 3.1. UpdateEngine.bind綁定
            • 3.2. onStatusUpdate和onPayloadApplicationComplete接口函數
            • 3.3. 升級狀態碼解釋
            • 3.4. 升級錯誤碼解釋
          • 4. 參考

          Android源碼有車機系統升級的demo app:SystemUpdater,使用原生settings UI畫面。該應用可用于理解應用層同系統層進行交互,觸發完成升級的邏輯流程。

          1. demo app目錄結構

          1.1. 文件目錄

          該demo app是專用于汽車升級的示例apk,源碼路徑:packages/apps/Car/SystemUpdater

          android/packages/apps/Car/SystemUpdater$ tree.├── AndroidManifest.xml├── Android.mk├── PREUPLOAD.cfg├── res│?? ├── .....└── src    └── com        └── android            └── car                └── systemupdater                    ├── DeviceListFragment.java                    ├── SystemUpdaterActivity.java                    ├── UpdateLayoutFragment.java                    ├── UpdateParser.java                    └── UpFragment.java

          1.2. Android.mk

          LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS := optional# 模塊src路徑加載LOCAL_SRC_FILES := $(call all-java-files-under, src)# 資源加載LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res# 定義該應用是platform appLOCAL_CERTIFICATE := platform# APP名稱LOCAL_PACKAGE_NAME := SystemUpdaterLOCAL_PRIVATE_PLATFORM_APIS := true# 是否預編譯LOCAL_DEX_PREOPT := false# 此常量為是否使用aapt2LOCAL_USE_AAPT2 := true# 控制是否開啟proguard,默認值為fullLOCAL_PROGUARD_ENABLED := disabledLOCAL_DX_FLAGS := --multi-dex# This module depends on androidx.car_car for legacy reasons.# Don't copy-paste the use of androidx.car_car# 依賴庫LOCAL_STATIC_ANDROID_LIBRARIES :=     androidx.car_car     androidx.legacy_legacy-support-v4     androidx.appcompat_appcompatinclude $(BUILD_PACKAGE)

          1.3. AndroidManifest.xml

          <!-- 包名 --><manifest        xmlns:andro        package="com.android.car.systemupdater"><!-- 應用外部存儲讀寫權限、重啟權限、usb權限 -->    <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.REBOOT" />    <uses-feature android:name="android.hardware.usb.host" /><!-- 使用settings主題歌和標題目錄 -->    <application            android:label="@string/title"            android:theme="@style/SystemUpdaterTheme">        <activity            android:name="com.android.car.systemupdater.SystemUpdaterActivity"            android:label="@string/title">            <intent-filter>                <action android:name="android.intent.action.MAIN" />            </intent-filter>            <intent-filter>                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />            </intent-filter>            <intent-filter>                <action android:name="com.android.settings.action.EXTRA_SETTINGS" />                <category android:name="android.intent.category.DEFAULT" />            </intent-filter>            <meta-data android:name="com.android.settings.title"                       android:resource="@string/title" />            <meta-data android:name="com.android.settings.icon"                       android:resource="@drawable/ic_system_update_alt_black_48dp" />            <meta-data android:name="com.android.settings.category"                       android:value="com.android.settings.category.ia.system" />        </activity>    </application></manifest>

          2. applyPayload觸發流程

          2.1. SystemUpdaterActivity啟動

          //packages/apps/Car/SystemUpdater/src/com/android/car/systemupdater/SystemUpdaterActivity.javapublic class SystemUpdaterActivity extends AppCompatActivity        implements DeviceListFragment.SystemUpdater {    private static final String FRAGMENT_TAG = "FRAGMENT_TAG";    private static final int STORAGE_PERMISSIONS_REQUEST_CODE = 0;    //權限    private static final String[] REQUIRED_STORAGE_PERMISSIONS = new String[]{            Manifest.permission.READ_EXTERNAL_STORAGE,            Manifest.permission.WRITE_EXTERNAL_STORAGE,            Manifest.permission.WRITE_MEDIA_STORAGE    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        //check 權限        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)                != PackageManager.PERMISSION_GRANTED) {            ActivityCompat.requestPermissions(this, REQUIRED_STORAGE_PERMISSIONS,                    STORAGE_PERMISSIONS_REQUEST_CODE);        }        setContentView(R.layout.activity_main);        Toolbar toolbar = findViewById(R.id.toolbar);        setSupportActionBar(toolbar);        if (savedInstanceState == null) {            Bundle intentExtras = getIntent().getExtras();            if (intentExtras != null && intentExtras.getBoolean(EXTRA_RESUME_UPDATE)) {                //創建UpdateLayoutFragment對象,調用newResumedInstance                UpdateLayoutFragment fragment = UpdateLayoutFragment.newResumedInstance();                getSupportFragmentManager().beginTransaction()                        .replace(R.id.device_container, fragment, FRAGMENT_TAG)                        .commitNow();            } else {                //創建DeviceListFragment對象                DeviceListFragment fragment = new DeviceListFragment();                getSupportFragmentManager().beginTransaction()                        .replace(R.id.device_container, fragment, FRAGMENT_TAG)                        .commitNow();            }        }    }    .....

          2.2. DeviceListFragment開始升級準備

          (1) DeviceListFragment.java - onCreate

              @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Context context = getContext();        mItemProvider = new FileItemProvider(context);        mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);        if (mStorageManager == null) {            if (Log.isLoggable(TAG, Log.WARN)) {                Log.w(TAG, "Failed to get StorageManager");            }            Toast.makeText(context, R.string.cannot_access_storage, Toast.LENGTH_LONG).show();            return;        }    }

          (2)調用get(int position)函數

          (3)調用onFileSelected(File file)選中的升級包文件

          (4)如果升級包存在,則調用mSystemUpdater.applyUpdate(file),該接口由SystemUpdaterActivity實現

          //DeviceListFragment.java    /** Used to request installation of an update. */    interface SystemUpdater {        /** Attempt to apply an update to the device contained in the {@code file}. */        void applyUpdate(File file);    }

          (5)SystemUpdaterActivity.java - applyUpdate,獲取UpdateLayoutFragment對象,傳入升級路徑

              @Override    public void applyUpdate(File file) {        //new UpdateLayoutFragment()對象        //new Bundle對象        UpdateLayoutFragment fragment = UpdateLayoutFragment.getInstance(file);        getSupportFragmentManager().beginTransaction()                .replace(R.id.device_container, fragment, FRAGMENT_TAG)                .addToBackStack(null)                .commit();    }

          (6)調用UpdateLayoutFragment.java - onActivityCreated,然后調用mPackageVerifier.execute(mUpdateFile)

              @Override    public void onActivityCreated(Bundle savedInstanceState) {        super.onActivityCreated(savedInstanceState);        .....        if (getArguments().getBoolean(EXTRA_RESUME_UPDATE)) {            //顯示install進度            showInstallationInProgress();        } else {            //執行必要的步驟開始升級            mPackageVerifier.execute(mUpdateFile);        }    }
          //UpdateLayoutFragment.java//該類繼承AsyncTask//嘗試驗證更新并提取安裝所需的信息    private class UpdateVerifier extends AsyncTask<File, Void, UpdateParser.ParsedUpdate> {        @Override        protected UpdateParser.ParsedUpdate doInBackground(File... files) {            Preconditions.checkArgument(files.length > 0, "No file specified");            File file = files[0];            try {                //調用UpdateParser.java的parse解析升級包文件                return UpdateParser.parse(file);            } catch (IOException e) {                Log.e(TAG, String.format("For file %s", file), e);                return null;            }        }        @Override        protected void onPostExecute(UpdateParser.ParsedUpdate result) {            mProgressBar.setVisibility(View.GONE);            if (result == null) {                showStatus(R.string.verify_failure);                return;            }            if (!result.isValid()) {                showStatus(R.string.verify_failure);                Log.e(TAG, String.format("Failed verification %s", result));                return;            }            if (Log.isLoggable(TAG, Log.INFO)) {                Log.i(TAG, result.toString());            }            //調用installUpdate,然后調用mUpdateEngine.applyPayload傳入升級所需要的url,偏移量,大小等開始升級            showInstallNow(result);        }    }

          2.2.1. UpdateParser.parse解析升級文件

          //packages/apps/Car/SystemUpdater/src/com/android/car/systemupdater/UpdateParser.java    static ParsedUpdate parse(@NonNull File file) throws IOException {        Preconditions.checkNotNull(file);        long payloadOffset = 0;        long payloadSize = 0;        boolean payloadFound = false;        String[] props = null;        try (ZipFile zipFile = new ZipFile(file)) {            Enumeration<? extends ZipEntry> entries = zipFile.entries();            while (entries.hasMoreElements()) {                ZipEntry entry = entries.nextElement();                long fileSize = entry.getCompressedSize();                if (!payloadFound) {                    payloadOffset += ZIP_FILE_HEADER + entry.getName().length();                    if (entry.getExtra() != null) {                        payloadOffset += entry.getExtra().length;                    }                }                if (entry.isDirectory()) {                    continue;                } else if (entry.getName().equals(PAYLOAD_BIN_FILE)) {                    payloadSize = fileSize; //payload.bin升級數據文件的大小                    payloadFound = true;                } else if (entry.getName().equals(PAYLOAD_PROPERTIES)) {                    try (BufferedReader buffer = new BufferedReader(                            new InputStreamReader(zipFile.getInputStream(entry)))) {                        props = buffer.lines().toArray(String[]::new);  //hash值                    }                }                if (!payloadFound) {                    payloadOffset += fileSize; //偏移量                }                if (Log.isLoggable(TAG, Log.DEBUG)) {                    Log.d(TAG, String.format("Entry %s", entry.getName()));                }            }        }        //內部靜態類        return new ParsedUpdate(file, payloadOffset, payloadSize, props);    }

          2.2.2. applyPayload請求升級

          調用framework java應用層的接口

          //frameworks/base/core/java/android/os/UpdateEngine.java    private IUpdateEngine mUpdateEngine;    private IUpdateEngineCallback mUpdateEngineCallback = null;    private final Object mUpdateEngineCallbackLock = new Object();    public void applyPayload(String url, long offset, long size, String[] headerKeyValuePairs) {        try {            mUpdateEngine.applyPayload(url, offset, size, headerKeyValuePairs);        } catch (RemoteException e) {            throw e.rethrowFromSystemServer();        }    }

          2.2.3. 序列圖


          3. 綁定回調流程

          3.1. UpdateEngine.bind綁定

          //packages/apps/Car/SystemUpdater/src/com/android/car/systemupdater/UpdateLayoutFragment.java    private ProgressBar mProgressBar; //升級進度    private File mUpdateFile;   //升級包文件    private Button mSystemUpdateToolbarAction;    //PowerManager對象,用于重啟    private PowerManager mPowerManager;    private NotificationManager mNotificationManager;    private final UpdateVerifier mPackageVerifier = new UpdateVerifier();    //創建UpdateEngine對象    private final UpdateEngine mUpdateEngine = new UpdateEngine();    private boolean mInstallationInProgress = false;    //新建對象    private final CarUpdateEngineCallback mCarUpdateEngineCallback = new CarUpdateEngineCallback();    ...//UpdateLayoutFragment.java的onPostExecute函數調用    /** Show the install now button. */    private void showInstallNow(UpdateParser.ParsedUpdate update) {        mContentTitle.setText(R.string.install_ready);        mContentInfo.append(getString(R.string.update_file_name, mUpdateFile.getName()));        mContentInfo.append(System.getProperty("line.separator"));        mContentInfo.append(getString(R.string.update_file_size));        mContentInfo.append(Formatter.formatFileSize(getContext(), mUpdateFile.length()));        mContentDetails.setText(null);        //調用installUpdate        mSystemUpdateToolbarAction.setOnClickListener(v -> installUpdate(update));        ...    }    /** Attempt to install the update that is copied to the device. */    private void installUpdate(UpdateParser.ParsedUpdate parsedUpdate) {        //調用showInstallationInProgress        showInstallationInProgress();        //調用applyPayload        mUpdateEngine.applyPayload(                parsedUpdate.mUrl, parsedUpdate.mOffset, parsedUpdate.mSize, parsedUpdate.mProps);    }    //綁定UpdateEngine,并且顯示進度    /** Set the layout to show installation progress. */    private void showInstallationInProgress() {        mInstallationInProgress = true;        mProgressBar.setIndeterminate(false);        mProgressBar.setVisibility(View.VISIBLE);        mProgressBar.setMax(PERCENT_MAX);        mSystemUpdateToolbarAction.setVisibility(View.GONE);        showStatus(R.string.install_in_progress);        //CarUpdateEngineCallback回調函數調用        mUpdateEngine.bind(mCarUpdateEngineCallback, new Handler(getContext().getMainLooper()));    }

          3.2. onStatusUpdate和onPayloadApplicationComplete接口函數

          • 升級狀態碼見frameworks/base/core/java/android/os/UpdateEngine.java - UpdateStatusConstants(抽取system/update_engine/client_library/include/update_engine/update_status.h數據)
          • 升級錯誤碼見frameworks/base/core/java/android/os/UpdateEngine.java - ErrorCodeConstants(抽取system/update_engine/common/error_code.h部分)
          //UpdateLayoutFragment.java   public class CarUpdateEngineCallback extends UpdateEngineCallback {        @Override        //升級狀態碼和進度接收        public void onStatusUpdate(int status, float percent) {            if (Log.isLoggable(TAG, Log.DEBUG)) {                Log.d(TAG, String.format("onStatusUpdate %d, Percent %.2f", status, percent));            }            switch (status) {                //UpdateStatusConstants升級狀態碼見frameworks/base/core/java/android/os/UpdateEngine.java                case UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT:                    rebootNow();                    break;                case UpdateEngine.UpdateStatusConstants.DOWNLOADING:                    mProgressBar.setProgress((int) (percent * 100));                    break;                default:                    // noop            }        }        @Override        //升級結果接收        public void onPayloadApplicationComplete(int errorCode) {            Log.w(TAG, String.format("onPayloadApplicationComplete %d", errorCode));            mInstallationInProgress = false;            //錯誤碼見frameworks/base/core/java/android/os/UpdateEngine.java的ErrorCodeConstants集合定義            showStatus(errorCode == UpdateEngine.ErrorCodeConstants.SUCCESS                    ? R.string.install_success                    : R.string.install_failed);            mProgressBar.setVisibility(View.GONE);            mSystemUpdateToolbarAction.setVisibility(View.GONE);        }    }

          重啟接口調用:

              private void rebootNow() {        if (Log.isLoggable(TAG, Log.INFO)) {            Log.i(TAG, "Rebooting Now.");        }        mPowerManager.reboot(REBOOT_REASON);    }

          3.3. 升級狀態碼解釋

          //frameworks/base/core/java/android/os/UpdateEngine.java   /**     * Status codes for update engine. Values must agree with the ones in     * {@code system/update_engine/client_library/include/update_engine/update_status.h}.     */    public static final class UpdateStatusConstants {        //IDLE狀態        public static final int IDLE = 0;        //update engine服務檢查升級        public static final int CHECKING_FOR_UPDATE = 1;        //存在可獲取的升級        public static final int UPDATE_AVAILABLE = 2;        //downloading下載步驟狀態        public static final int DOWNLOADING = 3;        //update engine正在校驗狀態        public static final int VERIFYING = 4;        //update engine正在完成一個升級        public static final int FINALIZING = 5;        //請求重啟(一般是升級成功)        public static final int UPDATED_NEED_REBOOT = 6;        //update egnine上報一個錯誤事件        public static final int REPORTING_ERROR_EVENT = 7;        //update engine試圖恢復一個升級(可能升級被中斷過)        public static final int ATTEMPTING_ROLLBACK = 8;        //update engine處于被禁止狀態        public static final int DISABLED = 9;    }

          3.4. 升級錯誤碼解釋

          //frameworks/base/core/java/android/os/UpdateEngine.java    /**     * Error codes from update engine upon finishing a call to     * {@link applyPayload}. Values will be passed via the callback function     * {@link UpdateEngineCallback#onPayloadApplicationComplete}. Values must     * agree with the ones in {@code system/update_engine/common/error_code.h}.     */    public static final class ErrorCodeConstants {        //升級成功        public static final int SUCCESS = 0;        //升級失敗        public static final int ERROR = 1;        //文件系統拷貝失敗        public static final int FILESYSTEM_COPIER_ERROR = 4;        /**         * Error code: an update failed to apply due to an error in running         * post-install hooks.         */        //post-install運行時報錯        public static final int POST_INSTALL_RUNNER_ERROR = 5;        /**         * Error code: an update failed to apply due to a mismatching payload.         *         * <p>For example, the given payload uses a feature that's not         * supported by the current update engine.         */        public static final int PAYLOAD_MISMATCHED_TYPE_ERROR = 6;        /**         * Error code: an update failed to apply due to an error in opening         * devices.         */        public static final int INSTALL_DEVICE_OPEN_ERROR = 7;        /**         * Error code: an update failed to apply due to an error in opening         * kernel device.         */        public static final int KERNEL_DEVICE_OPEN_ERROR = 8;        /**         * Error code: an update failed to apply due to an error in fetching         * the payload.         *         * <p>For example, this could be a result of bad network connection         * when streaming an update.         */        //download傳輸報錯,比如U盤升級download時拔出U盤        public static final int DOWNLOAD_TRANSFER_ERROR = 9;        /**         * Error code: an update failed to apply due to a mismatch in payload         * hash.         *         * <p>update engine does sanity checks for the given payload and its         * metadata.         */        public static final int PAYLOAD_HASH_MISMATCH_ERROR = 10;        /**         * Error code: an update failed to apply due to a mismatch in payload         * size.         */        public static final int PAYLOAD_SIZE_MISMATCH_ERROR = 11;        /**         * Error code: an update failed to apply due to failing to verify         * payload signatures.         */        public static final int DOWNLOAD_PAYLOAD_VERIFICATION_ERROR = 12;        /**         * Error code: an update failed to apply due to a downgrade in payload         * timestamp.         *         * <p>The timestamp of a build is encoded into the payload, which will         * be enforced during install to prevent downgrading a device.         */        //版本時間戳校驗,如果不支持回滾,則回滾升級會報錯        public static final int PAYLOAD_TIMESTAMP_ERROR = 51;        /**         * Error code: an update has been applied successfully but the new slot         * hasn't been set to active.         *         * <p>It indicates a successful finish of calling {@link #applyPayload} with         * {@code SWITCH_SLOT_ON_REBOOT=0}. See {@link #applyPayload}.         */        public static final int UPDATED_BUT_NOT_ACTIVE = 52;    }

          4. 參考

          • Android.mk 常用常量總結
          • java SystemUpdater 到 c++ updateEngine
          標簽:demoapp-

          網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...

          在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...

          在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...

          有沒有人花888充值淘寶88會員?懂的人說說怎么樣吧?過來看看,有個傻女孩[羅斯],因為她一年前是88kai的會員,但續約時沒注意。當時規定1000分以下需要888分。我沒注意[遮住我的臉]。當我發現的時候,它已經在支付界面上了。當時,我的手機是華為榮耀。返回按鈕和指紋支付按鈕是相同的。當我想按返回按鈕時,付款成功了。后來聯系淘寶客服,他們還給我了??头χf不相信有人會買888。初衷是讓大家有一...

          我的電腦的flash打不開了怎么辦?瀏覽器有時會提示Flash版本太低,無法使用。該解決方案包括:1.首先,檢查一下自己有沒有安裝。如果你不 t,下載安裝。2.開始菜單/控制面板/Flash播放器/更新/立即更新。按確定就行了。3.還有一種方法就是用騰訊電腦管家來修復。打開管家后,你會發現電腦診所的Flash版本太低,然后馬上點擊修復。flash插件安裝上也不能播放怎么弄?系統中可能有緩存,或者瀏...

          蘋果手機QQ顯示2G在線怎么設置?有兩種情況1.是可以表示用蘋果手機登陸后的,但是是2g網絡,同理可證,3g是手機3g在線,另外無線網絡標志意思是是手機wifi在線,電腦標志應該是電腦免費。2.要是是對方的屬于什么掛機的或退圈于桌面本來以前的那是2g然后他剛刪號時間不長也會會如此總是顯示.蘋果手機上的QQ只顯示4G,沒有顯示Wifi,這是什么情況?應該怎么辦?直接點擊可以設置,下拉到點開,再點可以...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>