使用包名启动活动

3

我一直在测试一些我没有源代码的软件包,其中一个软件包通常是通过按三个按钮三秒钟启动的。当我尝试使用典型的方法启动软件包时,我收到了一个java.lang.NullPointerException:尝试调用虚拟方法'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 *:Fadb 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

有人知道为什么我会收到这个错误吗?我已经尝试使用日志记录中列出的每个包名,但都没有成功。欢迎任何建议。

2个回答

1
如果您想启动另一个应用程序,请先检查该应用程序是否已安装,否则您将会收到一个NullPointerException,然后使用包选项通过意图启动应用程序:

就像这样:

Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.domain.anotherapp");
        if (launchIntent != null) {
            startActivity(launchIntent);//null pointer check in case package name was not found
        }

这将启动具有默认启动活动的应用程序,如果您想启动特定活动,则必须知道如何处理其他应用程序端的要求,否则可能会崩溃或无法工作(可能需要传递某些变量或某些数据以表示此应用程序的先前信息),无论如何,要打开此特定活动,您必须使用ComponentName

可以使用两个StringComponentName构造函数来引用另一个应用程序中的组件。但是,第一个参数不是类的包名称;它是应用程序的包名称——在该应用程序的AndroidManifest.xml中的manifest元素的package属性。因此,您的第一个示例应该是

ComponentName cn = new ComponentName("com.domain.anotherapp",
    "com.domain.anotherapp.widget.WidgetProvider");

那个构造函数当然可以用来引用您自己应用程序中的组件,但是既然您已经拥有了来自自己应用程序的Context,您可能会想使用它并使用其他构造函数之一。 在我看来,只要可用,就应该优先考虑使用一个接受Class的构造函数。 如果由于某种原因仅动态地知道类,则可以使用接受String的构造函数; 在这种情况下,它应采用上述完全限定的类名。
完整的用法以启动意图(不处理传递信息不正确的空指针异常):
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


0

我找到了一种适合我的方法,尽管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的解决方案一样,但是更少抽象化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接