1. 程式人生 > >Android版本更新並安裝工具類

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系統