Android App detects new version, automatically downloads, installs and upgrades, and is compatible with Android 7.0 and above

Posted by EvilPrimate on Thu, 16 Jan 2020 06:52:13 +0100

Preface

Some companies may not go to the App store after developing an App, but they also need to regularly maintain and update later, so they will choose to publish the packaged apk to their own servers, and then build a version number table in the database, and then the rest will be handed over to you for android development. android itself needs to implement version detection and update. Because of the downloadm brought by android itself Manager can realize the download function, and it will be very simple to use. There is no need to write a lot of download and other related codes. However, after downloading, some of them are notified in the notice bar, and then users manually click to install. Some of them will enter the installation state after downloading. Users only need to confirm the installation. However, due to some high-level systems and low-level systems Automatic installation is different.

Android 7.0 or below, after downloading, it will automatically pop up the installation interface and prompt for installation;

Android 7.0 and above, do not automatically pop up the installation interface after downloading;

text

Download, tool class Util, and then top a static method downLoadApk(), version number request and comparison are omitted here.

/**
 * Update download apk
 * @param context  Context object
 * @param title    Program name
 * @param url       Download url address
 *
 */

public static long downLoadApk(Context context,String title,String url){

        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
        request.setDestinationInExternalFilesDir(context, Environment.DIRECTORY_DOWNLOADS,"ausee.apk");
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        // Set Notification information
        request.setTitle(title);
        request.setDescription("Please click open after downloading");
        request.setVisibleInDownloadsUi(true);
        request.allowScanningByMediaScanner();
        request.setMimeType("application/vnd.android.package-archive");

        // Instantiate DownloadManager object
        DownloadManager downloadManager = (DownloadManager) MyApp.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
        final long refrence = downloadManager.enqueue(request);

        return refrence;
}
The static method above can be downloaded, and it's OK to pass the url. Next, we'll deal with the rest. Note that the method above will return a long value,

When activity calls this method, you get the return value, and then build a broadcast receiver in activity. Because the above return value is a download id returned by DownloadManager after downloading. Each download task will return a unique id and send a broadcast. Here I define a method in activity: listener (I d) And build a broadcast receiver as follows:

private void listener(final long Id) {
    // Download completion event of registered broadcast monitoring system.
    IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
    broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            DownloadManager manager = (DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);
            // Here is the id of the download through the following method,
            long ID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
            // Here, we compare the passed id with the id obtained in the broadcast. If so, we will start to get the download path
            if (ID == Id) {

                DownloadManager.Query query = new DownloadManager.Query();
                query.setFilterById(Id);

                Cursor cursor = manager.query(query);
                if (cursor.moveToFirst()){
                    // Get file download path
                    String fileName = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));

                    // If the file name is not empty, it means that the file already exists, then install apk automatically
                    if (fileName != null){

                        openAPK(fileName);

                    }
                }
                cursor.close();
            }
        }
    };
    registerReceiver(broadcastReceiver, intentFilter);
}

Installation, automatic pop-up window

/**
 * Install apk
 * @param fileSavePath
 */
private void openAPK(String fileSavePath){
    File file=new File(Uri.parse(fileSavePath).getPath());
    String filePath = file.getAbsolutePath();
    Intent intent = new Intent(Intent.ACTION_VIEW);
    Uri data = null;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//Judge version is greater than or equal to 7.0
        // uri of the generated file,,
        // Note that the following parameter com.ausee.fileprovider adds. Fileprovider to the package name of apk,
        data = FileProvider.getUriForFile(LoginActivity.this, "com.ausee.fileprovider", new File(filePath));
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);// Apply a temporary authorization to the target
    } else {
        data = Uri.fromFile(file);
    }

    intent.setDataAndType(data, "application/vnd.android.package-archive");
    startActivity(intent);
}

fileprovider file

The above is basically OK, but the above parameter, com.ausee.fileprovider, needs to be noted and configured as follows.
First, create a new folder named XML under the project res file, and then create a new XML file: file_paths.xml; 
The content of xml is:
<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="name" path="."/>
</paths>

Manifest file

After it is written here, configure a provider tag in the manifest as follows: this way, you can:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.ausee.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

Take a closer look at the Android: authorities = "com. Authe. Fileprovider" (COM. Authe is your own package name). Is this the same as the previous parameter? Just because of this, the content here is also filled in like that. Add a fileprovider to the package name, and then configure the newly opened xml file in meta data!

Finish!!!


Original link: https://blog.csdn.net/I123456789T/article/details/81584352

105 original articles published, 65 praised, 220000 visitors+
Private letter follow

Topics: Android FileProvider xml REST