通过包名启动 Activity
Launching Activities via package names
我一直在测试一些我没有源代码的包,其中一个包通常通过按三个按钮三秒钟来启动。当我尝试使用典型方法启动程序包时,出现 java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Intent android.content.Intent.addFlags(int)
错误。下面是我的代码
@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);
}
我尝试使用 getContext
而不是 getTargetContext
,但是有人向我指出,如果不导出意图,我将无法以这种方式启动包,无论我怎样做。我试图通过使用命令 adb logcat ActivityManager:V *:F
以及 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
有人知道我为什么会收到此错误吗?我尝试使用 logcat 转储中列出的每个包名称,但没有成功。如有任何意见,我们将不胜感激。
如果您想启动另一个应用程序,请先检查是否已安装此应用程序,否则您将获得 NullPointerException
,然后通过 intent 启动该应用程序使用包选项:
就像这样:
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.domain.anotherapp");
if (launchIntent != null) {
startActivity(launchIntent);//null pointer check in case package name was not found
}
这将使用默认启动 activity 启动应用程序,如果您想启动特定的 activity 您已经知道如何处理其他应用程序端的要求,或者只是崩溃或不工作(可能你可能需要传递一些变量或一些数据来表示这个应用程序的先前信息),无论如何,要打开这个特定的 activity 你必须使用 ComponentName
.
带两个String
的ComponentName
构造函数可用于引用另一个应用程序中的组件。但是,第一个参数不是 class 的包名;它是应用程序的包名称——该应用程序 AndroidManifest.xml
中 manifest
元素的 package
属性。所以你的第一个例子应该是
ComponentName cn = new ComponentName("com.domain.anotherapp",
"com.domain.anotherapp.widget.WidgetProvider");
该构造函数当然可以用于引用您自己的应用程序中的组件,但由于您已经从自己的应用程序中获取了 Context
,因此您不妨使用它并使用其他构造函数之一.在我看来,只要可用,应该首选带 Class
的那个。如果您出于某种原因只动态地知道 class,则可以使用采用 String
的那个;在这种情况下,它应该采用上述完全限定的 class 名称。
Intent启动的完整使用(不处理传递信息不正确的空指针异常):
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);
参考:
https://developer.android.com/reference/android/content/ComponentName.html
我想出了一个适合我的方法,尽管 Brandon 的方法可能适用于另一种解决方案。这是我的解决方案:
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);
这可能与 Brandon 的解决方案做同样的事情,但不那么抽象。
我一直在测试一些我没有源代码的包,其中一个包通常通过按三个按钮三秒钟来启动。当我尝试使用典型方法启动程序包时,出现 java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Intent android.content.Intent.addFlags(int)
错误。下面是我的代码
@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);
}
我尝试使用 getContext
而不是 getTargetContext
,但是有人向我指出,如果不导出意图,我将无法以这种方式启动包,无论我怎样做。我试图通过使用命令 adb logcat ActivityManager:V *:F
以及 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
有人知道我为什么会收到此错误吗?我尝试使用 logcat 转储中列出的每个包名称,但没有成功。如有任何意见,我们将不胜感激。
如果您想启动另一个应用程序,请先检查是否已安装此应用程序,否则您将获得 NullPointerException
,然后通过 intent 启动该应用程序使用包选项:
就像这样:
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.domain.anotherapp");
if (launchIntent != null) {
startActivity(launchIntent);//null pointer check in case package name was not found
}
这将使用默认启动 activity 启动应用程序,如果您想启动特定的 activity 您已经知道如何处理其他应用程序端的要求,或者只是崩溃或不工作(可能你可能需要传递一些变量或一些数据来表示这个应用程序的先前信息),无论如何,要打开这个特定的 activity 你必须使用 ComponentName
.
带两个String
的ComponentName
构造函数可用于引用另一个应用程序中的组件。但是,第一个参数不是 class 的包名;它是应用程序的包名称——该应用程序 AndroidManifest.xml
中 manifest
元素的 package
属性。所以你的第一个例子应该是
ComponentName cn = new ComponentName("com.domain.anotherapp",
"com.domain.anotherapp.widget.WidgetProvider");
该构造函数当然可以用于引用您自己的应用程序中的组件,但由于您已经从自己的应用程序中获取了 Context
,因此您不妨使用它并使用其他构造函数之一.在我看来,只要可用,应该首选带 Class
的那个。如果您出于某种原因只动态地知道 class,则可以使用采用 String
的那个;在这种情况下,它应该采用上述完全限定的 class 名称。
Intent启动的完整使用(不处理传递信息不正确的空指针异常):
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);
参考: https://developer.android.com/reference/android/content/ComponentName.html
我想出了一个适合我的方法,尽管 Brandon 的方法可能适用于另一种解决方案。这是我的解决方案:
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);
这可能与 Brandon 的解决方案做同样的事情,但不那么抽象。