简体   繁体   中英

PackageInstaller crash when unable to resolve content provider with "downloads" authority

For a bit of background, I'm writing an Android app in Xamarin for an enterprise, that should be able to update itself, rather than through the play store. There's one device in particular that isn't able to update itself and I can't figure out why.

The code for the update looks like this:

            try
            {
                var intent = new Intent(Intent.ActionInstallPackage);
                intent.SetFlags(ActivityFlags.NewTask);
                var file = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory.Path + "/com.mycompany.appname.apk");
                var uri = FileProvider.GetUriForFile(this, "com.mycompany.appname.update_file_provider", file);
                GrantUriPermission("com.google.android.packageinstaller", uri, ActivityFlags.GrantReadUriPermission);
                intent.SetDataAndType(uri, "application/vnd.android.package-archive");
                var pendingIntent = PendingIntent.GetActivity(this, 0, intent, 0);
                var notification = GetNotificationBuilder(installedVersion, latestVersion, this)
                    .SetContentText("Download complete.")
                    .AddAction(new NotificationCompat.Action(Resource.Drawable.ic_note_add_black_24dp, "Install", pendingIntent))
                    .SetAutoCancel(true)
                    .Build();
                NotificationManagerCompat.From(this).Notify(NotificationId, notification);
                StopSelf();
            }
            catch (Exception e)
            {
                var notification = GetNotificationBuilder(installedVersion, latestVersion, this)
                    .SetContentText("Failed to install update: " + e.Message)
                    .SetAutoCancel(true)
                    .Build();
                NotificationManagerCompat.From(this).Notify(NotificationId, notification);
                StopSelf();
                return;
            }

When it runs, I get a message saying, "PackageInstaller has stopped." The stacktrace shows that this is happening as a result of an NPE in the package installer app:

12-02 17:37:17.153  4897  4897 E AndroidRuntime: FATAL EXCEPTION: main
12-02 17:37:17.153  4897  4897 E AndroidRuntime: Process: com.google.android.packageinstaller, PID: 4897
12-02 17:37:17.153  4897  4897 E AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.google.android.packageinstaller/com.android.packageinstaller.InstallStart}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.ComponentName android.content.pm.ComponentInfo.getComponentName()' on a null object reference
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2785)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2863)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at android.app.ActivityThread.-wrap11(Unknown Source:0)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1596)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at android.os.Handler.dispatchMessage(Handler.java:106)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at android.os.Looper.loop(Looper.java:164)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at android.app.ActivityThread.main(ActivityThread.java:6537)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at java.lang.reflect.Method.invoke(Native Method)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:465)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
12-02 17:37:17.153  4897  4897 E AndroidRuntime: Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.ComponentName android.content.pm.ComponentInfo.getComponentName()' on a null object reference
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at com.android.packageinstaller.InstallStart.isSystemDownloadsProvider(InstallStart.java:230)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at com.android.packageinstaller.InstallStart.getOriginatingUid(InstallStart.java:222)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at com.android.packageinstaller.InstallStart.onCreate(InstallStart.java:73)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at android.app.Activity.performCreate(Activity.java:7023)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at android.app.Activity.performCreate(Activity.java:7014)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2738)
12-02 17:37:17.153  4897  4897 E AndroidRuntime:        ... 9 more

For the record: this particular device is running Android 8.1. I've tested this with other devices running Android 8.0, Android 10, and Android 7 with no issues, but I don't have any other devices with that exact Android version to test with.

Edit I realize that I should explain a little bit more about the title. I've actually looked into the source code for the PackageInstaller app , around where that stack trace appears, and it appears that this line is the reason for this NPE:

final String downloadProviderPackage = getPackageManager().resolveContentProvider(
                DOWNLOADS_AUTHORITY, 0).getComponentName().getPackageName();

DOWNLOADS_AUTHORITY is a constant string with the value "downloads" , and the call to resolveContentProvider() is returning null. What isn't clear is why this occurs for this particular device, and not for others, or how to fix it.

The problem turned out to be that the download manager had been disabled. It appears to be an issue only in android 8.0 and 8.1. I'm still not sure how it became disabled to begin with, but my solution was to use the null check as recommended by blackapps, and included a prompt for the user to re-enable it if this is detected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM