I have been working on testing some packages that I do not have the source code for, and one of the packages is normally launched by pressing three buttons for three seconds. When I try to launch the package using the typical method, I get a java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Intent android.content.Intent.addFlags(int)
error. Below is my code
@Before
public void setup() {
//Initialize UiDevice instance
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
mDevice = UiDevice.getInstance(instrumentation);
mDevice.pressHome();
final String launcherPackage = mDevice.getLauncherPackageName();
assertThat(launcherPackage, notNullValue());
mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);
Context context = InstrumentationRegistry.getTargetContext();
final Intent intent = context.getPackageManager()
.getLaunchIntentForPackage(DEALER_DIAG_PACKAGE);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
mDevice.wait(Until.hasObject(By.pkg(DEALER_DIAG_PACKAGE).depth(0)), LAUNCH_TIMEOUT);
}
I tried using getContext
instead of getTargetContext
, however someone pointed out to me that if the intents are not exported, I will not be able to launch the package this way no matter what I do. I tried to get the package names by using the command adb logcat ActivityManager:V *:F
as well as adb shell pm list packages -f
--------- beginning of main
I/ActivityManager( 2296): START u0 {flg=0x10000000
cmp=com.android.systemui/.usb.UsbDebuggingActivity (has extras)} from uid
1000 on display 0
I/ActivityManager( 2296): Displayed
com.android.systemui/.usb.UsbDebuggingActivity: +184ms
I/ActivityManager( 2296): START u0 {act=android.intent.action.MAIN cat=
[android.intent.category.HOME] flg=0x10200000
cmp=com.android.launcher3/.Launcher} from uid 1000 on display 0
I/ActivityManager( 2296): START u0
{act=com.REDACTED.auto.diagnostics.dealer.MAIN flg=0x10800000
cmp=com.REDACTED.auto.diagnostics/.dealer.MainActivity} from uid 1000 on
display 0
I/ActivityManager( 2296): Start proc
20943:com.REDACTED.auto.diagnostics/1000 for activity
com.REDACTED.auto.diagnostics/.dealer.MainActivity
I/ActivityManager( 2296): Displayed
com.REDACTED.auto.diagnostics/.dealer.MainActivity: +572ms
Does anyone have any input as to why I am getting this error? I have tried using every package name listed in the logcat dump with no success. Any input would be appreciated.
If you want to launch another app just first check if this app is installed, or you'll get a NullPointerException
, then launch the app by an intent with the package options:
Just like this:
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.domain.anotherapp");
if (launchIntent != null) {
startActivity(launchIntent);//null pointer check in case package name was not found
}
This will launch the app with the default launch activity, if you want to launch a specific activity you already have to know how to handle the requirements of the other app side or will simply crash or not work (probably you might need to pass some variable or some data to represent previous information of this app), anyway, to open this specific activity you have to use ComponentName
.
The ComponentName
constructor taking two String
s can be used to refer to a component in another application. But, the first argument is not the package name of the class; it is the package name of the application---the package
attribute of the manifest
element in that application's AndroidManifest.xml
. So your first example should be
ComponentName cn = new ComponentName("com.domain.anotherapp",
"com.domain.anotherapp.widget.WidgetProvider");
That constructor could certainly be used to refer to components in your own application, but since you already have hold of a Context
from your own application you might as well use it and use one of the other constructors. In my opinion, the one taking a Class
should be preferred whenever usable. You could use the one taking a String
if you only know the class dynamically for some reason; in that case, it should take the fully-qualified class name as above.
The complete use to launch by an intent (without handle the null pointer exception for an incorrect passed information):
Intent launchIntent = new Intent(Intent.ACTION_MAIN);
launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName("com.domain.anotherapp",
"com.domain.anotherapp.widget.WidgetProvider");
launchIntent.setComponent(cn);
startActivity(launchIntent);
Reference: https://developer.android.com/reference/android/content/ComponentName.html
I figured out a method that worked for me, though Brandon's could possibly work on another solution. Here is my solution:
Intent intent = new Intent("com.REDACTED.auto.diagnostics.dealer.MAIN");
intent.setClassName("com.REDACTED.auto.diagnostics",
"com.REDACTED.auto.diagnostics.dealer.MainActivity");
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Context c = InstrumentationRegistry.getContext();
c.startActivity(intent);
This possibly does the same thing that Brandon's solution does, however less abstracted.
User contributions licensed under CC BY-SA 3.0