Android版本更新並安裝工具類

自己用系統的DownloadManager工具封裝了一個版本更新幫助類,代碼如下:

1.功能具體實現的java代碼

    private static final String TAG = "VersionUpdataHelper";

    private final String DOWNLOAD_FILE_NAME;

    private Context mContext;
    private DownloadManager mDownloadManager;
    private String mUrl;
    private long mDownloadId;
    private CompleteReceiver mReceiver;
    private int mCancleDownload;
    private CustomDialog mDialog;
    private CustomDialog.Builder mBuilder;
    private boolean mCancelable;
    private String mUpdateInfo;

    public VersionUpdataHelper(Activity activity, String url) {
        this(activity, url, true);
    }

    public VersionUpdataHelper(Activity activity, String url, boolean cancelable) {
        this(activity, url, cancelable, "");
    }

    public VersionUpdataHelper(Activity activity, String url, boolean cancelable, String info){
        DOWNLOAD_FILE_NAME = System.currentTimeMillis() + ".apk";
        if (activity == null || activity.isFinishing()){
            return;
        }
        mContext = activity;
        mUrl = url;
        mCancelable = cancelable;
        mUpdateInfo = info;
        showNewVersionDialog();
    }

    private void showNewVersionDialog() {
        String message = "發現新版本,是否下載並更新...";
        if (!TextUtils.isEmpty(mUpdateInfo)){
            message = message + "\n\n" + mUpdateInfo;
            Lg.i(TAG, "---message===" + message);
        }
        mBuilder = new CustomDialog.Builder(mContext);
        mBuilder.setMessage(message)
                .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        startDownload(mUrl);
                        initDownloadingDialog();
                        mDialog.show();
                        mCancleDownload = 0;
                    }
                });
        if (mCancelable) {
            mBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                }
            });
        }
        mDialog = mBuilder.create();
        mDialog.setCancelable(false);
        mDialog.show();
    }

    private void initDownloadingDialog() {
        mCancleDownload = 0;
        mBuilder = new CustomDialog.Builder(mContext);
        mBuilder.setMessage("軟件更新中...");
        mBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (mCancelable) {
                    mDownloadManager.remove(mDownloadId);
                    dialog.dismiss();
                    mCancleDownload = 1;
                    unregisterUpdataReceiver();
                }
            }
        });

        mDialog = mBuilder.create();
        mReceiver = new CompleteReceiver();
        mContext.registerReceiver(mReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

    public void unregisterUpdataReceiver() {
        mContext.unregisterReceiver(mReceiver);
    }

    private void startDownload(String url) {
        mDownloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
        Uri resource = Uri.parse(url);
        DownloadManager.Request request = new DownloadManager.Request(resource);
        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
        request.setAllowedOverRoaming(false);
        MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
        String mimeString = mimeTypeMap.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(url));
        request.setMimeType(mimeString);
        request.setShowRunningNotification(true);
        request.setVisibleInDownloadsUi(true);
        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, DOWNLOAD_FILE_NAME);
        mDownloadId = mDownloadManager.enqueue(request);
        mContext.getContentResolver().registerContentObserver(Uri.parse("content://downloads/"),
                true, new DownloadObserver(handler, mContext, mDownloadId));
    }

    //啓動安裝
    private void openFile(long downloadId) {
        Uri downloadFileUri = mDownloadManager.getUriForDownloadedFile(downloadId);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            Intent updateApk = new Intent(Intent.ACTION_VIEW);
            updateApk.setDataAndType(downloadFileUri, "application/vnd.android.package-archive");
            updateApk.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            mContext.startActivity(updateApk);
        }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive");
            mContext.startActivity(install);
        } else {
            File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + Environment.DIRECTORY_DOWNLOADS + "/", DOWNLOAD_FILE_NAME);
            openFile(file, mContext);
        }
    }

    public void openFile(File file, Context context) {
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(Intent.ACTION_VIEW);
        String mimeType = getMIMEType(file);
        intent.setDataAndType(Uri.fromFile(file), mimeType);
        try {
            context.startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String getMIMEType(File file) {
        String type = "";
        String name = file.getName();
        String fileName = name.substring(name.lastIndexOf(".") + 1, name.length()).toLowerCase();
        type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileName);
        return type;
    }

    public class CompleteReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            long completeDownloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
            if (mDownloadId == completeDownloadId && mCancleDownload == 0) {
                mDialog.dismiss();
                openFile(completeDownloadId);
                unregisterUpdataReceiver();
            }
        }
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            float mDownloadSoFar = (float) msg.arg1 / (1024 * 1024);
            float mDownloadAll = (float) msg.arg2 / (1024 * 1024);

            DecimalFormat decimalFormat = new DecimalFormat("0.00");
            if (mDialog.isShowing()) {
                TextView mDownloadDialogMessageCancelTv = (TextView) mDialog.findViewById(R.id.tv_dialog_message);
                mDownloadDialogMessageCancelTv.setText("已下載" + decimalFormat.format(mDownloadSoFar) + "M,共" + decimalFormat.format(mDownloadAll) + "M");
            }
        }
    };

    public class DownloadObserver extends ContentObserver {
        private long downid;
        private Handler handler;
        private Context context;

        public DownloadObserver(Handler handler, Context context, long downid) {
            super(handler);
            this.handler = handler;
            this.downid = downid;
            this.context = context;
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            DownloadManager.Query query = new DownloadManager.Query().setFilterById(downid);
            DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
            Cursor cursor = downloadManager.query(query);
            while (cursor.moveToNext()) {
                int mDownload_so_far = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                int mDownload_all = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                if (mDownload_so_far < 0) {
                    mDownload_so_far = 0;
                }
                Message message = Message.obtain();
                message.arg1 = mDownload_so_far;
                message.arg2 = mDownload_all;
                message.obj = downid;
                handler.sendMessage(message);
            }
        }
    }

    public static class CustomDialog extends Dialog {

        private TextView mMessageTv;
        private Button mPositiveBtn;
        private Button mNegativeBtn;
        private View mButtonDividerView;

        private String message;
        private String positiveButtonText;
        private String negativeButtonText;
        private OnClickListener positiveButtonClickListener;
        private OnClickListener negativeButtonClickListener;

        public CustomDialog(Context context) {
            super(context);
        }

        public CustomDialog(Context context, int theme) {
            super(context, theme);
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.dialog_custom);
            mMessageTv = (TextView) findViewById(R.id.tv_dialog_message);
            mPositiveBtn = (Button) findViewById(R.id.btn_dialog_positive);
            mNegativeBtn = (Button) findViewById(R.id.btn_dialog_negative);
            mButtonDividerView = findViewById(R.id.view_dialog_button_divider);

            if (message != null) {
                mMessageTv.setText(message);
            }
            if (positiveButtonText != null) {
                mPositiveBtn.setText(positiveButtonText);
                if (positiveButtonClickListener != null) {
                    mPositiveBtn.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            positiveButtonClickListener.onClick(CustomDialog.this, Dialog.BUTTON_POSITIVE);
                        }
                    });
                }
            } else {
                mPositiveBtn.setVisibility(View.GONE);
                mButtonDividerView.setVisibility(View.GONE);
            }

            if (negativeButtonText != null) {
                mNegativeBtn.setText(negativeButtonText);
                if (negativeButtonClickListener != null) {
                    mNegativeBtn.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            negativeButtonClickListener.onClick(CustomDialog.this, Dialog.BUTTON_NEGATIVE);
                        }
                    });
                }
            } else {
                mNegativeBtn.setVisibility(View.GONE);
                mButtonDividerView.setVisibility(View.GONE);
            }

        }

        private void setMessage(String msg) {
            message = msg;
        }

        private void setPositiveButtonText(String text) {
            positiveButtonText = text;
        }

        private void setNegativeButtonText(String text) {
            negativeButtonText = text;
        }

        private void setOnNegativeListener(OnClickListener listener) {
            negativeButtonClickListener = listener;
        }

        private void setOnPositiveListener(OnClickListener listener) {
            positiveButtonClickListener = listener;
        }

        public static class Builder {
            private Context context;
            private String message;
            private String positiveButtonText;
            private String negativeButtonText;
            private OnClickListener positiveButtonClickListener;
            private OnClickListener negativeButtonClickListener;

            public Builder(Context context) {
                this.context = context;
            }

            public Builder setMessage(String message) {
                this.message = message;
                return this;
            }

            public Builder setMessage(int message) {
                this.message = context.getString(message);
                return this;
            }

            public Builder setPositiveButton(int positiveButtonText,
                                             OnClickListener listener) {
                return setPositiveButton(context.getString(positiveButtonText), listener);
            }

            public Builder setPositiveButton(String positiveButtonText,
                                             OnClickListener listener) {
                this.positiveButtonText = positiveButtonText;
                this.positiveButtonClickListener = listener;
                return this;
            }

            public Builder setNegativeButton(int negativeButtonText,
                                             OnClickListener listener) {
                return setNegativeButton(context.getString(negativeButtonText), listener);
            }

            public Builder setNegativeButton(String negativeButtonText,
                                             OnClickListener listener) {
                this.negativeButtonText = negativeButtonText;
                this.negativeButtonClickListener = listener;
                return this;
            }

            public CustomDialog create() {
                CustomDialog dialog = new CustomDialog(context);
                dialog.setCancelable(false);
                dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
                dialog.setMessage(message);
                dialog.setNegativeButtonText(negativeButtonText);
                dialog.setPositiveButtonText(positiveButtonText);
                dialog.setOnNegativeListener(negativeButtonClickListener);
                dialog.setOnPositiveListener(positiveButtonClickListener);
                return dialog;
            }
        }
    }
}

2.用到的佈局文件dialog_custom.xml,放在layout目錄下

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@drawable/dialog_background"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_dialog_message"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:gravity="center"
            android:text="message"
            android:textColor="#333333"
            android:textSize="16sp" />

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#e8e8e8" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:orientation="horizontal">

            <Button
                android:id="@+id/btn_dialog_positive"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@null"
                android:text="todo"
                android:textColor="#EE6911"
                android:textSize="16sp" />

            <View
                android:id="@+id/view_dialog_button_divider"
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:background="#e8e8e8" />

            <Button
                android:id="@+id/btn_dialog_negative"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@null"
                android:text="cancel"
                android:textColor="#EE6911"
                android:textSize="16sp" />

        </LinearLayout>

    </LinearLayout>
</FrameLayout>

3.用到的背景設置dialog_background.xml文件,放在drawable目錄下

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/sweet_dialog_bg_color" />
    <corners android:radius="6dp"/>
</shape>   

使用說明書
* 說明:版本更新幫助類,負責下載apk文件並打開安裝
* 用法:直接new本類,構造方法裏分別傳
* Context Activity的context
* String apk下載地址
* boolean 允許跳過本次更新
* 示例:
* 普通版本更新 new VersionUpdataHelper(MainActivity.this, info.getUrl());
* 強制版本更新 new VersionUpdataHelper(MainActivity.this, info.getUrl(), false);
* 測試過紅米note 4.4,三星 5.1.1,華爲 6.0系統

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章