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