android 利用dwonLoadManager 實現apk下載更新

項目之前一直用的友盟的自動更新,但好像友盟那邊10月份就開始不支持軟件更新了,所以把更新的功能做到自己的服務器上面。

基本的實現思路如下:
1. 後臺可以提供一個接口也可以,就是我們將當前的版本傳過去,然後後臺返回是否需要更新,如果需要,給出url,
2. 下載apk
3. 安裝apk

具體實現:

1. 向服務器請求的結果如下

{
status: 1,
msg: "需要更新",
versionCode:1
updateUrl: "http://www.ejoooo.com/app/com.ejooo.jianli.apk"
}

後臺已經幫我們判斷了是否需要更新,我們只需要根據status的狀態來判斷是否做出進一步的操作。versionCode的作用是用來判斷用戶本地是否下載了最新的apk,避免重複下載。

2. 我是向後臺請求數據後,彈出一個詢問是否需要更新的對話框,點擊確定操作後

Intent intent = new Intent(mContext.getApplicationContext(), DownLoadService.class);
                intent.putExtra(UpdateConstants.FIELD_APK_DOWNLOAD_URL, VALUE_DOWNLOAD_URL);
                intent.putExtra(UpdateConstants.FIELD_APK_NAME, appName);
                intent.putExtra(UpdateConstants.FIELD_APK_PATH, mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getPath());
mContext.startService(intent);

3.這裏需要注意的是

DownLoadService 不可集成IntentService,不然寫在IntentService裏面的BroadCastRecieve接收不到廣播。

public class DownLoadService extends Service {
    public static long DOWNLOAD_ID;
    private String downloadUrl;
    private String apkName;
    private String apkPath;
    /**
     * 安卓系統下載類
     **/
    DownloadManager manager;

    /**
     * 接收下載完的廣播
     **/
    DownloadCompleteReceiver receiver;

    /**
     * 初始化下載器
     **/
    private void initDownManager() {

        manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);

        receiver = new DownloadCompleteReceiver();

        List<String> list = FileUtils.GetFiles(apkPath, "apk", apkName, false);
        if (list.size() != 0) {
            installAPK(Uri.fromFile(new File(list.get(0))));
            return;
        }

        //設置下載地址
        DownloadManager.Request down = new DownloadManager.Request(
                Uri.parse(downloadUrl));

        // 設置允許使用的網絡類型,這裏是移動網絡和wifi都可以
        down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE
                | DownloadManager.Request.NETWORK_WIFI);

        // 下載時,通知欄顯示途中
        down.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);

        // 顯示下載界面
        down.setVisibleInDownloadsUi(true);

        // 設置下載後文件存放的位置
        down.setDestinationInExternalFilesDir(this,
                Environment.DIRECTORY_DOWNLOADS, apkName + ".apk");

        // 將下載請求放入隊列
        DOWNLOAD_ID = manager.enqueue(down);

        //註冊下載廣播
        registerReceiver(receiver, new IntentFilter(
                DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        downloadUrl = intent.getStringExtra(UpdateConstants.FIELD_APK_DOWNLOAD_URL);
        apkName = intent.getStringExtra(UpdateConstants.FIELD_APK_NAME);
        apkPath = intent.getStringExtra(UpdateConstants.FIELD_APK_PATH);
        // 調用下載
        initDownManager();

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {

        return null;
    }

    @Override
    public void onDestroy() {

        // 註銷下載廣播
        if (receiver != null)
            unregisterReceiver(receiver);

        super.onDestroy();
    }

    /**
     * 安裝apk
     * @param apk
     */
    private void installAPK(Uri apk){
        Intent intent = new Intent();
        //執行動作
        intent.setAction(Intent.ACTION_VIEW);
        //執行的數據類型
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setDataAndType(apk, "application/vnd.android.package-archive");
        //不加下面這句話是可以的,查考的裏面說如果不加上這句的話在apk安裝完成之後點擊單開會崩潰
        //android.os.Process.killProcess(android.os.Process.myPid());
        startActivity(intent);
    }

    // 接受下載完成後的intent
    class DownloadCompleteReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            //判斷是否下載完成的廣播
            if (intent.getAction().equals(
                    DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {

                //獲取下載的文件id
                long downId = intent.getLongExtra(
                        DownloadManager.EXTRA_DOWNLOAD_ID, -1);

                //自動安裝apk
                installAPK(manager.getUriForDownloadedFile(downId));

                //停止服務並關閉廣播
                DownLoadService.this.stopSelf();

            }
        }

        /**
         * 安裝apk文件
         */
        private void installAPK(Uri apk) {

            // 通過Intent安裝APK文件

            Intent intent = new Intent();
            //執行動作
            intent.setAction(Intent.ACTION_VIEW);
            //執行的數據類型
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setDataAndType(apk, "application/vnd.android.package-archive");
            //不加下面這句話是可以的,查考的裏面說如果不加上這句的話在apk安裝完成之後點擊單開會崩潰
            //android.os.Process.killProcess(android.os.Process.myPid());
            startActivity(intent);

        }

    }
}

4.如何實現避免用戶重複下載的問題

具體的實現方法是通過文件查找的方法,查找下載目錄下面是否有最新的apk。至於apk是否爲最新的,就需要在下載的時候通過versionName+versionCode命名,更新的時候從無夫妻獲取到最新的versionCode 與文件名稱做比較即可。

 /**
     * 查找文件
     *
     * @param Path        文件夾路徑
     * @param Extension   文件擴展名
     * @param IsIterative 是否進入子文件夾
     */
    public static List<String> GetFiles(String Path, String Extension, String fileName, boolean IsIterative) //搜索目錄,擴展名,是否進入子文件夾
    {
        List<String> lstFile = new ArrayList<String>(); //結果 List
        File[] files = new File(Path).listFiles();
        if (files == null) {
            return lstFile;
        }
        for (int i = 0; i < files.length; i++) {
            File f = files[i];
            if (f.isFile()) {
                if (f.getPath().substring(f.getPath().length() - Extension.length()).equals(Extension)) { //判斷擴展名
                    String name =files[i].getName();
                    if (files[i].getName().equals(fileName+".apk")) {
                        lstFile.add(f.getPath());
                    }
                }
                /*if (!IsIterative)
                    break;*/
            } else if (f.isDirectory() && f.getPath().indexOf("/.") == -1) //忽略點文件(隱藏文件/文件夾)
                GetFiles(f.getPath(), Extension, fileName, IsIterative);
        }
        return lstFile;
    }
發佈了25 篇原創文章 · 獲贊 14 · 訪問量 49萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章