1. Design ideas, use Versioncode definition for version upgrade parameters.
Android provides 2 properties for our defined version:
Copy Code code as follows:
<manifest package= "Com.cnblogs.tianxia.subway"
Android:versioncode= "1" <!--integer type, the system is not displayed to the user-->
Android:versionname= "1.0" <!--string type, System displays user-->
></manifest>
Google recommends that we use Versioncode to indicate a version upgrade, whether large or small, and Versionname is a software version that displays the user's view and is used as a display. So we chose Versioncode as our parameter to define the version upgrade.
2. Engineering Catalogue
In order to real project or enterprise application has the actual combat guidance function, I simulate an independent project, the engineering directory set up some reasonable rigorous some, not just a demo.
Suppose we take the Shanghai Metro as the project, named "Subway", the engineering structure is as follows,
3. Version initialization and version number comparison.
First define the variables localversion and serverversion in the global file Global.java to store the local version number and the server version number respectively.
Copy Code code as follows:
public class Global {
Version information
public static int localversion = 0;
public static int serverversion = 0;
public static String Downloaddir = "app/download/";
}
Because this article only focuses on updating updates, in order to prevent too many other extraneous code redundancy, I directly define the method Initglobal () method in Subwayapplication.
Copy Code code as follows:
/**
* Initialize global variables
* The actual work in this method serverversion from the server side, preferably in the start of the activity of the screen execution
*/
public void Initglobal () {
try{
Global.localversion = Getpackagemanager (). Getpackageinfo (Getpackagename (), 0). Versioncode; Set Local version number
Global.serverversion = 1;//assumes server version is 2, local version defaults to 1
}catch (Exception ex) {
Ex.printstacktrace ();
}
}
If a new release is detected and the user is prompted to update, I have defined the Checkversion () method in subwayactivity:
Copy code code as follows:
/**
* Check update version
/
public void Checkversion () {
if (glo Bal.localversion < Global.serverversion) {
//discovery of new versions, prompting users to update
Alertdialog.builder alert = new Alertdialog.builder (this);
Alert.settitle ("Software Upgrade")
. Setmessage ("Discovery of new versions, recommended for immediate updating.")
. Setpositivebutton (update), new Dialoginterface.onclicklistener () {
public void OnClick (Dialoginterface dialog, int which) {
//Open update Service Updateservice
//Here to make the update more modular, you can pass some updateservice dependent values
//such as layout IDs, resource IDs, dynamically fetched headers, Here take App_name for example
Intent updateintent =new Intent (Subwayactivity.this, updateservice.class);
Updateintent.putextra ("TitleID", r.string.app_name);
StartService (updateintent);
}
})
. Setnegativebutton (cancel), new Dialoginterface.onclicklistener () {
public void OnClick ( Dialoginterface dialog, int which) {
Dialog.dismiss ();
}
});
Alert.create (). Show ();
}else{
//cleanup work, omit
//cheanupdatefile (), post the article I will enclose the code
}
}
Okay, now we're going to string these things up:
The first step executes the Initglobal () initialization version variable in the Subwayapplication OnCreate () method.
Copy Code code as follows:
public void OnCreate () {
Super.oncreate ();
Initglobal ();
}
The second step detects version update checkversion () in the Subwayactivity OnCreate () method.
Copy Code code as follows:
public void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
Setcontentview (R.layout.main);
Checkversion ();
Now that the entrance is open, it is shown in line 18th of the Checkversion method that when the user clicks on the update, we turn on the update service and download the latest version from the server.
4. Use service in the background to download from the server, after completion prompts the user to download the completed, and close the service.
Define a service Updateservice.java, first defining variables related to download and notification:
Copy Code code as follows:
Title
private int titleid = 0;
File storage
Private File updatedir = null;
Private File updatefile = null;
Notification Bar
Private Notificationmanager Updatenotificationmanager = null;
Private Notification updatenotification = null;
Notification Bar Jump Intent
Private Intent updateintent = null;
Private pendingintent updatependingintent = null;
In the Onstartcommand () method, prepare the related download work:
Copy Code code as follows:
@Override
public int Onstartcommand (Intent Intent, int flags, int startid) {
Get the Pass value
TitleID = Intent.getintextra ("TitleID", 0);
Create a file
if (Android.os.Environment.MEDIA_MOUNTED.equals (Android.os.Environment.getExternalStorageState ())) {
Updatedir = new File (Environment.getexternalstoragedirectory (), global.downloaddir);
Updatefile = new File (Updatedir.getpath (), Getresources (). getString (TitleID) + ". apk");
}
This.updatenotificationmanager = (Notificationmanager) getsystemservice (Notification_service);
This.updatenotification = new Notification ();
Set up the download process, click on the notification bar, back to the main interface
Updateintent = new Intent (this, subwayactivity.class);
Updatependingintent = pendingintent.getactivity (this,0,updateintent,0);
Set the notification bar display content
Updatenotification.icon = r.drawable.arrow_down_float;
Updatenotification.tickertext = "Start Download";
Updatenotification.setlatesteventinfo (This, "Shanghai Subway", "0%", updatependingintent);
Give notice
Updatenotificationmanager.notify (0,updatenotification);
Open a new thread download, if using the service synchronous download, can cause ANR problem, the service itself will block
New Thread (New Updaterunnable ()). Start ()//This is the focus of the download, is the process of downloading
Return Super.onstartcommand (Intent, flags, Startid);
}
It's all about prep work.
As you can see from the code, the Updaterunnable class is the real download class, and for the sake of user experience, this class is performed by a single thread backstage.
The download process has two jobs: 1. Download data from the server; 2. Notifies the user of the progress of the downloads.
Thread notification, we first define an empty updatehandler.
[/code]
Private Handler Updatehandler = new Handler () {
@Override
public void Handlemessage (msg) {
}
};
[/code]
To create a true implementation of the Updaterunnable class:
Copy Code code as follows:
Class Updaterunnable implements Runnable {
Message message = Updatehandler.obtainmessage ();
public void Run () {
Message.what = Download_complete;
try{
Add Permissions <uses-permission android:name= "Android.permission.WRITE_EXTERNAL_STORAGE" >;
if (!updatedir.exists ()) {
Updatedir.mkdirs ();
}
if (!updatefile.exists ()) {
Updatefile.createnewfile ();
}
Download functions, take QQ as an example
Add Permissions <uses-permission android:name= "Android.permission.INTERNET" >;
Long downloadsize = Downloadupdatefile ("http://softfile.3g.qq.com:8080/msoft/179/1105/10753/MobileQQ1.0 (Android) _ build0198.apk ", updatefile);
if (downloadsize>0) {
Download successful
Updatehandler.sendmessage (message);
}
}catch (Exception ex) {
Ex.printstacktrace ();
Message.what = Download_fail;
Download failed
Updatehandler.sendmessage (message);
}
}
}
</uses-permission></uses-permission>
There are many implementations of the download function, I post the code here, and we want to notify the user of the download progress when downloading:
Copy Code code as follows:
Public long Downloadupdatefile (String downloadurl, File savefile) throws Exception {
This is a lot of download code, I do not do too much explanation
int downloadcount = 0;
int currentsize = 0;
Long totalsize = 0;
int updatetotalsize = 0;
HttpURLConnection httpconnection = null;
InputStream is = null;
FileOutputStream fos = null;
try {
URL url = new URL (downloadurl);
Httpconnection = (httpurlconnection) url.openconnection ();
Httpconnection.setrequestproperty ("User-agent", "pacifichttpclient");
if (CurrentSize > 0) {
Httpconnection.setrequestproperty ("RANGE", "bytes=" + currentsize + "-");
}
Httpconnection.setconnecttimeout (10000);
Httpconnection.setreadtimeout (20000);
Updatetotalsize = Httpconnection.getcontentlength ();
if (httpconnection.getresponsecode () = = 404) {
throw new Exception ("fail!");
}
is = Httpconnection.getinputstream ();
FOS = new FileOutputStream (SaveFile, false);
byte buffer[] = new byte[4096];
int readsize = 0;
while ((readsize = is.read (buffer)) > 0) {
Fos.write (buffer, 0, readsize);
TotalSize + = ReadSize;
In order to prevent frequent notifications resulting in tight applications, a percentage increase of 10 is not notified once
if ((downloadcount = 0) | | (int) (totalsize*100/updatetotalsize) -10>downloadcount) {
Downloadcount + 10;
Updatenotification.setlatesteventinfo (updateservice.this, "Downloading", (int) totalsize*100/updatetotalsize+ "%", Updatependingintent);
Updatenotificationmanager.notify (0, updatenotification);
}
}
finally {
if (httpconnection!= null) {
Httpconnection.disconnect ();
}
if (is!= null) {
Is.close ();
}
if (FOS!= null) {
Fos.close ();
}
}
return totalsize;
}
After downloading completes, we prompt the user to download completes, and may click Installs, then we will fill in front the handler bar.
First, define 2 constants in Updateservice.java to indicate the download status:
Copy Code code as follows:
Download status
Private final static int download_complete = 0;
Private final static int download_fail = 1;
To process the main thread according to the download status:
Copy Code code as follows:
Private Handler Updatehandler = new Handler () {
@Override
public void Handlemessage (msg) {
Switch (msg.what) {
Case Download_complete:
Click to install Pendingintent
Uri uri = uri.fromfile (updatefile);
Intent installintent = new Intent (Intent.action_view);
Installintent.setdataandtype (URI, "application/vnd.android.package-archive");
Updatependingintent = pendingintent.getactivity (updateservice.this, 0, installintent, 0);
Updatenotification.defaults = notification.default_sound;//Ringtones Reminder
Updatenotification.setlatesteventinfo (Updateservice.this, "Shanghai Metro", "Download complete, click Install.") ", updatependingintent);
Updatenotificationmanager.notify (0, updatenotification);
Stop Service
StopService (updateintent);
Case Download_fail:
Download failed
Updatenotification.setlatesteventinfo (Updateservice.this, "Shanghai Metro", "Download complete, click Install.") ", updatependingintent);
Updatenotificationmanager.notify (0, updatenotification);
Default
StopService (updateintent);
}
}
};
At this point, the file is downloaded and the progress is notified in the notification bar.
Found myself a lot of nonsense, in fact, a few words of things, to and fro wrote so much, long-winded, behind the blog I will work towards streamlining.
PS: The previous code to attach Cheanupdatefile ()
Copy Code code as follows:
File Updatefile = new file (Global.downloaddir,getresources (). getString (R.string.app_name) + ". apk");
if (updatefile.exists ()) {
When not needed, clear the previous download file, avoid wasting user space
Updatefile.delete ();
}