如何在 Android 中从另一个应用程序启动 Activity

Posted

技术标签:

【中文标题】如何在 Android 中从另一个应用程序启动 Activity【英文标题】:How to launch an Activity from another Application in Android 【发布时间】:2011-04-21 18:52:09 【问题描述】:

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

【问题讨论】:

如果我从第一个应用程序打开第二个应用程序然后直接单击第二个应用程序的图标会发生什么情况,我会得到两个应用程序实例,这是不受欢迎的。如何管理它?? How to call one android application from another android application的可能重复 【参考方案1】:

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

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

【讨论】:

这不起作用的任何原因?至少我没有让它工作。 它启动了一个新的 Intent ,如何恢复在后台的应用程序? @andep:当我在自己创建的两个应用程序之间进行测试时,这对我来说效果很好。一旦我知道包名称将始终有效,或者有没有办法阻止某人启动您的应用程序(在清单或某处)? @Leonard:我的第一印象是它必须始终有效,因为包名称是公开的,因此任何应用程序都可以读取它们。从您的应用程序中,我认为您无法确定它是从哪里调用的,但您的应用程序可以确定它不能仅通过服务通过主要活动来调用。 是的,这可以返回 null。 "当前的实现首先在 CATEGORY_INFO 类别中查找主要活动,然后在 CATEGORY_LAUNCHER 类别中查找主要活动。如果都没有找到,则返回 null。"【参考方案2】:

我知道这已经得到解答,但我是这样实现的:

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

【讨论】:

我在向 Facebook 或 Twitter 个人资料启动 Intent 时遇到问题。它们在我的应用程序中打开,而不是作为新活动。添加 FLAG_ACTIVITY_NEW_TASK 解决了这个问题。谢谢! 没问题!我遇到了一些非常相似的问题 该方法对我有用,但有时新应用程序已打开,调用活动仍然是前台。任何想法如何解决? 有没有办法从即时应用中做到这一点? 仅适用于发行版。如果您尝试打开调试应用,intent 将为空。【参考方案3】:

我找到了解决方案。在应用程序的清单文件中,我找到了包名称:com.package.address 和我要启动的主要活动的名称:MainActivity 以下代码启动此应用程序:

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("com.package.address","com.package.address.MainActivity"));
startActivity(intent);

【讨论】:

我遇到了异常'你在 Manifest.xml 中声明了活动' 这种方式返回一个异常,说我需要在我的清单中声明活动..但它是一个外部应用程序! 如何在后台运行?表示第二个调用的应用程序不会显示在屏幕上,而是运行其 onCreated() 方法。 当我从即时应用程序尝试时收到此错误:不允许启动活动意图 @Bastian 如何从我们调用意图打开另一个应用程序的地方关闭当前应用程序?【参考方案4】:
// 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;

【讨论】:

【参考方案5】:

根据评论进行编辑

在某些版本中——如 cmets 中所建议的——抛出的异常可能不同。

因此下面的解决方案稍作修改

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等

【讨论】:

如果包名未被识别,PackageManager.getLaunchIntentForPackage(...) 方法返回 null。它不会抛出PackageManager.NameNotFoundException。见here。 我刚刚在 Android 10 模拟器上尝试了 startActivity(null),它抛出了 NullPointerException 而不是 PackageManager.NameNotFoundException 在我的注释 7 中,它完全按照预期的方式工作。 startActivity(Intent intent) 方法被赋予一个空Intent 时,它的预期行为是什么?是什么让你这么说? Android 开发者的documentation 只声明它会抛出一个ActivityNotFoundException【参考方案6】:

这是我的示例,如果有人发现它有用,则从我的应用程序启动条码/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();

【讨论】:

【参考方案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 方法有字符限制吗?【参考方案8】:

如果您想打开另一个应用程序的特定活动,我们可以使用它。

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 的activity-alias,它是removed in Android Pie,所以我进行了编辑以使这个答案适合Pie。请注意,它也与旧版本兼容,请参阅 2011 年 11 月 10 日的 AOSP 提交 af9252849fd94c1f2859c56a4010900ea38a607e 等【参考方案9】:

根据文档,可以使用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 之前添加此标志。

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

相关回答here

【讨论】:

请教如何用 C++ 编写代码。 @GeneCode ***.com/a/22436147/8608146 可能会帮助我以前从未在 android 中使用过 c++ 库。【参考方案10】:

如果您知道已安装的包所响应的数据和操作,您只需在启动之前将这些信息添加到您的意图实例。

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

【讨论】:

感谢您的回复。是的,我有其他应用程序的 AndroidManifest。我现在尝试做的是以下代码: Intent intent = new Intent(Intent.ACTION_MAIN); intent.setComponent(new ComponentName("com.package",".MainActivity"));开始活动(意图);但以这种方式它不起作用。能不能给个更精确的链接,怎么做? 应用程序在“startActivity...”行崩溃:应用程序意外停止。请再试一次。我在哪里可以看到 LogCat 中的错误? 我发现错误:设置组件时,必须命名完全限定的类名,而不仅仅是类:intent.setComponent(new ComponentName("com.package","com.package .MainActivity")) 而不是 intent.setComponent(new ComponentName("com.package",".MainActivity")) 很高兴知道...您可以在 eclipse 上找到 LogCat:Window > Show view > Other, Android > Logcat @WarrenFaith 我需要***.com/questions/52335402/… 的支持,请帮忙。【参考方案11】:

启动新活动的步骤如下:

1.获取包的意图

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

3.如果intent不为空则打开activity

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

【讨论】:

【参考方案12】:
private fun openOtherApp() 
        val sendIntent = packageManager.getLaunchIntentForPackage("org.mab.dhyanaqrscanner")
        startActivity(sendIntent)
        finishAffinity()
    

【讨论】:

【参考方案13】:

从 API 30 (Android 11) 开始,您可以使用 launchIntentForPackage 接收 nullpointerexception

val launchIntent: Intent? = activity.packageManager.getLaunchIntentForPackage("com.google.android.gm")
startActivity(launchIntent) 

为避免这种情况,您需要将所需的包添加到清单中

<queries>
    <package android:name="com.google.android.gm" />
</queries>

这是文档 https://developer.android.com/training/package-visibility

还有中篇 https://medium.com/androiddevelopers/package-visibility-in-android-11-cc857f221cd9

【讨论】:

好的,谢谢。【参考方案14】:

试试下面的代码:

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("package_name", "Class_name"));
if (intent.resolveActivity(getPackageManager()) != null) 

   startActivity(intent);

【讨论】:

【参考方案15】:

在科特林中

fun openApplicationOrMarket(packageName: String) 
        var intent = requireContext().packageManager.getLaunchIntentForPackage(packageName)
        if (intent == null) 
            intent = Intent(Intent.ACTION_VIEW)
            intent.data = Uri.parse("market://details?id=$packageName")
        

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

【讨论】:

【参考方案16】:

如果未安装包,请传递包名称和要显示的消息 ;-)

void openApp(String appPackageName,String message)
    Intent launchIntent = getPackageManager().getLaunchIntentForPackage(appPackageName);
    if (launchIntent != null) 
        startActivity(launchIntent);
     else 
        Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
    

【讨论】:

【参考方案17】:

这将涵盖所有场景

1.获取包的意图

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

3.如果打开 playstore 出现问题,则在默认浏览器上打开。

var intent = activity!!.packageManager.getLaunchIntentForPackage("com.google.android.youtube")

          if (intent == null) 
            if (intent == null) 
                    intent = try 
                        Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.android.youtube"))
                     catch (e: Exception) 
                        Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=com.google.android.youtube"))
                    
                
             startActivity(intent)

对于 Android 11(API 级别 30)或更高版本,在 AndroidManifest.xml 中,

<queries>
    <package android:name="com.google.android.youtube" />
    <package android:name="com.example.app" />
</queries>

或者我们可以允许所有包(不推荐)

<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />

参考文献

Package visibility filtering on Android

Declaring package visibility needs

【讨论】:

【参考方案18】:

由于最近 kotlin 变得非常流行,我认为在 Kotlin 中也提供一个简单的解决方案是合适的。

var launchIntent: Intent? = null
try 
    launchIntent = packageManager.getLaunchIntentForPackage("applicationId")
 catch (ignored: Exception) 

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

【讨论】:

【参考方案19】:

在 Kotlin 中,使用此代码从您当前的活动中启动另一个应用程序

       var intent = packageManager.getLaunchIntentForPackage("com.bankid.bus")


       //var intent = this.packageManager.getLaunchIntentForPackage("com.bankid.bus")
        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 = Intent(Intent.ACTION_VIEW)
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            intent.data = Uri.parse("market://details?id=" + "com.bankid.bus")
            startActivity(intent)
        

对于 android 版本 10+,您还需要在 AndroidManifest.xml 文件中添加标签,否则 getLaunchIntentForPackage() 将返回 null 即

<queries> <package android:name="com.bankid.bus" /> </queries>

【讨论】:

以上是关于如何在 Android 中从另一个应用程序启动 Activity的主要内容,如果未能解决你的问题,请参考以下文章

在android中从另一个片段获取数据到片段

如何在 PHP 应用程序中从另一个站点呈现 javascript?

如何在谷歌地图应用程序中从另一个位置显示当前位置?

如何在 ASP.NET MVC 3 的一个解决方案中从另一个项目获取文件路径?

如何在 Nuxt 中从另一个访问一个 Vuex 状态?

如何在颤动中从另一个屏幕进行更改