Project Combat: Ota system upgrade

Source: Internet
Author: User


a summary of the previous OTA system upgrade project, including 4 parts: Introduction of OTA systems, OTA package production, code structure and issues to be improved.


1. Ota Introduction:

& Nbsp;     OTA full name over the air,   ota  upgrade is  android  Standard software upgrade methods provided by the system.   It is powerful and provides a fully upgraded, incremental upgrade mode that can be passed  SD  Card upgrades can also be upgraded via the network. In the system upgrade, the main thing is to compile the local full package and differential packet, put to the server for the user to choose.


2. The production of OTA package :

The complete package is the mutation of the entire system generated OTA package, the size may be around hundreds of m, but it is more stable than the OTA differential packet, the difference packet volume is relatively small, upgrade is more convenient, this depends on the user's own choice. Under Linux, the complete package is generated by: make clean; Make Make otapackage; A ZIP package will then be generated at Out/target/product/torsby: Vargo_torsby-ota.zip, which is a complete package that can be upgraded directly. At the same time, it also generates a package to compile the differential packet in the Out/target/product/torsby/obj/packaging/target_files_intermediates directory. We can first rename to Old.zip, and then the second package named New.zip, then we can generate a differential packet, in the Build/tools/releasetools directory, there is a ota_from_target_files system comes with a script, Under Linux:./build/tools/releasetools/ota_from_target_files-i ~/old.zip ~/new.zip ~/update.zip, Will generate the Update.zip differential packet in the current directory, note to put two OTA packages in the current directory to execute this command. Then the Update.zip differential packet here must be upgraded on Old.zip this system in order to new.zip this version.


3. Project structure:

The whole purpose of the function is that the user from the setup into the system upgrade, will automatically request the server to check if there is a version needs to be updated, if not go to a prompt interface: Your system is up to date! If it is not the latest system, then the interface will display the current system version number and the latest system version number, as well as more version of the update log, the user click Install Now will go to a version of the list, above the server returned all the finer version, select a version to install the update.

the core class of code is Iradarupdatesystemfragment . class, which he inherits from Preferencefragment to keep in sync with the UI design for setting up settings, and then it belongs to Iradarupdatesystemactivity, So the real code implementation is in this fragment. In the OnCreate () method, the initial initialization of actionbar and preference, followed by the use of the company's own encapsulated network framework Requestmanager to request the server to obtain the latest version, here to note: Before using Requestmanager to request a server, initialize it first:

Options opts = new Options.builder (). Enablenet (). Enablepush (). build ();     Vargohelper.init (this,opts);

I put this initialization in the custom otaapplication, but for the sake of insurance is still waiting for a period of time after initialization in the call Requestmanager request method, so with handler to control the timing of execution, 300ms and then request. The entire request process uses JSON to pass the data, the request parameter is Getdevicedata () to obtain, mainly is the current version number and the current machine's DeviceID, Requestmanager's use no longer describes uses the size function number to request the server, Binding Responselistener at the same time to get the results of the request, in onreceived () to get response is the result we want, and in a few other methods is some error return, etc., we can also give some UI hints. The point here is this: Requestmanager has been specially handled, can be called directly in the UI thread, and can be updated directly in the results UI, I did not use handler. Responsecode This parameter is to distinguish whether there is a version update, if there is an update, the results will be uploaded to Updatepreference () to update our interface .

Here is another is "learn more" this preference, is used to look at the update log: Click to jump to Updatelogactivity, he is a window activity implementation, with Webview.loadurl () method to load a copy of the update log.

Then after the interface update is complete, if the current version can be updated, the user click on the installation will pop up a version of the list, before there will be a WiFi and battery judgment, we have to be connected to the WiFi and power is not less than 50% to continue to update, check the WiFi is open code:

Checks whether the current network is Wifiprivate Boolean iswifinet () {Connectivitymanager ConnectionManager = (Connectivitymanager) Context.getsystemservice (context. Connectivity_service);   Networkinfo networkinfo = Connectionmanager.getactivenetworkinfo (); if (Networkinfo==null) {return false;} else{String netstate = Networkinfo.gettypename (), if (Netstate.equals ("WIFI")) { C2/>return true; } else return false; }}

Check that the current charge is less than 50% of the code:


here is a point: the general way to get power is to bind a broadcast, when the power changes will be received action_battery_changed system broadcast, but the problem is that there is no immediacy, the user click on the button should be acquired to broadcast, So use the above method: in the Android system this file "/sys/class/power_supply/battery/capacity" actually stored the current charge, directly new file () read it out!

When the power and WiFi are met, you can start downloading the installation system version. Download this piece I use the system comes with the Downloadmanager framework, Android native system is used in this framework, has already encapsulated the notification bar, the function is very perfect, the following details Downloadmanager in this project usage:

Downloadmanager is a download management class, obtained in OnCreate ():.

Manger= (Downloadmanager) getactivity (). Getsystemservice (context. Download_service);

downloadmanager.request is a download task, we can set some of the download parameters, such as: Notification bar is visible, network qualification, download directory and so on, set up and then call the Downloadmanager.enqueue method to start the download, it returns a ID is the ID of the current download task, so it supports multi-tasking! As you can see in the following code, this ID is set to the global variable, which can be used to query the current download progress:

Downloadmanager.request down=new downloadmanager.request (uri.parse (URL)); Down.addrequestheader (header, value); Down.setnotificationvisibility (Android.app.DownloadManager.Request.VISIBILITY_VISIBLE); Down.setallowednetworktypes (DownloadManager.Request.NETWORK_WIFI); Down.settitle (Getactivity (). Getresources (). getString (R.string.down_title)); if (GetFile (otaconstant.romname). Exists ()) {Boolean isdelete =  getFile (otaconstant.romname). Delete (); LOG.D (Log_tag, "original update.zip delete?>>>>>>>" + isdelete); } down.setdestinationinexternalpublicdir (Environment.directory_downloads, otaconstant.romname); Downloadid = Manger.enqueue (down); Sharedpreferences sharedpreferences = getactivity (). Getsharedpreferences ("Ota", context.mode_private); The private Data Editor editor = Sharedpreferences.edit ();//Get Editor Editor.putlong ("Downloadid", Downloadid); Editor.commit ();//Submit Changes

actually started to download here, but to update our progress bar, listening to the download progress of an ID, is to use Contentresolver () to listen to a system URI, remember to OnDestroy () to unbind! :

Context.getcontentresolver (). Registercontentobserver (Uri.parse ("Content://downloads/my_downloads"), True, Downloadobserver);

Listen for download progress class Downloadchangeobserver extends Contentobserver {public downloadchangeobserver () {super (handler);} @Overridepublic void OnChange (Boolean selfchange) {Updateview (); LOG.D (Log_tag, "the supervisor hears the download");}} public void Updateview () {sharedpreferences sharedpreferences = getactivity (). Getsharedpreferences ("Ota", Context.mode_private); Downloadid = Sharedpreferences.getlong ("Downloadid", -1l); LOG.D (Log_tag, "re-enter OTA continue to download id>>>>>>>" +downloadid); if (downloadid!=-1) {int[] Bytesandstatus = Getbytesandstatus (Downloadid); Handler.sendmessage (Handler.obtainmessage (0,bytesandstatus));}} Public int[] Getbytesandstatus (long Downloadid) {int[] bytesandstatus = new int[] {-1,-1, 0, 0};D ownloadmanager.query qu ery = new Downloadmanager.query (). Setfilterbyid (Downloadid); Cursor C = null;try {c = manger.query (query); if (c! = null && C.movetofirst ()) {Bytesandstatus[0] = C.getint (c.get Columnindexorthrow (Downloadmanager.column_bytes_downloaded_so_far)); Bytesandstatus[1] = C.getINT (C.getcolumnindexorthrow (downloadmanager.column_total_size_bytes)); bytesandstatus[2] = C.getInt ( C.getcolumnindex (Downloadmanager.column_status)); Bytesandstatus[3] = C.getint (C.getcolumnindex ( Downloadmanager.column_reason)); LOG.D (Log_tag, "column_status>>>>>>>>>" +bytesandstatus[2] + "COLUMN_REASON>>> >>>>>> "+bytesandstatus[3]);}} finally {if (c! = null) {C.close ();}} return bytesandstatus;}

    In the above code can be seen in the download process to put some download information such as: Download start, pause, downloading ... The current download size, total size, and so on, are emitted with handler to update the UI. Here's the problem, I'm not sure. Download status Downloadmanager.column_status in the pause and failure will be triggered, and sometimes in the download I directly disconnect the gateway machine, and then boot he can continue to download, sometimes he directly prompts the download failed, will not continue to download, I haven't been able to take full control of it yet. There is also a support for the continuation of the breakpoint, but I did not find how to manually pause, only in some cases it itself paused!

Also to deal with is the background download, even if the shutdown restart, I re-enter the software, the progress bar to be able to continue the current download to display. So I started the download immediately with sharedpreferences saved ID, and before the beginning of a download to clear the ID, after the next entry to determine whether the ID has a value: there is a description is being downloaded, no value (in fact, the code to the 1 default value) is a new download. This is the entire download process, in practice, the basic can be downloaded smoothly. After completion will see in the SD Card dowmload folder update.zip This update package, installation method:

Perform the install update package private void Installrom () {//comparison to MD5 to determine the integrity of the   ROM log.d (Log_tag, "The MD5 of the downloaded file is >>>>>>> >>   "+utils.getfilemd5 (GetFile (otaconstant.romname)); Sharedpreferences sp = context.getsharedpreferences ("Ota", 0); String romMd5 = sp.getstring ("MD5", "" "); LOG.D (Log_tag, "server given MD5 is >>>>>>>>>   " +rommd5); if (Utils.getfilemd5 (GetFile ( Otaconstant.romname)). Equalsignorecase (ROMMD5)) {try {recoverysystem.installpackage (context, GetFile ( Otaconstant.romname));} catch (IOException e) {//TODO auto-generated catch Blocke.printstacktrace ();}   } else{Toast.maketext (Getactivity (), getactivity (). Getresources (). getString (R.string.system_broken), 1). Show (); Getactivity (). Finish (); } if (Startinstall!=null) {Startinstall.dismiss ();}  }

The above code, in fact, before the installation of a package MD5 verification, download the installation package must and the server to my information consistent, to install otherwise the file is damaged, need to download again!  Install the OTA package at the heart of this sentence: Recoverysystem.installpackage (context, GetFile (otaconstant.romname)); Its process is not detailed understanding, the process is also not controllable, installation if the problem should be the installation package itself, there is a common error is: The prompt can not find the SD card mount path! This is generally a system recovery problem, to re-brush a recovery, about this detailed implementation of the process is not in-depth understanding.

The problem with OTAs is that we can't expect users to wait for the download at the current interface to complete the installation, which is likely to be done in the background, so the installation must be placed inside the service, which is the Installservice class in the code. However, the following practice tells me that simply putting the installation on the service is not enough, because in the download process may fail, must give the failure prompt, so the entire download process should be placed in the service, this is not considered clear at that time, Then actually fragment inside actually does not need tube to download and installs, this part of code has not been streamlined. There is also a manual installation and automatic installation, the project requirements are downloaded after the completion of 15 automatic installation, or users directly click Install immediately, this part with handler control it, plus a flag labeled manual automatic, Do not allow two installations to proceed. The following is an implementation of a custom notification bar that failed to download:

<pre name= "code" class= "java" >private void Shwonotify (context context) {LOG.D (Log_tag, "Start show a status bar"); Mnotificationmanager = (Notificationmanager) getsystemservice (Context.notification_service); Remoteviews view_custom = new Remoteviews (Getpackagename (), r.layout.view_custom); View_custom.setimageviewresource ( R.id.custom_icon, r.drawable.update); View_custom.settextviewtext (R.id.tv_custom_title, Context.getResources (). GetString (r.string.service_prompt)); View_custom.settextviewtext (R.id.tv_custom_content, Context.getresources (). GetString (R.string.system_broken)); mbuilder = new Builder (this); Mbuilder.setcontent (View_custom). Setwhen ( System.currenttimemillis ()). Setcontentintent (Getdefalutintent (Notification.flag_auto_cancel)). SetWhen ( System.currenttimemillis ())//.setticker (Context.getresources (). getString (R.string.service_prompt)). setPriority (Notification.priority_default)//. Setongoing (False)//.setsmallicon (r.drawable.update); Notification notify = Mbuilder.build (); Notify.contentview= View_custom;mnotificationmanager.notify (Notifyid, notify);  LOG.D (Log_tag, "End show a status bar"); Public pendingintent getdefalutintent (int flags) {Intent Intent = new Intent (); Intent.setclassname ("Cn.com.vargo.ota", "Cn.com.vargo.ota.IradarUpdateSystemActivity"); Pendingintent pendingintent= pendingintent.getactivity (this, 1, intent, flags); return pendingintent;}


finally attach utils inside two tools, one is to get the file of the MD5, one is to get the MAC address of the machine:

public class Utils {/** * calculates the MD5 * @param file * @return */public static String getFileMD5 (file file) {if (!FILE.ISFI  Le ()) {return "";  } MessageDigest digest = null;  FileInputStream in = null;  byte buffer[] = new byte[1024];  int Len;   try {digest = messagedigest.getinstance ("MD5");   in = new FileInputStream (file);   while (len = in.read (buffer, 0, 1024x768)! =-1) {digest.update (buffer, 0, Len);  } in.close ();   } catch (Exception e) {e.printstacktrace ();  return null;  } BigInteger bigInt = new BigInteger (1, Digest.digest ()); return bigint.tostring (+). toUpperCase ();               }/** *//Get MAC Address: * @param context * @return */public static String getmacaddress (context context) {        String macAddress = "000000000000";            try {Wifimanager wifimgr = (wifimanager) context. Getsystemservice (Context.wifi_service);         Wifiinfo info = (Null = = Wifimgr? null:wifimgr. Getconnectioninfo ());   if (null! = info) {if (!                Textutils.isempty (Info.getmacaddress ())) macAddress = Info.getmacaddress (). Replace (":", "");            else return macAddress;            }} catch (Exception e) {//TODO auto-generated catch block E.printstacktrace ();        return macAddress;    } return macAddress; }}


4. Pending resolution:

as summarized in the above description, there are several issues to be perfected:

The first one is that Downloadmanager supports the continuation of a breakpoint, but does not know how to manually pause it. It is not certain that it gives pause or failure in the case of divine horse.

The second is that the OTA package installation process did not go into the study, and the download and installation should all be removed from the fragment only on the service.


Project Combat: Ota system upgrade

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.