javaandroidandroid-studiobroadcastreceiverandroid-download-manager

Install new apk after download by Download Manager and exit from running app


I have create android app using java. But i want upgrade my app without playstore. I try to download manually but it make more time to do that. I want make it simply. So i use download manager for download new file from my server. And now i donno how to install automatically my new app.

What shoul i do ?

This is manifest :

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28"/>

<application
        ...
        android:supportsRtl="true"
        android:usesCleartextTraffic="true"
        android:requestLegacyExternalStorage="true"
        ...
</application>

And this what i have tried for download file :

String destination = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/";
destination += name_app_list;

final Uri uri = Uri.parse("file://" + destination);

final DownloadManager.Request request = new DownloadManager.Request(Uri.parse("url" + name_app_list));
request.setDestinationUri(uri);
request.setMimeType("application/vnd.android.package-archive");
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);

final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
final long downloadID = manager.enqueue(request);

And this i have tried to install that apk :

BroadcastReceiver onComplete = new BroadcastReceiver() {
   public void onReceive(Context ctxt, Intent intent) {
      Intent intez = new Intent(Intent.ACTION_VIEW);
      intez.setDataAndType(Uri.fromFile(new File(name_app_list)), "application/vnd.android.package-archive");
      startActivity(intez);
   }
};

registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

This Error :

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.dsi.updateapp/com.dsi.updateapp.MainActivity}: android.os.FileUriExposedException: file:///storage/emulated/0/Download/1.4/phd.apk exposed beyond app through Intent.getData()
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6077)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
     Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Download/1.4/phd.apk exposed beyond app through Intent.getData()
        at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799)
        at android.net.Uri.checkFileUriExposed(Uri.java:2346)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:8933)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:8894)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1517)
        at android.app.Activity.startActivityForResult(Activity.java:4224)
        at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:597)
        at android.app.Activity.startActivityForResult(Activity.java:4183)
        at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:583)
        at android.app.Activity.startActivity(Activity.java:4507)
        at android.app.Activity.startActivity(Activity.java:4475)
        at com.dsi.updateapp.MainActivity.openFile(MainActivity.java:202)
        at com.dsi.updateapp.MainActivity.onCreate(MainActivity.java:109)
        at android.app.Activity.performCreate(Activity.java:6662)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)

Solution

  • After I search all day, i got the solution Thank you for comment my post :) This is my solution Add to manifest :

    <provider
       android:authorities="${applicationId}.provider"
       android:name="androidx.core.content.FileProvider"
       android:exported="false"
       android:grantUriPermissions="true">
       <meta-data 
          android:name="android.support.FILE_PROVIDER_PATHS"
          android:resource="@xml/provider_paths"/>
    
    </provider>
    

    add new dir and file xml/provider_paths.xml

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

    And then in Activity :

    BroadcastReceiver onComplete = new BroadcastReceiver() {
       public void onReceive(Context ctxt, Intent intent) {
          Uri uri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider", destination);
          Intent intents = new Intent(Intent.ACTION_VIEW);
          intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
          intents.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
          intents.setDataAndType(uri,"application/vnd.android.package-archive");
          startActivity(intents);
       }
    };
    
    registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));