During APP installation in the project, the “package parsing error” error occurs, and there is no obvious fatal information in the log. Therefore, the system should report an error.

Android development, catch the log is a necessary skill, no error log, then catch the full amount of logcat log, started crazy to see the log, found an error.

Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{ca55219 13782:com.android.packageinstaller/u0a32} (pid=13782, uid=10032) that is not exported from UID 10076

Ha, ha, ha, there is an error log, you can search, the problem is close at hand. FLAG_GRANT_WRITE_URI_PERMISSION in addition to intent. FLAG_GRANT_WRITE_URI_PERMISSION. If you think about it, I this is just a simple installation of an App, did not write data ah, in order to be afraid of the pit left by predecessors, or add this permission, run the program, and sure enough is useless, or need to continue.

I wonder if the FileProvider has permissions. Check if the FileProvider has permissions

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationid}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>
Copy the code

From the configuration file, all the permissions have been given to the Filepaths, so I checked the filepaths configuration file.

<external-path
        name="external_storage_root"
        path="." />
Copy the code

To briefly describe the profile, what each field represents.

Path: Paths that require temporary authorization (. Represents all paths)

Name: You give the access path a name

So what does the tag external-path mean? Represents external storage. The details are as follows:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <root-path name="root" path="" />// represents the root directory of the device new File("/");<files-path name="files" path="" /> //context.getFilesDir()
    <cache-path name="cache" path="" /> //context.getCacheDir()
    <external-path name="external" path="" /> //Environment.getExternalStorageDirectory()
    <external-files-path name="name" path="path" /> //context.getExternalFilesDirs()
     <external-cache-path name="name" path="path" /> //getExternalCacheDirs()
</paths>
Copy the code

Now that I understand, what I specified is not wrong, but it still does not work, I re-read the error message, found in the error message

that is not exported
Copy the code

If you want to set the parameters specified on the provider exported, you can see that it is not a problem. What the hell is this? Take a look at the log:

 java.lang.SecurityException: Provider must not be exported
Copy the code

You cannot set the value of exported to true.

Let me reframe the adaptation of the APP installation. The FileProvider adaptation actually has three stages.

There are before 6.0, 7.0, and after 7.0, which means you don’t need to use the FileProvider at all before 7.0, just before 6.0

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri.fromFile(new File(installPath)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
Copy the code

In 7.0, however, Google changed its policy and needed to use FileProvider,

Intent intent = new Intent();
Uri uri = null;
uri = FileProvider.getUriForFile(context, context.getPackageName()+".fileprovider".new File(filesPath));
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_VIEW);
Copy the code
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${APPLICATIONID}.FileProvider"
    android:exported="false"
    android:grantUriPermissions="true"
    tools:replace="android:authorities">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_path" />
</provider>
Copy the code

Authorities: App package name. fileProvider

GrantUriPermissions: Must be true to grant temporary access to the URI

Google has changed again at 8.0 and above, damn it. When installing the APP, you also need to copy the APP to the context.getFilesdir () directory, but you still need the FileProvider as follows:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addCategory("android.intent.category.DEFAULT");
Uri contentUri = FileProvider.getUriForFile(context, "com.iflytek.appstroe2.fileprovider".new File(dstPath));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(contentUri, context.getContentResolver().getType(contentUri));
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
    context.grantUriPermission(resolveInfo.activityInfo.packageName, contentUri,Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
context.startActivity(intent);
Copy the code

Here is a clear comb, but MY problem is still not solved. I looked at my system version, found that the nima is Android8.0, but I have been working on Android7.0, I according to the method of Android8.0 tried, found that it can.

Conclusion: From the process of solving this problem, we can see that even if there is no solution for a small problem, we still need to return to the essence of the problem, so that we can give a targeted solution.