从你自己的应用程序中打开另一个应用程序(意图)

142

我知道如何更新我的程序,也知道如何打开使用预定义Uri的程序(例如短信或电子邮件)

我需要知道如何创建一个Intent来打开MyTracks或任何其他我不知道它们监听哪些意图的应用程序。

我从DDMS中获得了这些信息,但我尝试将其转换为我可以使用的Intent时没有成功。 这是手动打开MyTracks时获取的。

谢谢你的帮助

05-06 11:22:24.945: INFO/ActivityManager(76): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.google.android.maps.mytracks/com.google.android.apps.mytracks.MyTracks bnds=[243,338][317,417] }
05-06 11:22:25.005: INFO/ActivityManager(76): Start proc com.google.android.maps.mytracks for activity com.google.android.maps.mytracks/com.google.android.apps.mytracks.MyTracks: pid=1176 uid=10063 gids={3003, 1015}
05-06 11:22:26.995: INFO/ActivityManager(76): Displayed activity com.google.android.maps.mytracks/com.google.android.apps.mytracks.MyTracks: 1996 ms (total 1996 ms)
20个回答

245

我已经像这样处理了它:

/** Open another app.
 * @param context current Context, like Activity, App, or Service
 * @param packageName the full package name of the app to open
 * @return true if likely successful, false if unsuccessful
 */
public static boolean openApp(Context context, String packageName) {
    PackageManager manager = context.getPackageManager();
    try {
        Intent i = manager.getLaunchIntentForPackage(packageName);
        if (i == null) {
            return false;
            //throw new ActivityNotFoundException();
        }
        i.addCategory(Intent.CATEGORY_LAUNCHER);
        context.startActivity(i);
        return true;
    } catch (ActivityNotFoundException e) {
        return false;
    }
}

使用示例:

openApp(this, "com.google.android.maps.mytracks");

5
由于使用getLaunchIntentForPackage("应用程序包名")可能会引发异常。 - xtr
这是一个很好的答案,简单地捕获异常并执行所需操作,通知用户等。 - IT-Dan
5
不想太苛刻,但是在第一行分配一个新的 Intent 没有必要,因为你使用了 getLaunchIntentForPackage 调用的结果。 - Chris Lacy
2
getLaunchIntentForPackage()已经添加了类别,请参见源代码:https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/ApplicationPackageManager.java#L150 - jrub
对我来说唯一的问题是Context对象在哪里/如何获取或创建它?以及需要导入哪些包。我是Android开发中的Java新手。 - Aleksey Kontsevich

142

首先,在Android中,“应用程序”这个概念略微有些扩展。

一个应用程序 - 技术上是一个进程 - 可以有多个活动、服务、内容提供者和/或广播侦听器。如果其中至少一个正在运行,则该应用程序正在运行(即进程正在运行)。

因此,您需要确定如何“启动应用程序”。

好的...下面是您可以尝试的方法:

  1. 使用 action=MAINcategory=LAUNCHER 创建一个意图(intent)
  2. 使用 context.getPackageManager从当前上下文获取PackageManager
  3. packageManager.queryIntentActivity(<intent>, 0) 其中意图(intent)具有category=LAUNCHERaction=MAINpackageManager.resolveActivity(<intent>, 0)以获取第一个具有main/launcher的活动
  4. 获取您感兴趣的ActivityInfo
  5. ActivityInfo中获取packageNamename
  6. 最后,创建另一个具有category=LAUNCHERaction=MAINcomponentName = new ComponentName(packageName, name)setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)的意图(intent)
  7. 最后,使用context.startActivity(newIntent)

如果我想打开三个不同的应用程序怎么办? - Si8
7
如果你知道软件包的名称,下面社区维基的答案更好。https://dev59.com/WXE85IYBdhLWcg3wbS_1#7596063 - Martin Belcher - AtWrk
你如何在调用应用程序和启动的应用程序之间传递数据?我发现了 'Intent.putExtra()',但我不知道如何在启动的应用程序中检索额外的数据。 - Bram
onCreate => 创建Bundle extras = getIntent().getExtras() => Bundle extras = getIntent().getExtras()if(extras != null) { extras.getString("blah") } => if(extras != null) { extras.getString("blah") } 等等 - gvaish
2
getPackageManager().getLaunchIntentForPackage() 已经为您完成了所有操作。请参考 https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/ApplicationPackageManager.java#L137 - jrub
显示剩余3条评论

97
    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.setComponent(ComponentName.unflattenFromString("com.google.android.maps.mytracks/com.google.android.apps.mytracks.MyTracks"));
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
    startActivity(intent);

编辑:

如评论所建议,在startActivity(intent);之前添加一行代码。

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

18
但需要知道活动的名称。 - njzk2
我尝试了这个,但出现了一个错误,建议使用FLAG_ACTIVITY_NEW_TASK标志。在startActivity之前,我添加了这行代码:intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 然后它就可以工作了。 - david-hoze
1
@njzk2 在 Google Play 上查找某个应用的包名很容易;它就在 URL 中。例如:https://play.google.com/store/apps/details?id=com.google.zxing.client.android&hl=en - Da-Jin
@iceybobby 是的,包名很容易找到,但是如何找到要启动的活动的类名呢? - phreakhead
@phreakhead 你说得对。我想我使用了这个答案中的解决方案:https://dev59.com/WXE85IYBdhLWcg3wbS_1#8944286,所以活动名称是不需要的,因此我认为我的回复对njzk2在这里没有帮助。 - Da-Jin

40

如果您已经知道要激活的软件包名称,可以使用以下代码,它更具通用性:

PackageManager pm = context.getPackageManager();
Intent appStartIntent = pm.getLaunchIntentForPackage(appPackageName);
if (null != appStartIntent)
{
    context.startActivity(appStartIntent);
}

我发现它在主活动未被常规启动方法找到的情况下运行得更好。


1
对我来说,这是最佳答案 :-) 对我很有帮助。谢谢 - Jalpesh Khakhi
1
非常适合我。非常感谢Muzikant : ) - Alex

13

这是我基于MasterGaurav解决方案的代码:

private void  launchComponent(String packageName, String name){
    Intent launch_intent = new Intent("android.intent.action.MAIN");
    launch_intent.addCategory("android.intent.category.LAUNCHER");
    launch_intent.setComponent(new ComponentName(packageName, name));
    launch_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    activity.startActivity(launch_intent);
}

public void startApplication(String application_name){
    try{
        Intent intent = new Intent("android.intent.action.MAIN");
        intent.addCategory("android.intent.category.LAUNCHER");

        intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        List<ResolveInfo> resolveinfo_list = activity.getPackageManager().queryIntentActivities(intent, 0);

        for(ResolveInfo info:resolveinfo_list){
            if(info.activityInfo.packageName.equalsIgnoreCase(application_name)){
                launchComponent(info.activityInfo.packageName, info.activityInfo.name);
                break;
            }
        }
    }
    catch (ActivityNotFoundException e) {
        Toast.makeText(activity.getApplicationContext(), "There was a problem loading the application: "+application_name,Toast.LENGTH_SHORT).show();
    }
}

10

我使用inversus的解决方案并扩展了代码段,添加了一个函数。当目标应用程序当前未安装时,将调用该函数。因此它的工作方式是: 按软件包名称运行应用程序,如果找不到,则打开Android市场-Google Play以获取该软件包。

public void startApplication(String packageName)
{
    try
    {
        Intent intent = new Intent("android.intent.action.MAIN");
        intent.addCategory("android.intent.category.LAUNCHER");

        intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        List<ResolveInfo> resolveInfoList = getPackageManager().queryIntentActivities(intent, 0);

        for(ResolveInfo info : resolveInfoList)
            if(info.activityInfo.packageName.equalsIgnoreCase(packageName))
            {
                launchComponent(info.activityInfo.packageName, info.activityInfo.name);
                return;
            }

        // No match, so application is not installed
        showInMarket(packageName);
    }
    catch (Exception e) 
    {
        showInMarket(packageName);
    }
}

private void launchComponent(String packageName, String name)
{
    Intent intent = new Intent("android.intent.action.MAIN");
    intent.addCategory("android.intent.category.LAUNCHER");
    intent.setComponent(new ComponentName(packageName, name));
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    startActivity(intent);
}

private void showInMarket(String packageName)
{
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + packageName));
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
}

它的使用方式如下:

startApplication("org.teepee.bazant");

6

如果应用程序已存在,则打开它,否则打开Google Play商店以安装它:

private void open() {
    openApplication(getActivity(), "com.app.package.here");
}

public void openApplication(Context context, String packageN) {
    Intent i = context.getPackageManager().getLaunchIntentForPackage(packageN);
    if (i != null) {
        i.addCategory(Intent.CATEGORY_LAUNCHER);
        context.startActivity(i);
    } else {
        try {
            context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + packageN)));
        }
        catch (android.content.ActivityNotFoundException anfe) {
            context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://play.google.com/store/apps/details?id=" + packageN)));
        }
    }
}

应该是 if (i != null) - vallllll

6

使用这个:

    PackageManager pm = getPackageManager();
    Intent intent = pm.getLaunchIntentForPackage("com.package.name");
    startActivity(intent);

有任何想法吗?打开一个test.apk而不是安装在设备存储器中现有应用程序的内部。当单击按钮时,提示启动存储在现有项目中的test.apk应用程序。提前致谢。 - Selim Raza

4

我希望从我的应用程序活动中启动另一个应用程序活动,目前运行良好。

如果另一个应用程序已安装在您的手机上,则以下代码将起作用,否则不可能从一个应用程序重定向到另一个应用程序。因此,请确保您的应用程序已启动。

Intent intent = new Intent();
intent.setClassName("com.xyz.myapplication", "com.xyz.myapplication.SplashScreenActivity");
startActivity(intent);

请勿编写几乎与同一问题相同的多个答案。请使用答案下方的“编辑”链接更改原始内容。 - AdrianHHH

3
如果您想打开另一个应用程序,但是它尚未安装,则可以将其发送到Google应用商店进行下载。
  1. First create the openOtherApp method for example

    public static boolean openOtherApp(Context context, String packageName) {
        PackageManager manager = context.getPackageManager();
         try {
            Intent intent = manager.getLaunchIntentForPackage(packageName);
            if (intent == null) {
                //the app is not installed
                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 (ActivityNotFoundException e) {
                    //throw new ActivityNotFoundException();
                    return false;
                }
    
             }
             intent.addCategory(Intent.CATEGORY_LAUNCHER);
             context.startActivity(intent);
             return true;
        } catch (ActivityNotFoundException e) {
            return false;
        }
    
    }
    

2.- 用法

openOtherApp(getApplicationContext(), "com.packageappname");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接