Невозможно запустить новое намерение с помощью setClassName с другим пакетом в Android

Я хочу начать новое намерение динамически. Следовательно setClassName кажется лучшим выбором.

Во-первых, я определяю 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 динамически запускать новую активность, но в том же пакете.

Есть идеи, чтобы решить эту проблему? Вся помощь приветствуется.

8 ответов

Решение

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);
}

Первый параметр - это идентификатор приложения, расположенный в файле build.gradle.

Второй параметр - это полный путь к классу с его пакетом. например: intentObj.setClassName ("ApplicatioId", "com.youCompany.yourAppName.YourClassName")

Вы можете использовать следующий метод для создания намерения в контексте пакета:

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

Таким образом, вы держите общий код.

НТН

Вы также можете запустить Действия таким образом. Попробуй это

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");

Используйте этот код, и все будет в порядке.

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

intent.setClassName(packageName, className);

где
packageName - имя пакета, реализующего желаемый компонент, то есть пакет, к которому принадлежит вызывающая сторона.
className - полное имя класса [из другого пакета]

Звонить из com.example.pkg2.Act:

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

Наиболее вероятная причина проблемы заключается в том, что данное имя класса не является классом, связанным с pkg2. Вот фрагмент кода, который я использовал для запуска намерения в приложении AndroidInstumentationTest.

    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. Судя по тому, что я прочитал о первоначальной постановке проблемы, похоже, что это то, что, по словам пользователя антикафе, пытался сделать. Я предполагаю, что внутри есть вызов "Class.forName(className, classLoader), где classLoader - это ClassLoader для данного пакета. И, конечно, это не удастся, поскольку этот пакет не связан.

И да, вам нужно добавить флаг "FLAG_ACTIVITY_NEW_TASK", как предлагали другие, по крайней мере, для ситуаций, когда у вас есть связанный класс!

Следуйте синтаксису, чтобы написать метод setClassName():

 setClassName( pkgName, className ) 
intent.setClassName(Act.this, Act1.class);
Другие вопросы по тегам