【问题标题】:Cannot start new Intent by setClassName with different package in Android无法通过 setClassName 在 Android 中使用不同的包启动新 Intent
【发布时间】:2012-04-12 23:52:58
【问题描述】:

我想动态启动一个新的 Intent。因此setClassName 似乎是最好的选择。

首先,我在 Manifest 中定义了 3 个活动

<activity android:name="com.example.pkg2.Act" />
<activity android:name="com.example.pkg1.Act1" />
<activity android:name="com.example.pkg1.Act2" />

来自com.example.pkg2.Act

Intent intent = new Intent();
if(index == 0) intent.setClassName(Act.this, "com.example.pkg1.Act1");
else intent.setClassName(Act.this, "com.example.pkg1.Act2");
startActivity(intent);

并且会得到这个异常:

Unable to find explicit activity class {com.example.pkg2.Act/com.example.pkg1.Act1}; have you declared this activity in your AndroidManifest.xml?

看起来我们只能使用setClassName 来动态启动新的Activity,但在同一个包中。

有解决这个问题的办法吗?感谢所有帮助。

【问题讨论】:

  • &lt;activity android:name="com.example.pkg1.Act1" /&gt;将Act1更改为Act2 你已经两次声明Act1了?
  • 谢谢@imrankhan 复制粘贴是我的错:p
  • 没关系,看我更新的答案。
  • 您找到有效的解决方案了吗?

标签: android android-intent


【解决方案1】:

问题的最可能原因是给定的类名不是链接到 pkg2 的类。这是我用来在 AndroidInstumentationTest 应用程序中启动意图的代码的 sn-p。

    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.setClassName("com.xxx.android.app",
            "com.xxx.android.app.MainActivity")
            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    mActivity = instrumentation.startActivitySync(intent);

这段代码在我的应用模块中运行得非常好,其中包含 MainActivity 类。如果我尝试在没有 MainActivity 类链接的模块中使用它,它将不起作用。从我对原始问题陈述的阅读来看,这似乎很可能是用户“anticafe”所说的他试图做的事情。我的猜测是,在内部有一个对“Class.forName(className, classLoader) 的调用,其中 classLoader 是给定包的 ClassLoader。当然这会失败,因为该包没有链接。

是的,您确实需要添加标志“FLAG_ACTIVITY_NEW_TASK”,正如其他人所建议的那样,至少对于您确实链接了类的情况!

【讨论】:

    【解决方案2】:

    setClassName 将包上下文作为第一个参数 setClassName(Context packageContext, String className):

    Intent intent = new Intent();
    if(index == 0) {
      intent.setClassName("com.example.pkg1", "com.example.pkg1.Act1");
    } else {
      intent.setClassName("com.example.pkg1", "com.example.pkg1.Act2");
      startActivity(intent);
    }
    

    <activity android:name="com.example.pkg2.Act" />
    <activity android:name="com.example.pkg1.Act1" />
    <activity android:name="com.example.pkg1.Act2" />
    

    或者你试试这个:

    if(index == 0) {
      Intent intent = new Intent(Intent.ACTION_MAIN)
        .addCategory(intent.CATEGORY_LAUNCHER)
        .setClassName("com.example.pkg1", "com.example.pkg1.Act1")
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        .addFlags(Intent.FLAG_FROM_BACKGROUND)
        .setComponent(new ComponentName("com.example.pkg1", "com.example.pkg1.Act1"));
      getApplicationContext().startActivity(intent);
    } else {
      Intent intent  = new Intent(Intent.ACTION_MAIN)
        .addCategory(intent.CATEGORY_LAUNCHER)
        .setClassName("com.example.pkg1", "com.example.pkg1.Act2")
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        .addFlags(Intent.FLAG_FROM_BACKGROUND)
        .setComponent(new ComponentName("com.example.pkg1", "com.example.pkg1.Act2"));
      getApplicationContext().startActivity(intent);
    }
    

    【讨论】:

      【解决方案3】:

      你也可以用这种方式启动Activity。试试这个

      Intent intent = new Intent();
      Class<?> activityClass = Class.forName("your.application.package.name." + NameOfClassToOpen); 
      intent.setClass(this, activityClass);
      

      为了使用setClassName。您应该为它提供 packageName 及其类路径也像

      intent.setClassName("your.application.package.name", "your.application.package.name.activityClass");
      

      【讨论】:

        【解决方案4】:

        使用此代码,您会没事的。

        Intent intent = new Intent();
        String resourcePackageName = getResources().getResourcePackageName(R.string.some_defined_resource);
        intent.setClassName(getApplicationContext().getPackageName(),resourcePackageName + ".SubPackageName[/if any/].ClassName");
        startActivity(intent);
        

        【讨论】:

          【解决方案5】:

          第一个参数是 build.gradle 文件中的 applicationId

          第二个参数是类及其包的完整路径。 例如: intentObj.setClassName("applicioId", "com.youCompany.yourAppName.YourClassName")

          【讨论】:

            【解决方案6】:

            intent.setClassName(packageName, className);

            在哪里
            packageName - 实现所需组件的包的名称,即调用者所属的包。
            className - 类的完全限定名[来自不同的包]

            来自com.example.pkg2.Act:

            intent.setClassName("com.example.pkg2", "com.example.pkg1.Act1");
            

            【讨论】:

              【解决方案7】:

              您可以使用以下方法在包上下文中创建意图:

                  Intent intent = new Intent(this, MyActivity.class);
                  intent.setAction(Intent.ACTION_VIEW);
                  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                  startActivity(intent);
              

              这样你就可以继续使用通用代码。

              HTH

              【讨论】:

                【解决方案8】:
                intent.setClassName(Act.this, Act1.class);
                

                【讨论】:

                  【解决方案9】:

                  按照语法编写 setClassName() 方法:

                   setClassName( pkgName, className ) 
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-09-06
                    • 2011-02-09
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-04-07
                    相关资源
                    最近更新 更多