1. 程式人生 > >Android中版本強制更新

Android中版本強制更新

借鑑:http://www.cnblogs.com/shmilyGWT/p/8177961.html,這個有是否強制更新的選擇,我簡單的修改了一部分邏輯,看你的業務邏輯了,也就是增加一個引數來判斷取消按鈕是否顯示,點選確認是否下載。

 一、工具類

public class UpdateManager {
    private Context mContext; //上下文
    private String apkUrl; //apk下載地址
    private List<String> list; //更新內容
    private static final String savePath = "/sdcard/updateAPK/"; //apk儲存到SD卡的路徑
    private static final String saveFileName = savePath + "app_feizufenqi.apk"; //完整路徑名
    private static final int DOWNLOADING = 1; //表示正在下載
    private static final int DOWNLOADED = 2; //下載完畢
    private static final int DOWNLOAD_FAILED = 3; //下載失敗
    private ProgressBar mProgress; //下載進度條控制元件
    private int progress; //下載進度
    private boolean cancelFlag = false; //取消下載標誌位
    private AlertDialog alertDialog1; //表示提示對話方塊、進度條對話方塊

    /** 建構函式 */
    public UpdateManager(Context context,String apkUrl, List list) {
        this.mContext = context;
        this.apkUrl = apkUrl;
        this.list = list;
    }

    /** 顯示更新對話方塊 */
    public void showNoticeDialog(double serverVersion,double clientVersion) {
        //如果版本最新,則不需要更新
        if (serverVersion <= clientVersion)
            return;
        AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
        LayoutInflater inflater = LayoutInflater.from(mContext);
        View view = inflater.inflate(R.layout.softupdate_progress, null);
        mProgress = view.findViewById(R.id.update_progress);
        ListView lv = view.findViewById(R.id.lv);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(mContext,R.layout.list_item,list);
        lv.setAdapter(adapter);
        view.findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mProgress.setVisibility(View.VISIBLE);
                //下載apk
                downloadAPK();
            }
        });
        dialog.setView(view);
        alertDialog1  = dialog.create();
        alertDialog1.setCancelable(false);
        alertDialog1.show();
    }

    /** 下載apk的執行緒 */
    public void downloadAPK() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    URL url = new URL(apkUrl);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    // 設定連線主機超時時間
                    conn.setConnectTimeout(5 * 1000);
                    //設定從主機讀取資料超時
                    conn.setReadTimeout(5 * 1000);
                    // 設定是否使用快取  預設是true
//                    conn.setUseCaches(true);
                    // 設定為Post請求
                    conn.setRequestMethod("GET");
                    conn.connect();
                    if (conn.getResponseCode() == 200) {
                        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(DOWNLOADING);
                            if (numread <= 0) {
                                //下載完成通知安裝
                                mHandler.sendEmptyMessage(DOWNLOADED);
                                break;
                            }
                            fos.write(buf, 0, numread);
                        } while (!cancelFlag); //點選取消就停止下載.
                        fos.close();
                        is.close();
                    }
                } catch(Exception e) {
                    mHandler.sendEmptyMessage(DOWNLOAD_FAILED);
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /** 更新UI的handler */
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case DOWNLOADING:
                    mProgress.setProgress(progress);
                    break;
                case DOWNLOADED:
                    if (alertDialog1 != null)
                        alertDialog1.dismiss();
                    installAPK();
                    break;
                case DOWNLOAD_FAILED:
                    Toast.makeText(mContext, "網路斷開,請稍候再試", Toast.LENGTH_LONG).show();
                    break;
                default:
                    break;
            }
        }
    };

    /** 下載完成後自動安裝apk */
    public void installAPK() {
        File apkFile = new File(saveFileName);
        if (!apkFile.exists()) {
            return;
        }

        Intent intent = new Intent(Intent.ACTION_VIEW);
        // 由於沒有在Activity環境下啟動Activity,設定下面的標籤
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        //版本在7.0以上是不能直接通過uri訪問的
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //引數1 上下文, 引數2 Provider主機地址 和配置檔案中保持一致   引數3  共享的檔案
            Uri apkUri = FileProvider.getUriForFile(mContext, "com.example.myversionupdate.fileprovider", apkFile);
            //新增這一句表示對目標應用臨時授權該Uri所代表的檔案
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
            Uri uri = Uri.fromFile(apkFile);
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
        }
        mContext.startActivity(intent);

    }
}

二、使用方法

UpdateManager() mUpdateManager = new UpdateManager(SplashActivity.this, "下載地址","更新內容集合");                                        
mUpdateManager.showNoticeDialog("後臺版本號", "本地版本號");

三、配置內容

1. 在res下建立一個名字為xml的資料夾,在此資料夾下建立一個名字為file_paths.xml的檔案。內容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <paths>
        <external-path
            name="external_files"
            path="." />
        <root-path
            name="root_path"
            path="." />
    </paths>
</resources>

2. 建立一個類MyFileProvider繼承FileProvider。

3.在清單檔案AndroidManifest中引用MyFileProvider。

        <!-- 解決apk安裝失敗的問題 -->
        <provider android:name=".MyFileProvider"
            android:authorities="com.example.myversionupdate.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

四、注意事項

1. 在清單檔案和工具類中的的authorities值一定是你的包名+fileprovider,不然下載失敗。

2. 在使用前記得呼叫動態許可權Manifest.permission.WRITE_EXTERNAL_STORAGE。