首先,在android 原生的设置中就已经有了ota联网升级的功能,可以仿照哪个做一个开机联网检测是否有新版本的功能,想法是在SystemUI 中增加,在第一次开机联网的时候检测更新

AndroidManifest.xml
增加权限

diff --git a/frameworks/base/packages/SystemUI/AndroidManifest.xml b/frameworks/base/packages/SystemUI/AndroidManifest.xml
old mode 100644
new mode 100755
index 5599b5a..e678030
--- a/frameworks/base/packages/SystemUI/AndroidManifest.xml
+++ b/frameworks/base/packages/SystemUI/AndroidManifest.xml
@@ -70,6 +70,7 @@<uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" /><uses-permission android:name="android.permission.CONTROL_VPN" /><uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/>
+    <uses-permission android:name="android.permission.INTERNET" /><!-- Physical hardware --><uses-permission android:name="android.permission.MANAGE_USB" /><uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS" />
@@ -105,7 +106,6 @@<!-- DreamManager --><uses-permission android:name="android.permission.READ_DREAM_STATE" /><uses-permission android:name="android.permission.WRITE_DREAM_STATE" /><!-- Alarm clocks --><uses-permission android:name="com.android.alarm.permission.SET_ALARM" />@@ -229,6 +229,7 @@android:theme="@style/Theme.SystemUI"android:defaultToDeviceProtectedStorage="true"android:directBootAware="true"
+        android:usesCleartextTraffic="true"android:appComponentFactory="android.support.v4.app.CoreComponentFactory"><!-- Keep theme in sync with SystemUIApplication.onCreate().Setting the theme on the application does not affect views inflated by services.

android:usesCleartextTraffic="true"表示是否打算使用明文网络流量,例如明文HTTP, Aandroid 9 及以上默认为false,推荐使用 HTTPS 加密的方式传输,更安全

NetworkControllerImpl.java
网络监听广播,监听到网络变化后,检测网络是否可用,可用检测是否有版本升级,有就弹出升级dialog
SystemProperties.set(“zwt.update.ischeck”, “1”); 是这只系统的变量,因为不是persist 或 ro 开头的变量,所以断电上电后这个属性就被删除了,达到开机只检测一次的目的

diff --git a/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/frameworks/base/packages/SystemUI/sr
old mode 100644
new mode 100755
index b8d6f13..b65093c
--- a/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -34,6 +34,8 @@ import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.os.PersistableBundle;
+import android.os.Build;
+import android.os.SystemProperties;import android.provider.Settings;import android.telephony.CarrierConfigManager;import android.telephony.ServiceState;
@@ -58,6 +60,8 @@ import com.android.systemui.R;import com.android.systemui.settings.CurrentUserTracker;import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;// Mediatek Android Patch Begin
+import com.android.systemui.update.CheckoutUpdateVersion;
+import com.android.systemui.update.UpdateVersionDialogImpl;import com.android.systemui.util.Utils;// Mediatek Android Patch End@@ -462,6 +466,17 @@ public class NetworkControllerImpl extends BroadcastReceiverbreak;case ConnectivityManager.CONNECTIVITY_ACTION:case ConnectivityManager.INET_CONDITION_ACTION:
+                // 2022 add update dialog start
+                Log.d(TAG,"##zwt_UpdateDialog## internet change,isCheck::"+("1".equals(SystemProperties.get("wssl.ischeck"))));
+                if (!("1".equals(SystemProperties.get("wssl.update.ischeck")))){
+                    if (isNetworkAvailable()){
+                        SystemProperties.set("zwt.update.ischeck", "1");
+                        CheckoutUpdateVersion checkoutUpdateVersion = new CheckoutUpdateVersion(new UpdateVersionDialogImpl(mContext).getHandler());
+                        Log.d(TAG,"##zwt_UpdateDialog## show dialog");
+                        checkoutUpdateVersion.checkout();
+                    }
+                }
+                // 2022 add update dialog endupdateConnectivity(intent);break;// Mediatek Android Patch End
@@ -1121,4 +1136,30 @@ public class NetworkControllerImpl extends BroadcastReceiverreturn config;}}
+    // 2022 add update dialog start
+    public boolean isNetworkAvailable(){
+        ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+        if (connectivityManager == null){
+            return false;
+        }
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
+            Network[] networks = connectivityManager.getAllNetworks();
+            NetworkInfo networkInfo;
+            for (Network network : networks){
+                networkInfo = connectivityManager.getNetworkInfo(network);
+                if (networkInfo.getState().equals(NetworkInfo.State.CONNECTED))
+                    return true;
+            }
+        }else {
+            NetworkInfo[] networkInfos = connectivityManager.getAllNetworkInfo();
+            for (NetworkInfo networkInfo : networkInfos) {
+                if (networkInfo.getState() == NetworkInfo.State.CONNECTED) {
+                    return true;
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+    // 2022 add update dialog end}

后面是新增的弹出 dialog 文件,逻辑很简单不作解释

CheckoutUpdateVersion.java

package com.android.systemui.update;import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.SystemProperties;
import android.util.Log;import org.json.JSONException;
import org.json.JSONObject;import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;public class CheckoutUpdateVersion {private final String TAG = "CheckoutUpdateVersion";Handler handler;public CheckoutUpdateVersion(Handler handler){this.handler = handler;}private static final String JSON_URL = "填写ota服务器url";public Boolean checkout(){new Thread(new Runnable() {@Overridepublic void run() {String jsonStr = getJsonString();String updateVersion = getVersionInfo(jsonStr);if(checkVersion(updateVersion)){Log.d(TAG,"has new version:"+updateVersion);Message msg = handler.obtainMessage();msg.what = 1;msg.obj = updateVersion;handler.sendMessage(msg);}}}).start();//checkVersion(getVersionInfo(getJsonString()));return true;}private String getJsonString(){StringBuffer buffer = new StringBuffer();HttpURLConnection httpUrlConnection = null;InputStream inputStream = null;BufferedReader bufferedReader = null;try {final String systemVersion = Build.VERSION.INCREMENTAL;final String systemDevice = SystemProperties.get("ro.product.device");final String customerId = SystemProperties.get("ro.build.version.customerid");
//            final String systemDevice = "mt5862_bga_1g";String urlstr = JSON_URL + "?" + "version=" + systemVersion + "&" + "device=" + systemDevice + "&customer=" + customerId; Log.d(TAG, urlstr);URL url = new URL(urlstr);httpUrlConnection = (HttpURLConnection) url.openConnection();httpUrlConnection.setRequestProperty("Content-Type", "text/json; charset=UTF-8");httpUrlConnection.connect();inputStream = httpUrlConnection.getInputStream();bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));String line = "";while ((line = bufferedReader.readLine()) != null) {buffer.append(line);}} catch (IOException e) {e.printStackTrace();} finally {try {if (httpUrlConnection != null)httpUrlConnection.disconnect();if (inputStream != null)inputStream.close();if (bufferedReader != null)bufferedReader.close();} catch (IOException e) {e.printStackTrace();}}return buffer.toString();}private String getVersionInfo(String jsonString) {String resultVersion = "";try{JSONObject jsonObject = new JSONObject(jsonString);resultVersion = jsonObject.getString("FW_VER");} catch (JSONException e) {e.printStackTrace();}return resultVersion;}private boolean checkVersion(String updateVersion){String ignoreUpdateVersion = file2String("/mnt/sdcard/Android/ignoreUpdateVersion");if (ignoreUpdateVersion.contains(updateVersion)){Log.d(TAG, "ignore");return false;}final String systemVersion = Build.VERSION.INCREMENTAL;if (systemVersion == null){return false;}if (updateVersion != null && systemVersion.contains(".")) {if (updateVersion.compareTo(systemVersion) > 0) {return true;} else {return false;}}return false;}private String file2String(String ignoreUpdateVersionFile) {String content="";File file = new File(ignoreUpdateVersionFile);if (!file.exists()) return "Unable to open file!";try {InputStream inputStream = new FileInputStream(file);if (inputStream != null){InputStreamReader reader = new InputStreamReader(inputStream,"GB2312");BufferedReader bufferedReader = new BufferedReader(reader);String line;while ((line = bufferedReader.readLine()) != null){content += line + "\n";}inputStream.close();}} catch (IOException e) {e.printStackTrace();}return content;}}

UpdateVersionDialogImpl.java

package com.android.systemui.update;import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.ColorDrawable;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import com.android.systemui.R;
import android.os.Environment;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import android.util.Log;
import android.os.Handler;
import android.os.Message;public class UpdateVersionDialogImpl {private CheckBox checkBox;private Button btnUpdate;private Button btnCancel;private TextView alertDialogTips;private final Context mContext;AlertDialog dialog;AlertDialog.Builder mbuilder;public UpdateVersionDialogImpl(Context context){mContext = context;}@SuppressLint("SdCardPath")private void show(String updateVersion){mbuilder = new AlertDialog.Builder(mContext);dialog = mbuilder.create();Window mWindow = dialog.getWindow();mWindow.requestFeature(Window.FEATURE_NO_TITLE);mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);mWindow.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);mWindow.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);final WindowManager.LayoutParams lp = mWindow.getAttributes();lp.format = PixelFormat.TRANSLUCENT;lp.windowAnimations = -1;mWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);mWindow.setBackgroundDrawableResource(R.drawable.dialog_background);dialog.setCanceledOnTouchOutside(true);mWindow.setAttributes(lp);dialog.show();//View view = LayoutInflater.from(mContext).inflate(R.layout.system_update_dialog, null);//TextView tvTitle = (TextView) view.findViewById(R.id.alert_dialog_title);dialog.setContentView(R.layout.system_update_dialog);btnUpdate = dialog.findViewById(R.id.alert_dialog_button_update);btnCancel = dialog.findViewById(R.id.alert_dialog_button_cancel);checkBox = dialog.findViewById(R.id.alert_dialog_checkBox);alertDialogTips = dialog.findViewById(R.id.alert_dialog_tips);//        dialog.show();btnUpdate.setOnClickListener((View v)->{Intent intent = new Intent();ComponentName comp = new ComponentName("com.android.tv.settings", "com.android.tv.settings.update.SystemNetUpdateActivity");intent.setComponent(comp);intent.putExtra("other", "true");intent.setAction("android.intent.action.VIEW");intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);mContext.startActivity(intent);dialog.dismiss();});btnCancel.setOnClickListener((View v)->{if (checkBox.isChecked()){//string2File("aaa","/data/user/ignoreUpdateVersion");string2File(updateVersion+"#","/mnt/sdcard/Android/ignoreUpdateVersion");}dialog.dismiss();});checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {if (isChecked){//选中btnUpdate.setEnabled(false);//alertDialogTips.setVisibility(View.VISIBLE);}else {//alertDialogTips.setVisibility(View.INVISIBLE);btnUpdate.setEnabled(true);}}});}private boolean string2File(String res, String filePath) {boolean flag = true;BufferedReader bufferedReader = null;BufferedWriter bufferedWriter = null;try {File distFile = new File(filePath);if (!distFile.getParentFile().exists()){distFile.getParentFile().mkdirs();}bufferedReader = new BufferedReader(new StringReader(res));bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(distFile, true)));char buf[] = new char[1024];int len;while ((len = bufferedReader.read(buf)) != -1) {bufferedWriter.write(buf, 0, len);}bufferedWriter.flush();bufferedReader.close();bufferedWriter.close();} catch (IOException e) {e.printStackTrace();flag = false;return flag;} finally {if (bufferedReader != null) {try {bufferedReader.close();} catch (IOException e) {e.printStackTrace();}}}return flag;}private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 1:String updateVersion = (String) msg.obj;show(updateVersion);break;default:break;}}};public Handler getHandler(){return handler;}
}

ComponentName comp = new ComponentName(“com.android.tv.settings”, “com.android.tv.settings.update.SystemNetUpdateActivity”);
是去调起系统的更新界面,也可以自己写服务后台下载升级,偷懒就直接调用系统的升级界面

dialog_background.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><solid android:color="#ffffff"/><strokeandroid:width="2dp"android:color="#ffffff" /><corners android:radius="30dp"/></shape>

system_update_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="2dp"><TextViewandroid:id="@+id/alert_dialog_title"android:layout_width="match_parent"android:layout_height="wrap_content"android:textColor="#000000"android:textSize="23sp"android:text="@string/system_update_dialog_title"android:paddingTop="20dp"android:paddingBottom="10dp"android:paddingLeft="30dp"/><TextViewandroid:id="@+id/alert_dialog_message"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#FFFFFF"android:textColor="#171718"android:textSize="18sp"android:paddingLeft="20dp"android:layout_marginTop="10dp"android:layout_marginBottom="10dp"android:text="@string/system_update_dialog_message"/><TextViewandroid:id="@+id/alert_dialog_tips"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#000000"android:text="将不会在收到这个版本的更新提示,可在设置中手动升级"android:layout_gravity="center"android:visibility="gone"/><CheckBoxandroid:id="@+id/alert_dialog_checkBox"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#000000"android:text="@string/system_update_dialog_ignore"android:checked="false"android:layout_gravity="right"android:layout_marginRight="30dp"/><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="2dp"android:gravity="right"android:layout_marginBottom="10dp"><Buttonandroid:id="@+id/alert_dialog_button_cancel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="20dp"android:text="@string/system_update_dialog_cancel" /><Buttonandroid:id="@+id/alert_dialog_button_update"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity= "center"android:text="@string/system_update_dialog_update"android:layout_marginRight="30dp"/></LinearLayout></LinearLayout>

字符串的国际化的修改

diff --git a/frameworks/base/packages/SystemUI/res/values/strings.xml b/frameworks/base/packages/SystemUI/res/values/strings.xml
old mode 100644
new mode 100755
index edf56af..9403469
--- a/frameworks/base/packages/SystemUI/res/values/strings.xml
+++ b/frameworks/base/packages/SystemUI/res/values/strings.xml
@@ -2243,4 +2243,12 @@app for debugging. Will not be seen by users. [CHAR LIMIT=20] --><string name="heap_dump_tile_name">Dump SysUI Heap</string>+
+    <!-- ota system update dialog -->
+    <string name="system_update_dialog_title">System Update</string>
+    <string name="system_update_dialog_message">A new version has been detected. Do you want to update it</string>
+    <string name="system_update_dialog_ignore">Ignore this version</string>
+    <string name="system_update_dialog_cancel">Cancel</string>
+    <string name="system_update_dialog_update">Update</string>
+    <!-- ota system update dialog --></resources>diff --git a/frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml b/frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml
old mode 100644
new mode 100755
index 3bf909b..a9b8b11
--- a/frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -854,4 +854,11 @@<string name="open_saver_setting_action" msgid="8314624730997322529">"设置"</string><string name="auto_saver_okay_action" msgid="2701221740227683650">"知道了"</string><string name="heap_dump_tile_name" msgid="9141031328971226374">"转储 SysUI 堆"</string>
+    <!-- ota system update dialog -->
+    <string name="system_update_dialog_title">系统更新</string>
+    <string name="system_update_dialog_message">检测到新版本,是否更新</string>
+    <string name="system_update_dialog_ignore">忽略此版本</string>
+    <string name="system_update_dialog_cancel">取消</string>
+    <string name="system_update_dialog_update">更新</string>
+    <!-- ota system update dialog --></resources>

注意,因为修改了AndroidManifest.xml 文件,单编过后复制到系统中时,需要将 oat 目录也一起复制过去,不然AndroidManifest.xml 文件没有替换,会报权限问题,至于单编systemui 编译不过这篇文章中有讲:https://blog.csdn.net/weixin_44128558/article/details/125396703

至此添加完成



记录:系统原生设置:
Settings\src\com\android\tv\settings\update\SystemNetUpdateActivity.java
从这个类的 onCreate 看起

 @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.system_net_update);findViews();        //初始化checkStorage();        //检查空间是否充足,主要检查/cache 文件夹的空间是否充足,不充足则使用其他外部存储的空间mCurrentProgress = 0;            //当前下载进度为0new Thread(new Runnable() {       //http 请求为耗时操作,要放到线程中,不然报错@Overridepublic void run() {getVersionInfo();      // 获得远程升级包信息,通过http请求,并将返回的信息保存到 mVersionInfo 对象中// check new versionhandler.sendEmptyMessage(CHECK_NEW_VERSION); //handler根据获得的版本号进行不同的逻辑显示}}).start();registerListeners();          //注册监听点击事件等}//获得远程升级版本信息private void getVersionInfo() {try {JSONObject jsonObject = new JSONObject(JSONData.getUpgradeInfo()); //http请求返回jason字符串mVersionInfo.setVersion(jsonObject.getString("FW_VER"));    //版本号mVersionInfo.setUrl(jsonObject.getString("FW_URL"));     //ota包下载URLmVersionInfo.setSize(jsonObject.getLong("size"));          //ota包大小,用于校验mVersionInfo.setMd5(jsonObject.getString("md5"));         //ota包的MD5值,用于校验} catch (JSONException e) {e.printStackTrace();handler.sendEmptyMessage(CHECK_VERSION_FAIL);}}

通过 getVersionInfo() 方法中的 JSONData.getUpgradeInfo();进行http请求,去获取服务器端的升级版本信息json字符串,并将相关的信息放到 mVersionInfo 对象中保存起来

Settings\src\com\android\tv\settings\update\JSONData.java

 private static final String JSON_URL = "ota服务器地址";private static String json_data = null;@SuppressLint("NewApi")private static String getJsonString(JSONObject json) {   //请求json字符串StringBuffer buffer = new StringBuffer();HttpURLConnection httpUrlConnection = null;InputStream inputStream = null;BufferedReader bufferedReader = null;try {final String systemVersion = Tools.getSystemVersion();final String systemDevice = SystemProperties.get("ro.product.device");            //获得版型final String customerId = SystemProperties.get("ro.build.version.customerid"); //获得客户idString urlstr = JSON_URL + "?" + "version=" + systemVersion + "&" + "device=" + systemDevice + "&customer=" + customerId;     //服务器根据传过来的systemVersion等信息查找相应的更新包,get方式传递参数给服务器URL url = new URL(urlstr);Log.d(TAG, "json url, " + urlstr);httpUrlConnection = (HttpURLConnection) url.openConnection();httpUrlConnection.setRequestProperty("Content-Type", "text/json; charset=UTF-8");httpUrlConnection.connect();Log.d(TAG, "response code, " + httpUrlConnection.getResponseCode());inputStream = httpUrlConnection.getInputStream();bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));String line = "";while ((line = bufferedReader.readLine()) != null) {buffer.append(line);}} catch (Exception e) {e.printStackTrace();} finally {try {if (httpUrlConnection != null) {httpUrlConnection.disconnect();}if (inputStream != null) {inputStream.close();}if (bufferedReader != null) {bufferedReader.close();}} catch (Exception e) {e.printStackTrace();}}Log.d(TAG, "buffer.toString, " + buffer.toString());return buffer.toString();}@SuppressLint("NewApi")public static String getUpgradeInfo() {if (json_data == null || json_data.isEmpty()){ //判断是否已经有保存的数据,避免重复请求JSONObject json = new JSONObject();json_data = getJsonString(json);             //通过http协议请求}return json_data;}

回到Settings\src\com\android\tv\settings\update\SystemNetUpdateActivity.java请求成功后oCreate会调用到下面的地方

 // Handlerprivate Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case CHECK_STORAGE:checkStorage();break;case CHECK_NEW_VERSION:        //检查新版本mHasNewVersion = checkUpdateVersion();if (mHasNewVersion) {         //当前系统版本为空或者有新版本,显示为 下载 按钮mUpdateInfo += getString(R.string.new_version) + mNewVersion + "\n";mUpdateInfoText.setText(mUpdateInfo);mUpdateButton.setText(getString(R.string.download));mUpdateButton.setEnabled(true);} else {                 //版本校验失败,显示你的系统版本已经是最新 显示为 退出 按钮mUpdateInfo += getString(R.string.latest) + "\n";mUpdateInfoText.setText(mUpdateInfo);mUpdateButton.setText(getString(R.string.exit));mUpdateButton.setEnabled(true);}break;case DOWNLOAD_ERROR:...default:break;}}};private void init() {String directoryName = "";mPackageSize = mVersionInfo.getSize();      //获得的升级包信息大小long cacheFreeSize = getCacheFreeSize();   //获得catch 文件夹大小if (cacheFreeSize > mPackageSize) {directoryName = "/cache/versioninfor";} else {      //获取根路径,优先外部存储directoryName = Environment.getExternalStorageDirectory().toString() + "/versioninfor";}Tools.string2File(JSONData.getUpgradeInfo(), directoryName);   //将升级json写到本地 /cache/versioninfor}private boolean checkUpdateVersion() {init();mNewVersion = mVersionInfo.getVersion();    // 获得升级的版本号mPackageSize = mVersionInfo.getSize();      //获得升级包大小mDownloadUrl = mVersionInfo.getUrl();         //获得下载的URLif (mDownloadUrl != null) {                  //通过SharedPreferences 存储升级信息commitURLValue(DOWNLOAD_ADDRESS, mDownloadUrl);commitURLValue(VERSION, mNewVersion);commitURLValue(PACKAGE_SIZE, String.valueOf(mPackageSize));}return checkVersion();}private boolean checkVersion() {final String systemVersion = Tools.getSystemVersion();  //获取本机及其的内部版本号,Build.VERSION.INCREMENTAL;if (systemVersion == null) {  //当前版本为空,请求的时候会传递过去,在服务器端处理,应该是下载默认的应用mHasNewVersion = true;return mHasNewVersion;}if (systemVersion.equals(mNewVersion)) {   //两个版本相同,显示已经是最新的版本mHasNewVersion = false;return mHasNewVersion;}if (mNewVersion != null && systemVersion.contains(".")) { //判断版本大小,要大于当前版本if (mNewVersion.compareTo(systemVersion) > 0) {mHasNewVersion = true;} else {mHasNewVersion = false;}}Log.d(TAG, "mHasNewVersion, " + mHasNewVersion);return mHasNewVersion;}private void commitURLValue(String key, String value) {SharedPreferences preference = getSharedPreferences(NAME, Context.MODE_PRIVATE);Editor edit = preference.edit();edit.putString(key, value);edit.commit();}

到这里http请求服务器查看有没有版本更新的代码就完成了,如果有新版本,按钮显示Download,没有新版本则提示已经是最新版本,按钮显示Exit

 private void registerListeners() {mUpdateButton.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if (mHasNewVersion) { //是否有新版本if (!isNetConnected()) { //网络是否连接Toast.makeText(SystemNetUpdateActivity.this,getString(R.string.not_network), Toast.LENGTH_SHORT).show();return;}mUpdateInfo += getString(R.string.downloading) + "\n"; //Downloading new version......mUpdateInfoText.setText(mUpdateInfo);mLayout.setVisibility(View.VISIBLE); //显示下载进度Log.d(TAG, "downUrl, " + mVersionInfo.getUrl());Log.d(TAG, "newVersion, " + mVersionInfo.getVersion());Log.d(TAG, "size, " + mVersionInfo.getSize());Intent intent = new Intent(SystemNetUpdateActivity.this, UpdateService.class);Bundle bundle = new Bundle();bundle.putString("downUrl", mDownloadUrl);                //传递下载的信息bundle.putString("newVersion", mNewVersion);bundle.putString("size", String.valueOf(mPackageSize));intent.putExtras(bundle);SystemNetUpdateActivity.this.startServiceAsUser(intent, UserHandle.CURRENT);//开启下载服务mUpdateButton.setEnabled(false); //设置按钮不能点击mUpdateButton.setText(getString(R.string.download_ing)); //Downloading} else if (mHasDownloaded) { //是否已经下载完成mUpdateInfo += getString(R.string.check_package);mUpdateInfoText.setText(mUpdateInfo);mHasDownloaded = false;mLayout.setVisibility(View.VISIBLE);      mUpdateButton.setEnabled(false);isUpdating = true;      //表示正在更新new UpdateSystemThread().start();       //开启线程,更新系统} else {finish();   //退出应用}}});}

如果有新版本,当点击按钮的时候就会开启一个下载服务在后台下载,SystemNetUpdateActivity.this.startServiceAsUser(intent, UserHandle.CURRENT);
Settings\src\com\android\tv\settings\update\UpdateService.java

public class UpdateService extends Service {private Handler mHandler = new Handler() {public void handleMessage(android.os.Message msg) {super.handleMessage(msg);Log.d(TAG, "mHandler msg " + msg.what);if (msg.what <= 100) {if (msg.what == 0) { // 准备下载mNotification.contentView = mRemoteViews;mNotification.contentIntent = mPendingIntent;mNotificationManager.notify(DOWNLOADING, mNotification);}if (msg.what == 100) { //下载完成commitPercentValue(PERCENT, 100);mNotificationManager.cancel(DOWNLOADING);mNotification.flags |= Notification.FLAG_AUTO_CANCEL;showNotification(R.drawable.appwidget_bg_holo, R.string.downloading, msg.what);}mRemoteViews.setTextViewText(R.id.task_percent, msg.what + "%");mRemoteViews.setProgressBar(R.id.task_progressbar, 100, msg.what, false);sendPercentData();  //发送广播通知ui下载进度}mNotification.contentView = mRemoteViews;mNotification.contentIntent = mPendingIntent;mNotificationManager.notify(DOWNLOADING, mNotification); //刷新通知显示};};//下载错误时private Handler mErrorHandler = new Handler() {public void handleMessage(Message msg) {super.handleMessage(msg);if (msg.what == DOWNLOAD_ERROR) {commitPercentValue(PERCENT, mDownloadPercent);onUpdateError(ERROR_DOWNLOAD); //此方法也是发送广播,通知ui下载异常}};};@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); mDownloadPercent = 0; //下载百分比showNotification(R.drawable.appwidget_bg_holo, R.string.downloading, mDownloadPercent);//定义通知,开启前台服务Message msg = mHandler.obtainMessage();     msg.what = mDownloadPercent;mHandler.sendMessage(msg);     // 发送handler DownloadPercent = 0 在handler中做一些初始化}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {mDownloadUrl = intent.getStringExtra("downUrl");   //获得传递过来的下载版本信息mNewVersion = intent.getStringExtra("newVersion");mSize = intent.getStringExtra("size");Log.d(TAG, "UpdateService-downUrl, " + mDownloadUrl);Log.d(TAG, "UpdateService-newVersion, " + mNewVersion);Log.d(TAG, "UpdateService-mSize, " + mSize);startDownload();  //开始下载return super.onStartCommand(intent, flags, startId);}/*** start download the update package.*/private void startDownload() {String directoryName = "";long cacheFreeSize = getCacheFreeSize(); //获得cache目录剩余空间大小if (cacheFreeSize > Long.parseLong(mSize)) {   //判断下载的文件放到哪个位置directoryName = "/cache/update_signed.zip";} else {directoryName = Environment.getExternalStorageDirectory().toString()+ "/update_signed.zip";}// if ota upgrade package exited, delete itFile f = new File(directoryName);if (f.exists()) {f.delete();}// 下载监听 监听下载进度IDownloadProgressListener downloadProgressListener = new IDownloadProgressListener() {@Overridepublic void onDownloadSizeChange(int percent) {mDownloadPercent = percent;Log.d(TAG, "percent:" + percent);Message msg = mHandler.obtainMessage();msg.what = percent;mHandler.sendMessage(msg);}};//UpgradeTask 实现 RunnableUpgradeTask upgradeTask = new UpgradeTask(UpdateService.this, mDownloadUrl, directoryName,mNewVersion, downloadProgressListener, mErrorHandler);new Thread(upgradeTask).start(); //开启任务线程下载}
}

Settings\src\com\android\tv\settings\update\UpgradeTask.java

public class UpgradeTask implements Runnable {@Overridepublic void run() {prepare(); //准备 获得相关信息,下载地址版本和大小int count = 20;int loop = 0;int res = -1;while(loop < count) //尝试20次下载{res = download();    //开始下载if (res == -1) {Log.d(TAG, "download failed");mHandler.sendEmptyMessage(DOWNLOAD_ERROR);return;} else if ( res == -2) {loop++;Log.d(TAG, "download except, retry...");continue;} else {return;}}};private void prepare() {File file = new File(mLocalPath);if (!file.getParentFile().exists()) { //创建文件夹file.getParentFile().mkdirs();}String versionString = getStringData(VERSION); //获得要下载版本if (versionString.equals(mVersion)) {mUpgradeURL = getStringData(DOWNLOAD_ADDRESS);mTotalSize = Long.parseLong(getStringData(PACKAGE_SIZE));} else {Log.d(TAG, "delete file");file.delete();}}/** @see* com.jrm.core.container.cmps.upgrade.task.BaseUpgradeTask#onDownload()*/protected int download() {File file = new File(mLocalPath);if (file.exists()) { //判断下载的文件是否存在mDownloadedSize = file.length();} else {mDownloadedSize = 0;}// check package whether be downloadedif (mDownloadedSize == mTotalSize && this.mDownloadProgressListener != null) { //对比两个文件大小,一样表示已经下载过,无需重新下载mDownloadProgressListener.onDownloadSizeChange(100); //回调下载进度100%return 0;} else if (mDownloadedSize > mTotalSize) {if (!file.delete()) {return -1;}}Log.d(TAG, "==> mUpgradeURL, " + mUpgradeURL + " downloadedSize, " + mDownloadedSize);HttpURLConnection httpConnection = null;URL url = null;BufferedInputStream binStream = null;BufferedOutputStream boutStream = null;try {url = new URL(mUpgradeURL);httpConnection = (HttpURLConnection) url.openConnection();httpConnection.setRequestMethod("GET");httpConnection.setRequestProperty("Range", "bytes=" + mDownloadedSize + "-");httpConnection.setRequestProperty("Connection", "close");httpConnection.setReadTimeout(10*1000);httpConnection.connect();Log.d(TAG, "response code, " + httpConnection.getResponseCode());binStream = new BufferedInputStream(httpConnection.getInputStream());boutStream = new BufferedOutputStream(new FileOutputStream(mLocalPath, true));int offset = 0;int count = 0;int perUnit = (int) mTotalSize / 8192 / 100;byte[] buffer = new byte[8192];while ((offset = binStream.read(buffer, 0, 8192)) != -1) {boutStream.write(buffer, 0, offset);count++;if (count == perUnit && mDownloadedSize < mTotalSize) {mDownloadPercent = (int) (mDownloadedSize * 100 / mTotalSize);if (this.mDownloadProgressListener != null) {mDownloadProgressListener.onDownloadSizeChange(mDownloadPercent);}count = 0;}mDownloadedSize += offset;}if (mDownloadedSize == mTotalSize && this.mDownloadProgressListener != null) {mDownloadProgressListener.onDownloadSizeChange(100);Log.d(TAG, "download finished.");return 0;} else {Log.d(TAG, "download error.");return -2;}} catch (Exception e) {e.printStackTrace();return -2;} finally {try {if (binStream != null) {binStream.close();}if (httpConnection != null) {httpConnection.disconnect();}if (boutStream != null) {boutStream.close();}} catch (Exception e) {e.printStackTrace();}}}
}

到这里,下载完成后会通知SystemNetUpdateActivity.java 下载的进度为100%,SystemNetUpdateActivity.java会更新ui,将button显示的字符更改为update,当用户点击按钮时,就 new UpdateSystemThread().start(); 去更新系统

Android 9 第一次开机联网检测系统升级相关推荐

  1. 树莓派4B与Android之缘——树莓派下LineageOS(Android 9)系统开机联网与远程控制

    一.树莓派连接屏幕 1.找到树莓派的micro hdmi口,是视频图像的输出口,见下图中的MICRO HDMI PORTS 2.连接屏幕 (1)如果显示屏输入端口是HDMI,就用micro HDMI到 ...

  2. Android开机启动检测和连接wifi检测

    Android启动时,会发出一个系统广播 ACTION_BOOT_COMPLETED,它的字符串常量表示为 "android.intent.action.BOOT_COMPLETED&quo ...

  3. android 如何使得电阻屏在第一次开机时自动叫起屏幕校准程序

    Android系统中有一个Provision程序,只会在第一次开机时运行一次,它会将Settings.Secure.DEVICE_PROVISIONED的值设置为1,随后就把自己disable掉 ,那 ...

  4. (安卓/android)第一次开机扫描过程分析与第一次启动速度优化

    第一次开机扫描过程分析与第一次启动速度优化 第一次开机扫描过程分析 1.PackageMangerService的启动 不是本篇主要内容,简要了解即可 2.指定以下几个目录进行扫描 /data/dat ...

  5. 原生Android系统的第一次开机google验证的解决

    网络访问问题 作为Android系统开发者,编译AOSP是无法避免的,下载Nexus系列的AOSP image来使用也是无法避免的.如果是我们自己编译AOSP的话,我们可以选择eng版本,从而省去这些 ...

  6. 这篇文章适合所有Android手机第一次买Android手机的可以看看!(ZT)

    这篇文章适合所有Android手机第一次买Android手机的可以看看!(ZT) 18小时前 [b]这篇文章适合所有[/b][b]Android[/b][b]手机[/b][b]第一次买[/b][b]A ...

  7. Android判断当前的android设备是否处于联网状态

    2019独角兽企业重金招聘Python工程师标准>>> 首先,要想获得当前android设备是否处于联网状态,那么android本身给我们提供了一个服务 private Connec ...

  8. vbreport8.wpf.viewer 个别电脑不显示_【电脑手机小技巧】新买的电脑,第一次开机最好要这样设置...

    今年双11不少电脑的优惠幅度都很大,对于已经买了电脑的小伙伴来说,后面会陆陆续续收到电脑.入手新电脑的新手朋友,在收到电脑时肯定会有各种疑问,比如如何完成Windows初始配置.如何激活Windows ...

  9. Android Studio第一次安装遇见的问题汇总

    1.Android Studio启动时出现unable to access android sdk add-on list 1. 错误信息: 第一次安装完AS,出现这个错误提示 unable to a ...

最新文章

  1. IOS中CoreLocation框架地理定位
  2. 23个CVPR 2020收录的新数据集,都在这里了!
  3. ETH网络要爆炸,未来Token的最佳选择注定是BCH
  4. 作为Leader如何与团队成员更好地沟通?
  5. 【开源】WeChatRobot+WeChatHelper 制作自己的微信机器人
  6. VTK:图像梯度幅度用法实战
  7. C语言中的各输出格式含义
  8. hdu5831 Rikka with Parenthesis II
  9. 改变libreoffice的writer背景颜色
  10. 三角形面积=SQRT(S*(S-a)*(S-b)*(S-c)) 其中S=(a+b+c)/2,a、b、c为三角形的三边。 定义两个带参的宏,一个用来求area, 另一个宏用来求S。 写程序,在程序中用带
  11. spark 如何用netty实现akka的actor模型
  12. 学以致用一 安装centos7.2虚拟机
  13. 内部收益率计算公式用计算机,用excel怎么计算内部收益率?
  14. 宽带经常掉线应如何解决
  15. python学习之路之:import(详细介绍import的各种调用原理和使用方法)
  16. 如何学好图像处理——从小白到大神?
  17. 1100 1149C语言答案,C语言程序设计(何钦铭)课后习题作业
  18. java计算工作日_Java工作日计算工具类
  19. 关于node链接数据库Handshake inactivity timeout
  20. 审计风险控制流程的起点_审计过程中如何理解风险评估程序和内部控制测试?...

热门文章

  1. ClientDisconnectionReason(客户端断开原因)
  2. [ERROR] 两个jar包中存在Qualified Name完全相同的引用冲突问题 解决方案
  3. 基于深度学习的火焰检测系统(YOLOv5清新界面版,Python代码)
  4. 基于自适应反步法的三自由度直升机(3 DOF Helicopter)轨迹跟踪
  5. 办公神器再升级:钉钉电话秒变客服中心,钉邮域名自定义
  6. win10qt5.14.2下opencv4.4.0+contrib的mingw32编译
  7. 2022年四川建筑八大员(土建施工员)考试试题及答案
  8. 问题 F: 【递归入门】走迷宫
  9. Unity | 什么是委托?
  10. 反编译.net下的exe程序