Android app version updates function modules to solve 8.0 and permission issues

Keywords: Mobile Android xml FileProvider encoding

This article mainly solves some problems of app version updating function, refers to some codes, mainly 8.0 problems encountered online corresponding articles are relatively few, so specially write an article to summarize.

Functional requirements: A download function with a progress bar, and the installation interface can be automatically jumped after the download is completed.

1. Download the apk file

/**
         * File download
         *
         * @param url
         */

        public void downFile (String url, String version){

            final ProgressDialog progressDialog = new ProgressDialog(getActivity());
            progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            progressDialog.setTitle("Downloading");
            progressDialog.setMessage("Please wait a moment....");
            progressDialog.setProgress(0);
            progressDialog.setMax(100);
            progressDialog.show();
            progressDialog.setCancelable(false);
            DownloadUtil.get().download(url, Environment.getExternalStorageDirectory().getAbsolutePath(), "tutor"+version + ".apk", new DownloadUtil.OnDownloadListener() {
                @Override
                public void onDownloadSuccess(File file) {
                    if (progressDialog != null && progressDialog.isShowing()) {
                        progressDialog.dismiss();
                    }
                    install(file.getAbsolutePath());
                    //Download completed for related logical operations
                }
                @Override
                public void onDownloading(int progress) {
                    progressDialog.setProgress(progress);
                }
                @Override
                public void onDownloadFailed(Exception e) {
                    TabletApp.prompt("Download exception");
                    //Download exceptions for related prompts
                }
            });
        }

Need download tool classes:

/**
 * File Download Tool Class (Singleton Mode)
 * <p>
 * Created on 2017/10/16.
 */

public class DownloadUtil {
    private static DownloadUtil downloadUtil;
    private final OkHttpClient okHttpClient;

    public static DownloadUtil get() {
        if (downloadUtil == null) {
            downloadUtil = new DownloadUtil();
        }
        return downloadUtil;
    }

    private DownloadUtil() {
        okHttpClient = new OkHttpClient();
    }

    /**
     * @param url          Download connection
     * @param destFileDir  Downloaded File Storage Directory
     * @param destFileName Download file name
     * @param listener     Download monitoring
     */

    public void download(final String url, final String destFileDir, final String destFileName, final OnDownloadListener listener) {
        Request request = new Request.Builder().url(url).build();

        okHttpClient.newCall(request).enqueue(new Callback() {

            @Override
            public void onFailure(Call call, IOException e) {
                // Download Failure Monitor Callback
                listener.onDownloadFailed(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                // Directory for storing downloaded files

                File dir = new File(destFileDir);
                if (!Environment.getExternalStorageDirectory().canRead()){
                    TabletApp.prompt("No authority");
                }
                if (!dir.exists()) {

                    dir.mkdirs();

                }
                File file = new File(dir, destFileName);
                try {
                    is = response.body().byteStream();
                    long total = response.body().contentLength();
                    fos = new FileOutputStream(file);
                    long sum = 0;
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / total * 100);
                        // Update progress bar in download
                        listener.onDownloading(progress);
                    }
                    fos.flush();
                    // Download complete
                    listener.onDownloadSuccess(file);
                } catch (Exception e) {
                    listener.onDownloadFailed(e);
                } finally {
                    try {
                        if (is != null)
                            is.close();
                    } catch (IOException e) {
                    }
                    try {
                        if (fos != null)
                            fos.close();
                    } catch (IOException e) {
                    }
                }
            }
        });

    }
    public interface OnDownloadListener {

        /**
         * @param file Download successful files
         */
        void onDownloadSuccess(File file);

        /**
         * @param progress Download progress
         */
        void onDownloading(int progress);

        /**
         * @param e Download exception information
         */
        void onDownloadFailed(Exception e);
    }

}

2. Installation method

Because 7.0 "In order to improve the security of private files, access to private directories for Android 7.0 or higher versions of applications is restricted", temporary access to URI s is required.

1) Create a new file file file_paths.xml in res/xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <root-path name="root_path" path="."/>
        <external_path name="akp" path="" />
    </paths>
</resources>

2) Add provider configuration to the application tag in Android Manifest. XML

<provider
            android:name="android.support.v4.content.FileProvider"
            //Generally use package names, which need to be consistent with the following
            android:authorities="com.xxx.xxx.xxx"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

In Android 8.0, permission management has been strengthened. Switches for applications from unknown sources have been removed and replaced by management lists for applications from unknown sources. If you want to install an app from a developer you trust, you need to manually grant permission to "install unknown applications" every time.

1) Application for jump permission

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

2) Jump method

 /**
     * Jump to Settings - Allow Installation of Unknown Sources - Page
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    private void startInstallPermissionSettingActivity() { //Note that this is the 8.0 new API
        Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        getActivity().startActivity(intent);
    }

Integrate installation methods.

private void install (String filePath){
            Log.i(TAG, "Start the installation: " + filePath);
            File apkFile = new File(filePath);
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                Log.w(TAG, "Version greater than N ,Start using fileProvider Installation");
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                Uri contentUri = FileProvider.getUriForFile(
                        getActivity()
                        , "com.xxx.xxx.fileprovider"
                        , apkFile);
                intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    boolean hasInstallPermission = getContext().getPackageManager().canRequestPackageInstalls();
                    if (!hasInstallPermission) {
                        startInstallPermissionSettingActivity();

                    }
                }



            } else {
                Log.w(TAG, "Normal installation");
                intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
            }
            try {
                getActivity().startActivity(intent);
            } catch (Exception e) {
                Log.d(TAG, e.toString());
            }
        }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void startInstallPermissionSettingActivity() { //Note that this is the 8.0 new API
        Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        getActivity().startActivity(intent);
    }

Storage card read permissions that may be encountered during the intermediate process:

<! - Write to Extended Storage, Write to Extension Card, Write to Cache Location Data - > Write to Extension Card.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<! - SD Card Rights - >
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Some of the network privileges are not written. The first time you write an article, if you write badly, please correct it.

Posted by KindMan on Sat, 26 Jan 2019 00:39:13 -0800