如何从Android中的另一个应用程序启动活动


478

我想从我的Android应用程序启动已安装的软件包。我认为可以使用意图,但是我没有找到一种方法。有链接,在哪里可以找到信息?


2
如果我从第一个应用程序打开第二个应用程序,然后直接单击第二个应用程序的图标,会发生该应用程序的两个实例的情况,这是不希望的。如何管理它?
Radhey

Answers:


707

如果您不知道主要活动,则可以使用包名称来启动应用程序。

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

5
有什么理由为什么这行不通?我至少没有使它工作。
西蒙·佛斯伯格

22
它启动一个新的Intent,如何恢复后台的应用程序?
Salil Dua

3
@andep:当我在自己创建的两个应用程序之间进行测试时,这对我来说效果很好。一旦我知道软件包名称将始终有效,还是有办法阻止某人(在最简单的地方或其他地方)启动您的应用?
伦纳德·菲汉

2
@Leonard:我的第一印象是它必须始终有效,因为包名称是公共的,因此任何应用程序都可以读出它们。从您的应用程序中,我认为您无法确定调用源,但您的应用程序可以确定无法仅通过服务通过主要活动来调用它。
andep 2013年

1
是的,这可以返回null。“当前实现首先在类别中查找主要活动,然后在类别中CATEGORY_INFO查找主要活动CATEGORY_LAUNCHER如果均未找到,则返回null。
quietmint 2015年

239

我知道已经回答了,但是这是我实现类似内容的方法:

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
启动针对Facebook或Twitter个人资料的Intent时出现问题。他们正在我的应用程序中打开,而不是作为新活动打开。添加FLAG_ACTIVITY_NEW_TASK可以解决此问题。谢谢!
哈里

4
没问题!我遇到了非常类似的问题
Jared Burrows

1
该方法对我有用,但是有时新的应用程序已打开,并且调用Activity仍然是前台。任何想法如何解决?
lgdroid57 2014年

有什么办法可以从Instant-App做到这一点?
Mahdi '18

仅适用于发行版。如果您尝试打开调试应用程序,则intent将为null。
RexSplode '18

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中声明活动'
itzhar 2015年

这种方式返回一个异常,该异常表示我需要在清单中声明活动。但是它是一个外部应用程序!
JJ Ab

如何在后台运行它?表示第二个被调用的应用程序不在屏幕上显示,而是运行其onCreated()方法。
Dr.jacky

我从即时应用程序尝试时收到此错误:不允许启动活动意图
Mahdi,

@Bastian如何从调用打开另一个应用程序的意图的位置关闭当前应用程序?
阿诺德·布朗

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

用您要打开的包(例如com.google.maps等)替换“ applicationId”。


PackageManager.getLaunchIntentForPackage(...)如果无法识别包名称,则该方法返回null。它不会抛出PackageManager.NameNotFoundException。看这里
阿迪尔·侯赛因

我只是startActivity(null)在Android 10模拟器上尝试过,它抛出NullPointerException而不是PackageManager.NameNotFoundException
阿迪尔·侯赛因

在我的注释7中,它完全按照预期的方式工作。
mayank1513

startActivity(Intent intent)给该方法一个null时,该方法的预期行为是Intent什么,您为何这么说呢?Android开发人员的文档仅声明会抛出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中移除饼,所以我登顶编辑,使这个答案西装馅饼。请注意,它也与旧版本兼容,请参阅AOSP在2011年11月10日提交af9252849fd94c1f2859c56a4010900ea38a607e等
周末

3

如果知道数据和已安装的软件包所采取的措施,则只需在启动它之前将这些信息添加到您的intent实例中。

如果您可以访问其他应用程序的AndroidManifest,则可以在其中看到所有需要的信息。


1
谢谢回复。是的,我拥有其他应用程序的AndroidManifest。我现在尝试做的是以下代码:Intent intent = new Intent(Intent.ACTION_MAIN); intent.setComponent(new ComponentName(“ com.package”,“。MainActivity”)); startActivity(intent); 但这种方式不起作用。您能给我一个更精确的链接,怎么做?
巴斯蒂安

1
应用程序在“ startActivity ...”行崩溃:应用程序意外停止。请重试。在哪里可以看到LogCat中的错误?
巴斯蒂安

5
我发现了错误:设置组件时,必须命名完全合格的类名,而不仅仅是类:intent.setComponent(new ComponentName(“ com.package”,“ com.package.MainActivity”))而不是intent .setComponent(new ComponentName(“ com.package”,“。MainActivity”))
巴斯蒂安(Bastian

1
相关提示...您可以在eclipse上找到LogCat:窗口>显示视图>其他,Android> Logcat
WarrenFaith 2010年

@WarrenFaith我需要stackoverflow.com/questions/52335402/…的支持。
user158

2

启动新活动的步骤如下:

1.获取包装意向

2.如果intent为null,则将用户重定向到playstore

3.如果intent不为空则打开活动

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可能有助于我以前从未在Android中使用过c ++库。
Phani Rithvij

1
private fun openOtherApp() {
        val sendIntent = packageManager.getLaunchIntentForPackage("org.mab.dhyanaqrscanner")
        startActivity(sendIntent)
        finishAffinity()
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.