通过包名称启动活动

时间:2017-06-06 15:11:37

标签: android testing android-junit

我一直在测试一些我没有源代码的软件包,其中一个软件包通常是按下三个按钮三秒钟启动的。当我尝试使用典型方法启动程序包时,出现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转储中列出的每个包名都没有成功。任何意见都将不胜感激。

2 个答案:

答案 0 :(得分: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

使用两个ComponentName的{​​{1}}构造函数可用于引用另一个应用程序中的组件。但是,第一个参数不是类的包名;它是应用程序的包名称---该应用程序Stringpackage元素的manifest属性。所以你的第一个例子应该是

AndroidManifest.xml

该构造函数当然可以用于引用您自己的应用程序中的组件,但由于您已经拥有自己的应用程序中的ComponentName cn = new ComponentName("com.domain.anotherapp", "com.domain.anotherapp.widget.WidgetProvider"); ,因此您可以使用它并使用其他构造函数之一。在我看来,只要可以使用,Context的人应该是首选。如果您因某种原因仅动态地知道该类,则可以使用Class的那个;在这种情况下,它应该采用上面的完全限定类名。

完全用于通过intent启动(不处理错误传递信息的空指针异常):

String

参考: https://developer.android.com/reference/android/content/ComponentName.html

答案 1 :(得分: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);

这可能与布兰登的解决方案做同样的事情,但不那么抽象。