Как запустить активность из другого приложения в Android

479

Я хочу запустить установленный пакет из моего приложения для Android. Я предполагаю, что это возможно, используя намерения, но я не нашел способ сделать это. Есть ли ссылка, где найти информацию?

Бастиан
источник
2
что произойдет, если я открою второе приложение из первого, а затем щелкну непосредственно по значку второго приложения, я получу два экземпляра приложения, что нежелательно. Как им управлять?
Радхи

Ответы:

707

Если вы не знаете основной вид деятельности, то для запуска приложения можно использовать имя пакета.

Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.package.address");
if (launchIntent != null) { 
    startActivity(launchIntent);//null pointer check in case package name was not found
}
andep
источник
5
Любая причина, почему это не будет работать? Я не заставил это работать по крайней мере.
Саймон Форсберг
22
Он запускает новое намерение, как насчет возобновления приложения, которое находится в фоновом режиме?
Салил Дуа
3
@andep: Это хорошо сработало, когда я тестировал между двумя приложениями, которые создал сам. Если я знаю, что имя пакета будет работать всегда, или есть способ предотвратить запуск вашего приложения кем-либо (в манифесте или где-то еще)?
Леонард Фихан
2
@ Леонард: Мое первое впечатление, что оно всегда должно работать, потому что имена пакетов общедоступны, поэтому любые приложения могут их прочитать. Из ваших приложений я думаю, что вы не можете определить, откуда он был вызван, но ваше приложение может определить, что его нельзя вызвать с помощью основного действия только через сервисы.
2013 года
1
Да, это может вернуть ноль. «Текущая реализация сначала ищет основное действие в категории CATEGORY_INFO, а затем основное действие в категории CATEGORY_LAUNCHER. Возвращает
ноль, если ничего
240

Я знаю, что на это ответили, но вот как я реализовал нечто подобное:

Intent intent = getPackageManager().getLaunchIntentForPackage("com.package.name");
if (intent != null) {
    // We found the activity now start the activity
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
} else {
    // Bring user to the market or let them choose an app?
    intent = new Intent(Intent.ACTION_VIEW);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setData(Uri.parse("market://details?id=" + "com.package.name"));
    startActivity(intent);
}

Еще лучше, вот метод:

public void startNewActivity(Context context, String packageName) {
    Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
    if (intent != null) {
        // We found the activity now start the activity
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    } else {
        // Bring user to the market or let them choose an app?
        intent = new Intent(Intent.ACTION_VIEW);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setData(Uri.parse("market://details?id=" + packageName));
        context.startActivity(intent);
    }
}

Удален повторяющийся код:

public void startNewActivity(Context context, String packageName) {
    Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
    if (intent == null) {
        // Bring user to the market or let them choose an app?
        intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("market://details?id=" + packageName));
    }
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(intent);
}
Джаред Барроуз
источник
8
У меня возникла проблема при запуске Intent для профиля в Facebook или Twitter. Они открывались внутри моего приложения, а не как новый вид деятельности. Добавление FLAG_ACTIVITY_NEW_TASK исправило это. Спасибо!
Гарри
4
Нет проблем! У меня были проблемы с чем-то очень похожим
Джаред Берроуз,
1
Метод работает для меня, но иногда новое приложение открыто, и вызывающая активность все еще остается на переднем плане. Есть идеи как починить?
lgdroid57
Есть ли способ сделать это из Instant-приложения?
Махди
Работает только для релизных версий. Если вы пытаетесь открыть приложение отладки, намерение будет нулевым.
RexSplode
152

Я нашел решение. В файле манифеста приложения я нашел имя пакета: com.package.address и имя основного действия, которое я хочу запустить: MainActivity Следующий код запускает это приложение:

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("com.package.address","com.package.address.MainActivity"));
startActivity(intent);
Бастиан
источник
8
я получил исключение «доза, которую вы объявляете активностью в вашем Manifest.xml»
ижар
Этот способ возвращает исключение, которое говорит, что мне нужно объявить активность в моем манифесте ... но это внешнее приложение!
JJ Ab
Как запустить его в фоновом режиме? Означает, что вызываемые приложения не отображаются на экране, но запускают метод onCreated ().
Dr.jacky
Я получаю эту ошибку, когда пытаюсь запустить приложение мгновенно: не разрешено начинать работу. Намерение
Махди,
@ Бастиан, как закрыть текущее приложение, откуда мы вызываем намерение открыть другое приложение?
Арнольд Браун
18
// in onCreate method
String appName = "Gmail";
String packageName = "com.google.android.gm";
openApp(context, appName, packageName);

public static void openApp(Context context, String appName, String packageName) {
    if (isAppInstalled(context, packageName))
        if (isAppEnabled(context, packageName))
            context.startActivity(context.getPackageManager().getLaunchIntentForPackage(packageName));
        else Toast.makeText(context, appName + " app is not enabled.", Toast.LENGTH_SHORT).show();
    else Toast.makeText(context, appName + " app is not installed.", Toast.LENGTH_SHORT).show();
}

private static boolean isAppInstalled(Context context, String packageName) {
    PackageManager pm = context.getPackageManager();
    try {
        pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
        return true;
    } catch (PackageManager.NameNotFoundException ignored) {
    }
    return false;
}

private static boolean isAppEnabled(Context context, String packageName) {
    boolean appStatus = false;
    try {
        ApplicationInfo ai = context.getPackageManager().getApplicationInfo(packageName, 0);
        if (ai != null) {
            appStatus = ai.enabled;
        }
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return appStatus;
}
Ахамадулла Сайкат
источник
17

Вот мой пример запуска сканера штрих-кода / QR-кода из моего приложения, если кто-то находит это полезным

Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.setPackage("com.google.zxing.client.android");

try 
{
    startActivityForResult(intent, SCAN_REQUEST_CODE);
} 
catch (ActivityNotFoundException e) 
{
    //implement prompt dialog asking user to download the package
    AlertDialog.Builder downloadDialog = new AlertDialog.Builder(this);
    downloadDialog.setTitle(stringTitle);
    downloadDialog.setMessage(stringMessage);
    downloadDialog.setPositiveButton("yes",
            new DialogInterface.OnClickListener() 
            {
                public void onClick(DialogInterface dialogInterface, int i) 
                {
                    Uri uri = Uri.parse("market://search?q=pname:com.google.zxing.client.android");
                    Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                    try
                    {
                        myActivity.this.startActivity(intent);
                    }
                    catch (ActivityNotFoundException e)
                    {
                        Dialogs.this.showAlert("ERROR", "Google Play Market not found!");
                    }
                }
            });
    downloadDialog.setNegativeButton("no",
            new DialogInterface.OnClickListener() 
            {
                public void onClick(DialogInterface dialog, int i) 
                {
                    dialog.dismiss();
                }
            });
    downloadDialog.show();
}
Тин М.
источник
13

Редактировать в зависимости от комментария

В некоторых версиях - как предлагается в комментариях - выбрасываемое исключение может быть другим.

Таким образом, решение ниже немного изменено

Intent launchIntent = null;
try{
   launchIntent = getPackageManager().getLaunchIntentForPackage("applicationId");
} catch (Exception ignored) {}

if(launchIntent == null){
    startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("https://play.google.com/store/apps/details?id=" + "applicationId")));
} else {
    startActivity(launchIntent);
}

Оригинальный ответ

Несмотря на хороший ответ, есть довольно простая реализация, которая обрабатывает, если приложение не установлено. Я делаю это так

try{
    startActivity(getPackageManager().getLaunchIntentForPackage("applicationId"));
} catch (PackageManager.NameNotFoundException e) {
    startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("https://play.google.com/store/apps/details?id=" + "applicationId")));
}

Замените «applicationId» на пакет, который вы хотите открыть, например com.google.maps и т. Д.

mayank1513
источник
В PackageManager.getLaunchIntentForPackage(...)метод возвращает нулевое значение , если имя пакета не распознается. Это не бросает PackageManager.NameNotFoundException. Смотрите здесь .
Адиль Хуссейн
Я только что попробовал startActivity(null)на эмуляторе Android 10, и он бросает, NullPointerExceptionа не PackageManager.NameNotFoundException.
Адиль Хуссейн
На моей ноте 7 он работает именно так, как задумано.
mayank1513
Каково предполагаемое поведение startActivity(Intent intent)метода, когда ему дается ноль Intentи что заставляет вас так говорить? Андроида разработчиков документации только утверждает , что она будет бросаться ActivityNotFoundException.
Адиль Хуссейн
Здравствуйте, @Adil. Не могли бы вы помочь мне с этим вопросом - stackoverflow.com/q/59615815/9640177
mayank1513
7
// check for the app if it exist in the phone it will lunch it otherwise, it will search for the app in google play app in the phone and to avoid any crash, if no google play app installed in the phone, it will search for the app in the google play store using the browser : 

 public void onLunchAnotherApp() {

        final String appPackageName = getApplicationContext().getPackageName();

        Intent intent = getPackageManager().getLaunchIntentForPackage(appPackageName);
        if (intent != null) {

            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);

        } else {

            onGoToAnotherInAppStore(intent, appPackageName);

        }

    }

    public void onGoToAnotherInAppStore(Intent intent, String appPackageName) {

        try {

            intent = new Intent(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setData(Uri.parse("market://details?id=" + appPackageName));
            startActivity(intent);

        } catch (android.content.ActivityNotFoundException anfe) {

            intent = new Intent(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setData(Uri.parse("http://play.google.com/store/apps/details?id=" + appPackageName));
            startActivity(intent);

        }

    }
Карима Инженер
источник
есть ли ограничение на число символов для метода uri.parse?
API
7

Если вы хотите открыть определенную активность другого приложения, мы можем использовать это.

Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
final ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.fuelgauge.PowerUsageSummary");
intent.setComponent(cn);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try 
{
    startActivity(intent)
}catch(ActivityNotFoundException e){
    Toast.makeText(context,"Activity Not Found",Toast.LENGTH_SHORT).show()
}

Если вам нужно другое приложение, вместо того, чтобы показывать Toast, вы можете показать диалоговое окно. С помощью диалогового окна вы можете пригласить пользователя в Play-Store для загрузки необходимого приложения.

Виньеш К.М.
источник
com.android.settings.fuelgauge.PowerUsageSummaryэто просто деятельность, псевдоним из com.android.settings.Settings$PowerUsageSummaryActivity, и он был удален в Android Pie , так что я на вершину правки , чтобы сделать этот ответ костюм Pie. Обратите внимание, что он также совместим со старой версией, см. Фиксацию AOSP 10 ноября 2011 г. af9252849fd94c1f2859c56a4010900ea38a607e и т. Д.
выходные
3

Если вам известны данные и действие, на которое реагирует установленный пакет, вы просто должны добавить эту информацию в свой экземпляр намерения перед его запуском.

Если у вас есть доступ к AndroidManifest другого приложения, вы можете увидеть всю необходимую информацию там.

WarrenFaith
источник
1
Спасибо за ответ. Да, у меня есть AndroidManifest другого приложения. Теперь я пытаюсь сделать следующий код: Intent intent = new Intent (Intent.ACTION_MAIN); intent.setComponent (new ComponentName ("com.package", ". MainActivity")); startActivity (намерение); но таким образом это не работает. Можете ли вы дать мне более точную ссылку, как это сделать?
Бастиан
1
Сбой приложения в строке «startActivity ...»: приложение неожиданно остановилось. Пожалуйста, попробуйте еще раз. Где я могу увидеть ошибку в LogCat?
Бастиан
5
Я обнаружил ошибку: при установке компонента вместо имени класса необходимо указать полное имя класса, а не просто класс: intent.setComponent (new ComponentName ("com.package", "com.package.MainActivity")) вместо намерения .setComponent (new ComponentName ("com.package", ". MainActivity"))
Бастиан
1
Полезно знать ... Вы можете найти LogCat на затмении: Окно> Показать представление> Другое, Android> Logcat
WarrenFaith
@WarrenFaith Мне нужна поддержка stackoverflow.com/questions/52335402/… Пожалуйста, помогите.
user158
2

Шаги, чтобы начать новую деятельность следующим образом:

1. получить намерение для пакета

2. Если намерение является нулевым, перенаправить пользователя в playstore

3. Если намерение не является пустым, открытым действием

public void launchNewActivity(Context context, String packageName) {
    Intent intent = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.CUPCAKE) {
        intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
    }
    if (intent == null) {
        try {
            intent = new Intent(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setData(Uri.parse("market://details?id=" + packageName));
            context.startActivity(intent);
        } catch (android.content.ActivityNotFoundException anfe) {
            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + packageName)));
        }
    } else {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }
}
Шарат Кумар
источник
2

Можно запустить деятельность приложения, используя в Intent.setClassNameсоответствии с документами.

Пример:

val activityName = "com.google.android.apps.muzei.MuzeiActivity" // target activity name
val packageName = "net.nurik.roman.muzei" // target package's name
val intent = Intent().setClassName(packageName, activityName)
startActivity(intent)

Чтобы открыть его за пределами текущего приложения, добавьте этот флаг перед началом намерения.

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

Соответствующий ответ здесь

Фани Ритвий
источник
Пожалуйста, как писать в C ++.
GeneCode
1
@GeneCode stackoverflow.com/a/22436147/8608146 может помочь, я никогда раньше не работал с библиотеками c ++ в Android.
Фани Ритвий
1
private fun openOtherApp() {
        val sendIntent = packageManager.getLaunchIntentForPackage("org.mab.dhyanaqrscanner")
        startActivity(sendIntent)
        finishAffinity()
    }
Мирза Ахмед Байг
источник