One, foreword

App online update is a common requirement. When the new version is released, users will enter our APP, and the update prompt box will pop up to update the new version of APP in the first time. The online update is divided into the following steps:

1. Obtain the online version number through the interface, versionCode 2, compare the online versionCode with the local versionCode, and pop up the update window 3. Download APK file (file download) 4Copy the code

Online update on the above steps, the first two steps are relatively simple, the most important is the last two steps, and due to Android versions of the rights and privacy of the acceptance and protection, therefore, there will be a variety of adaptation problems, so this article summarizes the APP online update methods and some adaptation problems encountered.

Apk download

An APK download is a file download, and there are many ways to download files:

1, many third-party frameworks have the file upload and download function, you can use the third-party framework (e.g. Volley,OkHttp) 2, you can also start a thread to download, (can use IntentService) 3, the simplest way: The Android SDK actually provides us with the DownloadManager class, which can be easily downloaded with simple configuration items.Copy the code

This article uses the third method, DownloadManager, to download APK.

1. UseDownloadManagerDownload the apk

DownloadManager comes with the SDK. The process is as follows:

(1) Create a Request and perform simple configuration (download address, file saving address, etc.) (2) After downloading, the system will send a broadcast after downloading, and we need to listen to the broadcast. (3) After listening to the downloaded broadcast, find the downloaded APK file according to the ID. (4) Execute the APK installation in the code.

public void downloadApk(String apkUrl, String title, String desc) { // fix bug : File apkFile = new File(WeakReference.get ().getexternalFilesDir (environment.directory_downloads)),"test.apk");

       if(apkFile ! = null && apkFile.exists()) { apkFile.delete(); } DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl)); // setTitle request.settitle (title); // setDescription request.setDescription(desc); / / display notification bar after the completion of the request. SetNotificationVisibility (DownloadManager. Request. VISIBILITY_VISIBLE_NOTIFY_COMPLETED); request.setDestinationInExternalFilesDir(weakReference.get(), Environment.DIRECTORY_DOWNLOADS,"test.apk"); / / in the mobile phone to create a download folder on your SD card. / / the Environment getExternalStoragePublicDirectory (Environment. DIRECTORY_DOWNLOADS). The mkdir (); / / designated download to the SD card/download/my/directory / / request. SetDestinationInExternalPublicDir ("/codoon/"."test.apk");

       request.setMimeType("application/vnd.android.package-archive"); // remember reqId mReqId = mdownloadManager.enqueue (request); }Copy the code

As shown in the code above, first build a Request, set the download address, title, description, apK store directory, etc. Finally, call mdownloadManager.enqueue (Request) to start downloading.

Note: We need to remember this mReqId here, because once the download is complete, we need to find the APK file based on this ID and then install apK.

2. Update the download progress

To download files, we generally need to know the download progress and give users a friendly reminder on the interface. The same is true for app update. We need to display the current download progress and the total progress on the interface, so that users can know the approximate waiting time. What about getting the download progress?

Before downloading, we need to register an Observer in the Activity. This is an Observer that notifies the Observer when the download progress changes, thus updating the progress. The steps are as follows:

DownloadChangeObserver is used to monitor the download progress. DownloadChangeObserver is used to update the UI progressCopy the code

Specific code is as follows: DownloadChangeObserver. Class:

 class DownloadChangeObserver extends ContentObserver {

        /**
         * Creates a content observer.
         *
         * @param handler The handler to run {@link #onChange} on, or null if none.*/ public DownloadChangeObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); updateView(); }}Copy the code

In the updateView() method, query the download progress.

 private void updateView() {
        int[] bytesAndStatus = new int[]{0, 0, 0};
        DownloadManager.Query query = new DownloadManager.Query().setFilterById(mReqId);
        Cursor c = null;
        try {
            c = mDownloadManager.query(query);
            if (c != null && c.moveToFirst()) {
                //已经下载的字节数
                bytesAndStatus[0] = c.getInt(c.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                //总需下载的字节数
                bytesAndStatus[1] = c.getInt(c.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                //状态所在的列索引
                bytesAndStatus[2] = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
            }
        } finally {
            if (c != null) {
                c.close();
            }
        }

        if(mUpdateListener ! = null) { mUpdateListener.update(bytesAndStatus[0], bytesAndStatus[1]); } Log.i(TAG,"Download Progress:" + bytesAndStatus[0] + "/" + bytesAndStatus[1] + "");
    }

Copy the code

According to the ID we recorded in front to query the progress, the code has been annotated, no more talk.

To get the progress, you need to register the DownloadChangeObserver as follows:

weakReference.get().getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"), true,
                mDownLoadChangeObserver);

Copy the code

3. Obtain the download result

DownloadManager will send a completed broadcast downloadManager. ACTION_DOWNLOAD_COMPLETE. We just need to listen for this broadcast and get the APK file after receiving it.

Define a broadcast DownloadReceiver.

class DownloadReceiver extends BroadcastReceiver { @Override public void onReceive(final Context context, // Install APK long completeDownLoadId = Intent.getLongExtra (downloadManager.extra_download_id, -1); Logger.e(TAG,"Received a broadcast.");
        Uri uri;
        Intent intentInstall = new Intent();
        intentInstall.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intentInstall.setAction(Intent.ACTION_VIEW);

        if (completeDownLoadId == mReqId) {
           uri = mDownloadManager.getUriForDownloadedFile(completeDownLoadId);
         }

         intentInstall.setDataAndType(uri, "application/vnd.android.package-archive"); context.startActivity(intentInstall); }}Copy the code

Register for broadcasts before downloading

// Register broadcast, Weakreference.get (). RegisterReceiver (mDownloadReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));Copy the code

Through the above steps, basically complete the app online update function, under Android 6.0 can run normally. But don’t rush, this article is not over yet, each version of Android has some changes, so we need to adapt different versions, otherwise, there will be problems, let’s take a look at Android 6.0,7.0,8.0 related adaptation.

Three, adapt Android 6.0

Through the previous steps, the online update of the app works normally under 6.0. On Android6.0, the following error will be reported when installing the app:

Caused by:
5 android.content.ActivityNotFoundException:No Activity found to handle Intent { act=android.intent.action.VIEW typ=application/vnd.android.package-archive flg=0x10000000 }

Copy the code

Why is the error reported? After debugging, it is found that the Uri obtained by DownloadManager is different between Android6.0 and Android6.0.

The differences are as follows: (1) Android 6.0, getUriForDownloadedFile gets the value: Content ://downloads/my_downloads/10 (2) GetUriForDownloadedFile value is: get file:///storage/emulated/0/Android/data/packgeName/files/Download/xxx.apk

As you can see, Android6.0 gets the apK address starting with: content://. How do you solve it? A solution was found after searching for information:

// Query the downloaded APK in downLoadId, Public static File queryDownloadedApk(Context Context, Long Downdid) {File targetApkFile = null; DownloadManager downloader = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);if(downloadId ! = -1) { DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(downloadId); query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL); Cursor cur = downloader.query(query);if(cur ! = null) {if (cur.moveToFirst()) {
                    String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                    if (!TextUtils.isEmpty(uriString)) {
                        targetApkFile = new File(Uri.parse(uriString).getPath());
                    }
                }
                cur.close();
            }
        }
        return targetApkFile;
    }

Copy the code

Instead of using getUriForDownloadedFile to get the Uri, use the downloadManager.column_local_URI field to get the APK address as shown above.

After adapting Android 6.0, install apK code as follows:

 /**
     * @param context
     * @param intent
     */
    private void installApk(Context context, Intent intent) {
        long completeDownLoadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);

        Logger.e(TAG, "Received a broadcast.");
        Uri uri;
        Intent intentInstall = new Intent();
        intentInstall.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intentInstall.setAction(Intent.ACTION_VIEW);

        if (completeDownLoadId == mReqId) {
            if(build.version.sdk_int < build.version_codes.m) {// 6.0 the following uri = mDownloadManager.getUriForDownloadedFile(completeDownLoadId); }else if(build.version.sdk_int < build.version_codes.n) {// 6.0-7.0 File apkFile = queryDownloadedApk(context, completeDownLoadId); uri = Uri.fromFile(apkFile); } // Install application logger.e ("zhouwei"."Download complete");

            intentInstall.setDataAndType(uri, "application/vnd.android.package-archive"); context.startActivity(intentInstall); }}Copy the code
4. Adapt to Android 7.0

Just adapted to 6.0, in the 7.0 or more machine on the problem, why? Android 7.0 provides the FileProvider, which should be used to obtain the APK address and then install the APK. Simple adaptation is as follows:

(1) In the RES directory, create a new XML folder and create a file provider_Paths under the XML:

<? xml version="1.0" encoding="utf-8"? > <paths> <external-path name="external"
        path="" />
    <external-files-path
        name="Download"
        path="" />
</paths>

Copy the code

(2) Declare Provider in androidmanifest.xml:

<! Provider Android :name= provider Android :name="android.support.v4.content.FileProvider"
            android:authorities="packgeName.fileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>

Copy the code

(3) File address on Android 7.0:

 uri = FileProvider.getUriForFile(context,
                        "packageNam.fileProvider",
                        new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "xxx.apk"));

Copy the code

Ok, so 7.0 adaptation work is complete, the installation code after adaptation is as follows:

 /**
     * @param context
     * @param intent
     */
    private void installApk(Context context, Intent intent) {
        long completeDownLoadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);

        Logger.e(TAG, "Received a broadcast.");
        Uri uri;
        Intent intentInstall = new Intent();
        intentInstall.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intentInstall.setAction(Intent.ACTION_VIEW);

        if (completeDownLoadId == mReqId) {
            if(build.version.sdk_int < build.version_codes.m) {// 6.0 the following uri = mDownloadManager.getUriForDownloadedFile(completeDownLoadId); }else if(build.version.sdk_int < build.version_codes.n) {// 6.0-7.0 File apkFile = queryDownloadedApk(context, completeDownLoadId); uri = Uri.fromFile(apkFile); }else{/ / Android 7.0 above uri = FileProvider getUriForFile (context,"packgeName.fileProvider",
                        new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "xxx.apk")); intentInstall.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } // Install application logger.e ("zhouwei"."Download complete");

            intentInstall.setDataAndType(uri, "application/vnd.android.package-archive"); context.startActivity(intentInstall); }}Copy the code

Note: Replace the above packageNam with your own package name and XXX. Apk with your own APK name. For more information about FileProviders, we won’t go into detail here. If you want to know more about fileProviders, you can read our article: Android 7.0 behavior Changes using FileProviders to share files between applications.

5. Adaptation of Android 8.0: Application permissions from unknown sources

So tired, I continue to adapt Android 8.0, because there is no Android 8.0 mobile phone, I have not noticed, a few days ago, a Huawei user feedback online update the new version, specific performance is: apK download completed, flash, no jump to the APK installation interface. After investigation, it was determined that the Android 8.0 permission problem.

On Android8.0 and above, you can’t install apps from unknown sources by code (find apk in sd card, manual installation is possible), the switch of unknown app installation permissions has been removed, and replaced by the management list of unknown app installation permissions, which need to be enabled in the list of unknown app installation permissions. Google is doing this to prevent legitimate applications from doing illegal things with upgrades that violate users’ rights.

Know the problem, let’s adapt it:

Declare permissions in the manifest file: REQUEST_INSTALL_PACKAGES

  <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

Copy the code

(2) Judge whether the user has been authorized in the code, if so, you can directly install, if not, jump to the authorization list, let the user open the unknown source application installation permission, after opening, then install the application.

Add the following code to the broadcast listening for apK download status:

boolean haveInstallPermission; // Compatible with Android 8.0if(build.version.sdk_int >= build.version_codes.o) {haveInstallPermission = context.getPackageManager().canRequestPackageInstalls();if(! HaveInstallPermission) {/ / there is no authority / / popup window and go to the Settings page final authorization AndroidOInstallPermissionListener listener = newAndroidOInstallPermissionListener() {
                        @Override
                        public void permissionSuccess() {
                            installApk(context, intent);
                        }

                        @Override
                        public void permissionFail() {
                            ToastUtils.shortToast(context, "Authorization failed, application cannot be installed"); }}; AndroidOPermissionActivity.sListener = listener; Intent intent1 = new Intent(context, AndroidOPermissionActivity.class); context.startActivity(intent1); }else{ installApk(context, intent); }}else {
                installApk(context, intent);
            }

Copy the code

Because when authorized to play box prompts, we use an Activity to the agent creates an Activity: AndroidOPermissionActivity to apply for permission, after users click on Settings, jump to permissions Settings interface, Then we judge in onActivityResult that all authorization is successful.

AndroidOPermissionActivity code is as follows:

/** * Compatible with Android 8. 0 APP online update, Access application interface * Created by zhouwei on 2018/3/23. * / public class AndroidOPermissionActivity extends BaseActivity {public static final int INSTALL_PACKAGES_REQUESTCODE = 1; private AlertDialog mAlertDialog; public static AppDownloadManager.AndroidOInstallPermissionListener sListener; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); / / windowif (Build.VERSION.SDK_INT >= 26) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES}, INSTALL_PACKAGES_REQUESTCODE);
        } else {
            finish();
        }

    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case INSTALL_PACKAGES_REQUESTCODE:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    if (sListener != null) {
                        sListener.permissionSuccess();
                        finish();
                    }
                } else {
                    //startInstallPermissionSettingActivity();
                    showDialog();
                }
                break;

        }
    }

    private void showDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(R.string.app_name);
        builder.setMessage("In order to upgrade XXX APP normally, please click the Settings button to allow the installation of apps from unknown sources. This function is only used for XXX APP version upgrade.");
        builder.setPositiveButton("Settings", new DialogInterface.OnClickListener() { @RequiresApi(api = Build.VERSION_CODES.O) @Override public void onClick(DialogInterface dialogInterface, int i) { startInstallPermissionSettingActivity(); mAlertDialog.dismiss(); }}); builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                if (sListener != null) {
                    sListener.permissionFail();
                }
                mAlertDialog.dismiss();
                finish();
            }
        });
        mAlertDialog = builder.create();
        mAlertDialog.show();
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void startInstallPermissionSettingActivityIntent Intent = new Intent(settings.action_manage_unknown_sources, uri.parse (intents. Action_manage_unknown_sources, intents."package:" + getPackageName()));
        startActivityForResult(intent, 1);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == 1&& resultCode == RESULT_OK) {// Authorization succeedsif (sListener != null) {
                sListener.permissionSuccess();
            }
        } else{// Authorization failedif(sListener ! = null) { sListener.permissionFail(); } } finish(); } @Override protected voidonDestroy() { super.onDestroy(); sListener = null; }}Copy the code

Note: When jumping to an unknown app license list with an Intent, include the package name so that it can jump directly to your app. Otherwise, it can only jump to the list.

Okay, now you can update it online on Android 8.0.

Six, complete code, encapsulate a classAppDownloadManager

In order not to depend on an Activity, we package an AppDownloadManager, which can be updated online with a few lines of code. The complete code is given:

public class AppDownloadManager {
    public static final String TAG = "AppDownloadManager";
    private WeakReference<Activity> weakReference;
    private DownloadManager mDownloadManager;
    private DownloadChangeObserver mDownLoadChangeObserver;
    private DownloadReceiver mDownloadReceiver;
    private long mReqId;
    private OnUpdateListener mUpdateListener;

    public AppDownloadManager(Activity activity) {
        weakReference = new WeakReference<Activity>(activity);
        mDownloadManager = (DownloadManager) weakReference.get().getSystemService(Context.DOWNLOAD_SERVICE);
        mDownLoadChangeObserver = new DownloadChangeObserver(new Handler());
        mDownloadReceiver = new DownloadReceiver();
    }

    public void setUpdateListener(OnUpdateListener mUpdateListener) { this.mUpdateListener = mUpdateListener; } public void downloadApk(String apkUrl, String title, String desc) { // fix bug : File apkFile = new File(WeakReference.get ().getexternalFilesDir (environment.directory_downloads)),"app_name.apk");

        if(apkFile ! = null && apkFile.exists()) { apkFile.delete(); } DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl)); // setTitle request.settitle (title); // setDescription request.setDescription(desc); / / display notification bar after the completion of the request. SetNotificationVisibility (DownloadManager. Request. VISIBILITY_VISIBLE_NOTIFY_COMPLETED); request.setDestinationInExternalFilesDir(weakReference.get(), Environment.DIRECTORY_DOWNLOADS,"app_name.apk"); / / in the mobile phone to create a download folder on your SD card. / / the Environment getExternalStoragePublicDirectory (Environment. DIRECTORY_DOWNLOADS). The mkdir (); / / designated download to the SD card/download/my/directory / / request. SetDestinationInExternalPublicDir ("/codoon/"."codoon_health.apk");

        request.setMimeType("application/vnd.android.package-archive"); // mReqId = mDownloadManager.enqueue(request); } /** * cancel download */ public voidcancel() { mDownloadManager.remove(mReqId); } /** * corresponds to {@link Activity} */ public voidresumeParse () {// Set listening uri.parse ()"content://downloads/my_downloads")
        weakReference.get().getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"), true, mDownLoadChangeObserver); // Register broadcast, Weakreference.get (). RegisterReceiver (mDownloadReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); } /** * corresponds to {@link Activity#onPause()} ()}
     */
    public void onPause() {
        weakReference.get().getContentResolver().unregisterContentObserver(mDownLoadChangeObserver);
        weakReference.get().unregisterReceiver(mDownloadReceiver);
    }

    private void updateView() {
        int[] bytesAndStatus = new int[]{0, 0, 0};
        DownloadManager.Query query = new DownloadManager.Query().setFilterById(mReqId);
        Cursor c = null;
        try {
            c = mDownloadManager.query(query);
            if (c != null && c.moveToFirst()) {
                //已经下载的字节数
                bytesAndStatus[0] = c.getInt(c.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                //总需下载的字节数
                bytesAndStatus[1] = c.getInt(c.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                //状态所在的列索引
                bytesAndStatus[2] = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
            }
        } finally {
            if (c != null) {
                c.close();
            }
        }

        if(mUpdateListener ! = null) { mUpdateListener.update(bytesAndStatus[0], bytesAndStatus[1]); } Log.i(TAG,"Download Progress:" + bytesAndStatus[0] + "/" + bytesAndStatus[1] + "");
    }

    class DownloadChangeObserver extends ContentObserver {

        /**
         * Creates a content observer.
         *
         * @param handler The handler to run {@link #onChange} on, or null if none.*/ public DownloadChangeObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); updateView(); } } class DownloadReceiver extends BroadcastReceiver { @Override public void onReceive(final Context context, final Intent intent) { boolean haveInstallPermission; // Compatible with Android 8.0if(build.version.sdk_int >= build.version_codes.o) {haveInstallPermission = context.getPackageManager().canRequestPackageInstalls();if(! HaveInstallPermission) {/ / there is no authority / / popup window and go to the Settings page final authorization AndroidOInstallPermissionListener listener = newAndroidOInstallPermissionListener() {
                        @Override
                        public void permissionSuccess() {
                            installApk(context, intent);
                        }

                        @Override
                        public void permissionFail() {
                            ToastUtils.shortToast(context, "Authorization failed, application cannot be installed"); }}; AndroidOPermissionActivity.sListener = listener; Intent intent1 = new Intent(context, AndroidOPermissionActivity.class); context.startActivity(intent1); }else{ installApk(context, intent); }}else {
                installApk(context, intent);
            }

        }
    }

    /**
     * @param context
     * @param intent
     */
    private void installApk(Context context, Intent intent) {
        long completeDownLoadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);

        Logger.e(TAG, "Received a broadcast.");
        Uri uri;
        Intent intentInstall = new Intent();
        intentInstall.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intentInstall.setAction(Intent.ACTION_VIEW);

        if (completeDownLoadId == mReqId) {
            if(build.version.sdk_int < build.version_codes.m) {// 6.0 the following uri = mDownloadManager.getUriForDownloadedFile(completeDownLoadId); }else if(build.version.sdk_int < build.version_codes.n) {// 6.0-7.0 File apkFile = queryDownloadedApk(context, completeDownLoadId); uri = Uri.fromFile(apkFile); }else{/ / Android 7.0 above uri = FileProvider getUriForFile (context,"package_name.fileProvider",
                        new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "app_name.apk")); intentInstall.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } // Install application logger.e ("zhouwei"."Download complete");

            intentInstall.setDataAndType(uri, "application/vnd.android.package-archive"); context.startActivity(intentInstall); }} // Query downloaded APK in downLoadId, Public static File queryDownloadedApk(Context Context, Long Downdid) {File targetApkFile = null; DownloadManager downloader = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);if(downloadId ! = -1) { DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(downloadId); query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL); Cursor cur = downloader.query(query);if(cur ! = null) {if (cur.moveToFirst()) {
                    String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                    if (!TextUtils.isEmpty(uriString)) {
                        targetApkFile = new File(Uri.parse(uriString).getPath());
                    }
                }
                cur.close();
            }
        }
        returntargetApkFile; } public interface OnUpdateListener { void update(int currentByte, int totalByte); } public interface AndroidOInstallPermissionListener { void permissionSuccess(); void permissionFail(); }}Copy the code

It is very simple to use, as follows:

(1) Update prompt box: prompt users to update

 private void showUpdateDialog(final AppUpdateInfo updateInfo) {
        AppUpdateDialog dialog = new AppUpdateDialog(getContext());
        dialog.setAppUpdateInfo(updateInfo);
        dialog.setOnUpdateClickListener(new AppUpdateDialog.OnUpdateClickListener() {
            @Override
            public void update(final AppUpdateDialog updateDialog) {
                String title = "app name";
                String desc = "Version Update";

                mDownloadManager.setUpdateListener(new AppDownloadManager.OnUpdateListener() {
                    @Override
                    public void update(int currentByte, int totalByte) {
                        updateDialog.setProgress(currentByte, totalByte);
                        if((currentByte == totalByte) && totalByte ! = 0) { updateDialog.dismiss(); }}}); mDownloadManager.downloadApk(updateInfo.download_url, title, desc); }}); dialog.setCanceledOnTouchOutside(false);
        dialog.setCancelable(false);
        dialog.show();

    }

Copy the code

(2) Notice the corresponding methods in onResume and onPause:

 @Override
    public void onResume() {
        super.onResume();
        if (mDownloadManager != null) {
            mDownloadManager.resume();
        }
}

Copy the code
 @Override
    public void onPause() {
        super.onPause();
        if (mDownloadManager != null) {
            mDownloadManager.onPause();
        }

    }

Copy the code

[image uploading failed…(image-d8b11A-1524880080337)]

Seven,

This article summarizes some of the adaptation issues encountered with online app updates in the project. For Android 6.0 adaptation, if you don’t use DownloadManager, you probably won’t encounter this problem. 7.0 and 8.0 adaptations will be available either way.

This is the end of app online update version adaptation, if you have any questions, welcome to point out.

Link: https://www.jianshu.com/p/85913ed97af5, reprint please indicate the source

If the technical development can refer to the following article

Wechat small program development

Wechat small program development < 2 >

In this day and age, as a programmer, why should I learn small programs

Let’s develop a WanAndroid quick app

“Big Talk Architecture” Ali architects share technical essentials Java programmers need to break through

Believe in yourself, there is nothing impossible, only unexpected

Wechat official account: Terminal R&D Department