Android實現APP自動更新功能

來源:互聯網
上載者:User

Android實現APP自動更新功能

現在一般的android軟體都是需要不斷更新的,當你開啟某個app的時候,如果有新的版本,它會提示你有新版本需要更新。該小程式實現的就是這個功能。

該小程式的特點是,當有更新時,會彈出一個提示框,點擊確定,則在通知來建立一個進度條進行下載,點擊取消,則取消更新。

以下是詳細代碼:

1.建立布局檔案notification_item.xml,用於在通知欄產生一個進度條和下載表徵圖。

 

     

2.建立AppContext類,該類繼承自Application。

 

 

package com.test.application;import android.app.Application;import android.content.Context;import com.test.update.config.Config;public class AppContext extends Application {private static AppContext appInstance;private Context context;public static AppContext getInstance() {return appInstance;}@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();appInstance = this;context = this.getBaseContext();//// 擷取目前的版本號//try {//PackageInfo packageInfo = getApplicationContext()//.getPackageManager().getPackageInfo(getPackageName(), 0);//Config.localVersion = packageInfo.versionCode;//Config.serverVersion = 1;// 假定伺服器版本為2,本地版本預設是1//} catch (NameNotFoundException e) {//e.printStackTrace();//}initGlobal();}public void initGlobal() {try {Config.localVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; // 設定本地版本號碼Config.serverVersion = 2;// 假定伺服器版本為2,本地版本預設是1--實際開發中是從伺服器擷取最新版本號碼,android具體與後端的互動見我另///外的博文} catch (Exception ex) {ex.printStackTrace();}}}

3.建立設定檔類Config.java,在這個類裡面定義一些與版本相關的常量

 

 

package com.test.update.config;public class Config {//版本資訊    public static int localVersion = 0;    public static int serverVersion = 0;    /* 下載包安裝路徑 */      public static final String savePath = /sdcard/test/;        public static final String saveFileName = savePath + test.apk;  }


 

4.編寫更新服務類UpdateServcie.java

 

package com.test.update;import java.io.File;import java.io.FileOutputStream;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import android.annotation.SuppressLint;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.app.Service;import android.content.Intent;import android.net.Uri;import android.os.Environment;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.widget.RemoteViews;import com.test.update.config.Config;public class UpdateService extends Service {// 標題private int titleId = 0;// 檔案儲存體private File updateDir = null;private File updateFile = null;// 下載狀態private final static int DOWNLOAD_COMPLETE = 0;private final static int DOWNLOAD_FAIL = 1;// 通知欄private NotificationManager updateNotificationManager = null;private Notification updateNotification = null;// 通知欄跳轉Intentprivate Intent updateIntent = null;private PendingIntent updatePendingIntent = null;/*** * 建立通知欄 */RemoteViews contentView;// 這樣的下載代碼很多,我就不做過多的說明int downloadCount = 0;int currentSize = 0;long totalSize = 0;int updateTotalSize = 0;// 在onStartCommand()方法中準備相關的下載工作:@SuppressWarnings(deprecation)@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// 擷取傳值titleId = intent.getIntExtra(titleId, 0);// 建立檔案if (android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState())) {updateDir = new File(Environment.getExternalStorageDirectory(),Config.saveFileName);updateFile = new File(updateDir.getPath(), getResources().getString(titleId) + .apk);}this.updateNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);this.updateNotification = new Notification();// 設定下載過程中,點擊通知欄,回到主介面updateIntent = new Intent(this, UpdateActivity.class);updatePendingIntent = PendingIntent.getActivity(this, 0, updateIntent,0);// 設定通知欄顯示內容updateNotification.icon = R.drawable.ic_launcher;updateNotification.tickerText = 開始下載;updateNotification.setLatestEventInfo(this, QQ, 0%,updatePendingIntent);// 發出通知updateNotificationManager.notify(0, updateNotification);// 開啟一個新的線程下載,如果使用Service同步下載,會導致ANR問題,Service本身也會阻塞new Thread(new updateRunnable()).start();// 這個是下載的重點,是下載的過程return super.onStartCommand(intent, flags, startId);}@Overridepublic IBinder onBind(Intent arg0) {// TODO Auto-generated method stubreturn null;}@SuppressLint(HandlerLeak)private Handler updateHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case DOWNLOAD_COMPLETE:// 點擊安裝PendingIntentUri 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;// 鈴聲提醒updateNotification.setLatestEventInfo(UpdateService.this,QQ, 下載完成,點擊安裝。, updatePendingIntent);updateNotificationManager.notify(0, updateNotification);// 停止服務stopService(updateIntent);case DOWNLOAD_FAIL:// 下載失敗updateNotification.setLatestEventInfo(UpdateService.this,QQ, 下載完成,點擊安裝。, updatePendingIntent);updateNotificationManager.notify(0, updateNotification);default:stopService(updateIntent);}}};public long downloadUpdateFile(String downloadUrl, File saveFile)throws Exception {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;// 為了防止頻繁的通知導致應用吃緊,百分比增加10才通知一次if ((downloadCount == 0)|| (int) (totalSize * 100 / updateTotalSize) - 10 > downloadCount) {downloadCount += 10;updateNotification.setLatestEventInfo(UpdateService.this,正在下載, (int) totalSize * 100 / updateTotalSize+ %, updatePendingIntent);/*** * 在這裡我們用自定的view來顯示Notification */updateNotification.contentView = new RemoteViews(getPackageName(), R.layout.notification_item);updateNotification.contentView.setTextViewText(R.id.notificationTitle, 正在下載);updateNotification.contentView.setProgressBar(R.id.notificationProgress, 100, downloadCount, false);updateNotificationManager.notify(0, updateNotification);}}} finally {if (httpConnection != null) {httpConnection.disconnect();}if (is != null) {is.close();}if (fos != null) {fos.close();}}return totalSize;}class updateRunnable implements Runnable {Message message = updateHandler.obtainMessage();public void run() {message.what = DOWNLOAD_COMPLETE;try {// 增加許可權;if (!updateDir.exists()) {updateDir.mkdirs();}if (!updateFile.exists()) {updateFile.createNewFile();}// 下載函數,以QQ為例子// 增加許可權;long downloadSize = downloadUpdateFile(http://softfile.3g.qq.com:8080/msoft/179/1105/10753/MobileQQ1.0(Android)_Build0198.apk,updateFile);if (downloadSize > 0) {// 下載成功updateHandler.sendMessage(message);} } catch (Exception ex) {ex.printStackTrace();message.what = DOWNLOAD_FAIL;// 下載失敗updateHandler.sendMessage(message);}}}}

5.編寫活動類UpdateActivity

 

 

package com.test.update;import com.test.update.config.Config;import android.support.v4.app.Fragment;import android.app.Activity;import android.app.AlertDialog;import android.content.DialogInterface;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.LayoutInflater;public class UpdateActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);checkVersion();}/** * 檢查更新版本 */public void checkVersion() {if (Config.localVersion < Config.serverVersion) {Log.i(hgncxzy, ==============================);// 發現新版本,提示使用者更新AlertDialog.Builder alert = new AlertDialog.Builder(this);alert.setTitle(軟體升級).setMessage(發現新版本,建議立即更新使用.).setPositiveButton(更新,new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int which) {// 開啟更新服務UpdateService// 這裡為了把update更好模組化,可以傳一些updateService依賴的值// 如布局ID,資源ID,動態擷取的標題,這裡以app_name為例Intent updateIntent = new Intent(UpdateActivity.this,UpdateService.class);updateIntent.putExtra(titleId,R.string.app_name);startService(updateIntent);}}).setNegativeButton(取消,new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int which) {dialog.dismiss();}});alert.create().show();} else {// 清理工作,略去// cheanUpdateFile()}}}

6.添加許可權以及將服務靜態載入(在設定檔中載入)。

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.