6

I have a feature to be implemented: install an apk programmatically. Code I'm using:

ComponentName comp = new ComponentName("com.android.packageinstaller", "com.android.packageinstaller.PackageInstallerActivity");
Intent newIntent = new Intent(callingIntent);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
newIntent.setComponent(comp);

The callingIntent contains an apk from another service.

On Android 6.0 (MPA44G, Nexus 5), this intent is crashing. Logcat:

08-20 14:58:56.127 26222 26222 E AndroidRuntime: Caused by: android.content.ActivityNotFoundException: Unable to find explicit activity class {com.android.packageinstaller/com.android.packageinstaller.PackageInstallerActivity}; have you declared this activity in your AndroidManifest.xml?

On Lollipop- devices, the above code is working fine.

Has Google completely removed the PackageInstallerActivity? Is there any workaround to programmatically install an apk specifically on Android 6.0?

Reference: Issue 3017: Unable to find explicit activity class com.android.packageinstaller.PackageInstallerActivity

Song
  • 504
  • 7
  • 17

5 Answers5

2

I got the answer. Intent.ACTION_INSTALL_PACKAGE is a better choice. If your app is registered as a package installer, use the sample code below to bypass a chooser dialog:

intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData(Uri.fromFile(file));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

If you want to use the standard package installer, use the following code:

File apkFile = new File(apkFileString);
Intent intent = new Intent(Intent.ACTION_VIEW); 
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");  
mContext.startActivity(intent);  
Song
  • 504
  • 7
  • 17
2

As you noticed the package path was incorrect and not specifying it will get rid of the crash. We now have

API <= 22 com.android.packageinstaller

API >= 23 com.google.android.packageinstaller

You can find any system app path on a device with adb. An example of me looking for a new package installer on a Nexus 5X looks like this.

$ adb shell 'pm list packages -f install'

package:/data/app/android.autoinstalls.config.google.nexus-1/base.apk=android.autoinstalls.config.google.nexus
package:/system/app/CertInstaller/CertInstaller.apk=com.android.certinstaller
package:/system/priv-app/GooglePackageInstaller/GooglePackageInstaller.apk=com.google.android.packageinstaller
Abhinav Singh Maurya
  • 3,313
  • 8
  • 33
  • 51
Adam Wigren
  • 383
  • 2
  • 11
  • Nexus 5X running android version 6.0.1 (api 23): com.google.android.packageinstaller. Nexus 5 running android 6.0.1 (api 23): com.android.packageinstaller. Checking API level is NOT a guaranteed method to determine that package name – Bryan Johnson Jun 17 '16 at 20:25
  • @Bryan Johnson are you really right? you posted 2 equal versions with 2 different results? Are you sure it was not a preview version on one of them? Is this still actual? – David Oct 27 '16 at 11:53
  • @David There are devices out there with "wrong" path. I'd add fallbacks to both of them. Retrying with the other path. – Adam Wigren Oct 27 '16 at 18:55
  • @David Unfortunately neither of the devices were a preview or any other special flavor of android. The only other thing I'd add is that the Nexus 5 was upgraded from android 5.0 to 6.0 at some point prior to my testing. If you need to just install an app, use Adam's answer where he doesn't specify that package name. Otherwise you should try to use that 'adb shell' command to interrogate the device. – Bryan Johnson Oct 31 '16 at 18:31
1

In addition to @Adam Wigren answer:
In Android 6 the packge name was changed but not the activity

ComponentName comp; 
if(android.os.Build.VERSION.SDK_INT < 23){
    comp = new ComponentName("com.android.packageinstaller", "com.android.packageinstaller.PackageInstallerActivity"); 
}else{
    comp = new ComponentName("com.google.android.packageinstaller", "com.android.packageinstaller.PackageInstallerActivity"); 
}

Intent newIntent = new Intent(callingIntent);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
newIntent.setComponent(comp);
NickF
  • 5,637
  • 12
  • 44
  • 75
1

To avoid : ActivityNotFoundException using Intent.ACTION_INSTALL_PACKAGE

 ComponentName comp;
File apkFile = new File(apkFileString);
Intent intent = new Intent(Intent.ACTION_VIEW); 
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");  

if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1/*23*/){
 comp = new ComponentName("com.android.packageinstaller", "com.android.packageinstaller.PackageInstallerActivity");
}else{
 comp = new ComponentName("com.google.android.packageinstaller", "com.android.packageinstaller.PackageInstallerActivity");
}

intent.setComponent(comp);
startActivity(intent);
Jorgesys
  • 124,308
  • 23
  • 334
  • 268
0

You can just open apk file in android6.0. see demo code

Community
  • 1
  • 1