Install .apk files Programmatically

 

    private void download() {
        try {

            if (updateInfo == null) {
                dismiss();
                return;
            }

            String fileUrl = updateInfo.baseUrl + updateInfo.file;
            URL url = new URL(fileUrl);

            URLConnection conection = url.openConnection();
            conection.connect();

            // getting file length
            int lenghtOfFile = conection.getContentLength();

            // in kb
            final int fLengthOfFile = lenghtOfFile / 1000;

            // initialize progressbar
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    progressBarUpdate.setProgress(0);
                    String progress = 0 + "%";
                    textViewProgressPercent.setText(progress);
                    String bStr = String.format(Locale.US, "%d/%d", 0, fLengthOfFile);
                    textViewProgressBytes.setText(bStr);
                }
            });

            // input stream to read file - with 8k buffer
            InputStream input = new BufferedInputStream(url.openStream(), 8192);

            File folder = getContext().getFilesDir();

            String path = folder.getAbsolutePath() + "/" + updateInfo.file;
            File saveFile = new File(path);

            saveFile.createNewFile();

            // Output stream to write file
            OutputStream output = new FileOutputStream(saveFile, false);

            byte data[] = new byte[1024];

            int total = 0;
            int count = 0;

            while ((count = input.read(data)) != -1) {

                if (cancelCalled) {
                    dismiss();
                    return;
                }

                total += count;

                final int progressPercent = (int) ((total * 100) / lenghtOfFile);
                final int fTotal = total / 1000;


                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        progressBarUpdate.setProgress(progressPercent);
                        String progress = progressPercent + "%";
                        textViewProgressPercent.setText(progress);
                        String bStr = String.format(Locale.US, "%d/%d", fTotal, fLengthOfFile);
                        textViewProgressBytes.setText(bStr);
                    }
                });

                // writing data to file
                output.write(data, 0, count);
            }

            // flushing output
            output.flush();

            // closing streams
            output.close();
            input.close();

            saveFile = new File(path);

            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                saveFile.setReadable(true, false);
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.setDataAndType(Uri.fromFile(saveFile), "application/vnd.android.package-archive");
                getContext().getApplicationContext().startActivity(intent);
            } else {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                Uri fileUri = FileProvider.getUriForFile(getContext(),
                        "ir.mhdr.provider",
                        saveFile);

                intent.setDataAndType(fileUri, "application/vnd.android.package-archive");
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                startActivity(intent);
            }


            dismiss();

        } catch (Exception e) {
            e.printStackTrace();
            //FirebaseCrash.report(e);
            dismiss();
        }
    }

AndroidManifest.xml

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

file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="bmi.apk" path="" />
</paths>

the reason that my path is empty is according to google documents :

<files-path name="name" path="path" />

Represents files in the files/ subdirectory of your app’s internal storage area. This subdirectory is the same as the value returned by Context.getFilesDir() and because the path is relative so while my file is stored in the root directory of getFilesDir() the path should be empty.

References
https://developer.android.com/reference/android/support/v4/content/FileProvider.html
https://stackoverflow.com/questions/4967669/android-install-apk-programmatically
https://stackoverflow.com/questions/3568142/android-how-to-open-an-apk-file-after-downloading-for-auto-update
https://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed