2025-05-24

一個好的應用軟件都是需要好的維護,從初出版本到最後精品,這個過程需要版本不停的更新,那麼如何讓用戶第一時間獲取最新的應用安裝包呢?那麼就要求我們從第一個版本就要實現升級模塊這一功能。

自動更新功能的實現原理,就是我們事先和後臺協商好一個接口,我們在應用的主Activity裡,去訪問這個接口,如果需要更新,後臺會返回一些數據(比如,提示語;最新版本的url等)。然後我們給出提示框,用戶點擊開始下載,下載完成開始覆蓋安裝程序,這樣用戶的應用就保持最新的拉。

為瞭讓大傢容易理解,我像往常一樣準備一個小例子,這裡為瞭方便我就省去瞭和後臺交互部分瞭。步驟分別如下:

第一步:新建一個Android工程命名為:UpdateDemo.代碼結構如下圖所示:

 

 

第二步:新建一個UpdateManager.java類,負責軟件更新功能模塊,代碼如下:

[java] package com.tutor.update; 
 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.HttpURLConnection; 
import java.net.MalformedURLException; 
import java.net.URL; 
 
 
import android.app.AlertDialog; 
import android.app.Dialog; 
import android.app.AlertDialog.Builder; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.content.DialogInterface.OnClickListener; 
import android.net.Uri; 
import android.os.Handler; 
import android.os.Message; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.widget.ProgressBar; 
 
public class UpdateManager { 
 
    private Context mContext; 
     
    //提示語 
    private String updateMsg = "有最新的軟件包哦,親快下載吧~"; 
     
    //返回的安裝包url 
    private String apkUrl = "http://softfile.3g.qq.com:8080/msoft/179/24659/43549/qq_hd_mini_1.4.apk"; 
     
     
    private Dialog noticeDialog; 
     
    private Dialog downloadDialog; 
     /* 下載包安裝路徑 */ 
    private static final String savePath = "/sdcard/updatedemo/"; 
     
    private static final String saveFileName = savePath + "UpdateDemoRelease.apk"; 
 
    /* 進度條與通知ui刷新的handler和msg常量 */ 
    private ProgressBar mProgress; 
 
     
    private static final int DOWN_UPDATE = 1; 
     
    private static final int DOWN_OVER = 2; 
     
    private int progress; 
     
    private Thread downLoadThread; 
     
    private boolean interceptFlag = false; 
     
    private Handler mHandler = new Handler(){ 
        public void handleMessage(Message msg) { 
            switch (msg.what) { 
            case DOWN_UPDATE: 
                mProgress.setProgress(progress); 
                break; 
            case DOWN_OVER: 
                 
                installApk(); 
                break; 
            default: 
                break; 
            } 
        }; 
    }; 
     
    public UpdateManager(Context context) { 
        this.mContext = context; 
    } 
     
    //外部接口讓主Activity調用 
    public void checkUpdateInfo(){ 
        showNoticeDialog(); 
    } 
     
     
    private void showNoticeDialog(){ 
        AlertDialog.Builder builder = new Builder(mContext); 
        builder.setTitle("軟件版本更新"); 
        builder.setMessage(updateMsg); 
        builder.setPositiveButton("下載", new OnClickListener() {          
            @Override 
            public void onClick(DialogInterface dialog, int which) { 
                dialog.dismiss(); 
                showDownloadDialog();            
            } 
        }); 
        builder.setNegativeButton("以後再說", new OnClickListener() {            
            @Override 
            public void onClick(DialogInterface dialog, int which) { 
                dialog.dismiss();                
            } 
        }); 
        noticeDialog = builder.create(); 
        noticeDialog.show(); 
    } 
     
    private void showDownloadDialog(){ 
        AlertDialog.Builder builder = new Builder(mContext); 
        builder.setTitle("軟件版本更新"); 
         
        final LayoutInflater inflater = LayoutInflater.from(mContext); 
        View v = inflater.inflate(R.layout.progress, null); 
        mProgress = (ProgressBar)v.findViewById(R.id.progress); 
         
        builder.setView(v); 
        builder.setNegativeButton("取消", new OnClickListener() {  
            @Override 
            public void onClick(DialogInterface dialog, int which) { 
                dialog.dismiss(); 
                interceptFlag = true; 
            } 
        }); 
        downloadDialog = builder.create(); 
        downloadDialog.show(); 
         
        downloadApk(); 
    } 
     
    private Runnable mdownApkRunnable = new Runnable() {     
        @Override 
        public void run() { 
            try { 
                URL url = new URL(apkUrl); 
             
                HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 
                conn.connect(); 
                int length = conn.getContentLength(); 
                InputStream is = conn.getInputStream(); 
                 
                File file = new File(savePath); 
                if(!file.exists()){ 
                    file.mkdir(); 
                } 
                String apkFile = saveFileName; 
                File ApkFile = new File(apkFile); 
                FileOutputStream fos = new FileOutputStream(ApkFile); 
                 
                int count = 0; 
                byte buf[] = new byte[1024]; 
                 
                do{                  
                    int numread = is.read(buf); 
                    count += numread; 
                    progress =(int)(((float)count / length) * 100); 
                    //更新進度 
                    mHandler.sendEmptyMessage(DOWN_UPDATE); 
                    if(numread <= 0){     
                        //下載完成通知安裝 
                        mHandler.sendEmptyMessage(DOWN_OVER); 
                        break; 
                    } 
                    fos.write(buf,0,numread); 
                }while(!interceptFlag);//點擊取消就停止下載. 
                 
                fos.close(); 
                is.close(); 
            } catch (MalformedURLException e) { 
                e.printStackTrace(); 
            } catch(IOException e){ 
                e.printStackTrace(); 
            } 
             
        } 
    }; 
     
     /**
     * 下載apk
     * @param url
     */ 
     
    private void downloadApk(){ 
        downLoadThread = new Thread(mdownApkRunnable); 
        downLoadThread.start(); 
    } 
     /**
     * 安裝apk
     * @param url
     */ 
    private void installApk(){ 
        File apkfile = new File(saveFileName); 
        if (!apkfile.exists()) { 
            return; 
        }     
        Intent i = new Intent(Intent.ACTION_VIEW); 
        i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");  
        mContext.startActivity(i); 
     
    } 

第三步:在MainActivity.java也就是主Activity調用,代碼如下: [java] package com.tutor.update; 
 
import android.app.Activity; 
import android.os.Bundle; 
 
public class MainAcitivity extends Activity { 
     
 
    private UpdateManager mUpdateManager; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
         
        //這裡來檢測版本是否需要更新 
        mUpdateManager = new UpdateManager(this); 
        mUpdateManager.checkUpdateInfo(); 
    }      

第四步:添加程序所用的資源與權限:
下載的時候用到瞭ProgressBar,所以事先寫瞭一個progress.xml佈局文件,代碼如下:

[java] <?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
  xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content"> 
   
  <ProgressBar 
    android:id="@+id/progress" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    style="?android:attr/progressBarStyleHorizontal" 
  /> 
</LinearLayout> 
下載的時候用到瞭網絡部分,所以要在AndroidManifest.xml中添加網絡權限,代碼如下: [java] <uses-permission android:name="android.permission.INTERNET" /> 

  第五步:運行查看效果如下:
    
 圖一:提示有最新包                                                                                   圖二:點擊開始下載

圖三:下載完開始安裝,我這裡模擬器空間不足瞭。
 
源碼下載:http://up.aiwalls.com/2012/0409/20120409023126122.rar

摘自  虛懷若谷

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *