1

I have an app which is not on Play Store. I was earlier able to start the app installer by the following code:

In Activity:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/app_path/app_name.apk")), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);

Now, I've changed the targetSdkVersion to 25, and made some changes in my code but I'm getting the following error:

FATAL EXCEPTION: AsyncTask #1 Process: com.android.packageinstaller, PID: 6499 java.lang.RuntimeException: An error occurred while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:326) at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354) at java.util.concurrent.FutureTask.setException(FutureTask.java:223) at java.util.concurrent.FutureTask.run(FutureTask.java:242) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:244) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) at java.lang.Thread.run(Thread.java:761) Caused by: java.lang.SecurityException: Permission Denial: opening provider in.namespace.appname.comp.GenericFileProvider from ProcessRecord{ba35e80 6499:com.android.packageinstaller/u0a17} (pid=6499, uid=10017) that is not exported from uid 10076 at android.os.Parcel.readException(Parcel.java:1684) at android.os.Parcel.readException(Parcel.java:1637) at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:4213) at android.app.ActivityThread.acquireProvider(ActivityThread.java:5535) at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2239) at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1517) at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1131) at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:984) at android.content.ContentResolver.openInputStream(ContentResolver.java:704) at com.android.packageinstaller.PackageInstallerActivity$StagingAsyncTask.doInBackground(PackageInstallerActivity.java:804) at com.android.packageinstaller.PackageInstallerActivity$StagingAsyncTask.doInBackground(PackageInstallerActivity.java:795) at android.os.AsyncTask$2.call(AsyncTask.java:306) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:244)  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)  at java.lang.Thread.run(Thread.java:761) 

These are the changes I've made in my code:

in Manifest:

<permission
    android:name="in.namespace.appname.fp.READ"
    android:description="@string/file_provider_permission_description"
    android:label="in.namespace.appname.READ_FILE"/>

<uses-permission android:name="in.namespace.appname.fp.READ"/>

<application
    ...
    ...
    <provider
        android:name=".comp.GenericFileProvider"
        android:authorities="in.namespace.appname.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true"
        android:readPermission="in.namespace.appname.fp.READ">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
    </provider>
    .
    .
</application>

Create an empty class GenericFileProvider in directory comp:

public class GenericFileProvider extends FileProvider { }

Changed the Activity code to:

File updatedApk = new File(Environment.getExternalStorageDirectory() + "/file_path/appname.apk");
Uri updatedApkUri =  GenericFileProvider.getUriForFile(
     AppUpdateActivity.this,
     "in.namespace.appname.fileprovider",
     updatedApk);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(updatedApkUri, "application/vnd.android.package-archive");

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);

What's causing this error and how can I fix this ?

EDIT #1

Changed my manifest:

<provider
        android:name=".comp.GenericFileProvider"
        android:authorities="in.namespace.appname.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
    </provider>
mrid
  • 5,782
  • 5
  • 28
  • 71
  • Does this answer your question? [Android - file provider - permission denial](https://stackoverflow.com/questions/24467696/android-file-provider-permission-denial) – Sam Jul 26 '22 at 23:42

3 Answers3

2

In my case, for starting Intent has this flag Intent.FLAG_ACTIVITY_NEW_TASK and it was causing issue. So i removed that flag from the intent, and it started working.

Working sample code

String myPackageName = getApplicationContext().getPackageName();
File f = new File(Environment.getExternalStorageDirectory() + "/Download/" + downloadName);
Uri mediaUri = FileProvider.getUriForFile(getApplicationContext(), myPackageName + ".provider", f);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(mediaUri, "application/vnd.android.package-archive");
startActivity(intent);
Unnikuttan Kaveth
  • 73
  • 1
  • 1
  • 10
0

Remove android:readPermission="in.namespace.appname.fp.READ".

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Still the same error. On device, it says `Package installer has stopped` – mrid Nov 17 '17 at 12:12
  • @mrid: Double-check the stack trace, and confirm that you are still getting `GenericFileProvider... that is not exported...` as the error. It's possible that you need to completely uninstall and reinstall the app, though I would not expect that to be required here. – CommonsWare Nov 17 '17 at 12:14
  • yea, I'm getting the same error: `GenericFileProvider....not supported`, even uninstall didn't help – mrid Nov 17 '17 at 12:17
  • @mrid: `not supported` does not appear in your current stack trace. I suggest that you edit your question to show the revised manifest and the new stack trace. – CommonsWare Nov 17 '17 at 12:37
  • my bad, I accidentally wrote `not supported`. the error is the same as in question: `java.lang.SecurityException: Permission Denial: opening provider....that is not exported...` – mrid Nov 17 '17 at 12:42
  • @mrid: Hmmm... well, you definitely needed to remove that permission, as otherwise the package installer would not have permission to use your provider. You could try `ACTION_INSTALL_PACKAGE` instead of `ACTION_VIEW`, though I would not expect it to affect this problem. Make sure that you are passing in the correct `File` to `getUriForFile()`. I have used a `FileProvider` to install APKs on Android 7.0+, so I know that it works, but I am not certain where else your code may be going wrong. – CommonsWare Nov 17 '17 at 12:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/159232/discussion-between-mrid-and-commonsware). – mrid Nov 17 '17 at 13:05
0
 Uri updatedApkUri =  GenericFileProvider.getUriForFile(
 AppUpdateActivity.this,
 "in.namespace.appname.fileprovider",
 updatedApk);

Please change your code to this

 Uri updatedApkUri =  GenericFileProvider.getUriForFile(
 AppUpdateActivity.this,
 BuildConfig.APPLICATION_ID + ".provider",
 updatedApk);

and manage permissions like this

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
                } else if (Build.VERSION.SDK_INT >= 
Build.VERSION_CODES.JELLY_BEAN) {
                    val clip = ClipData.newUri(contentResolver, "A photo", 
mImageCaptureUri)
                    intent.clipData = clip
                    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
                } else {
                    val resInfoList = 
 packageManager.queryIntentActivities(intent, 
 PackageManager.MATCH_DEFAULT_ONLY)
                    for (resolveInfo in resInfoList) {
                        val packageName = 
 resolveInfo.activityInfo.packageName
                        grantUriPermission(packageName, mImageCaptureUri, 
 Intent.FLAG_GRANT_WRITE_URI_PERMISSION or 
 Intent.FLAG_GRANT_READ_URI_PERMISSION)
                    }
                }
            }
            intent.putExtra("return-data", true)