【问题标题】:Determining if an Activity exists on the current device?确定当前设备上是否存在 Activity?
【发布时间】:2025-11-25 16:20:09
【问题描述】:

有没有办法检查设备上是否存在活动?如果我有一个 youtube 视频链接,我想指定它在 YouTube PlayerActivity 中打开。但是,如果由于某种原因他们没有它,我不想崩溃。

有没有办法检查活动是否存在?我认为我无法捕获运行时异常,因为 startActivity() 不会抛出它。

【问题讨论】:

    标签: android android-activity


    【解决方案1】:

    您可以使用必要的组件信息创建一个 Intent 对象,然后检查该 Intent 是否可调用。我在 SO 上偶然发现了这个 sn-p,没有指向实际线程的链接。

    private boolean isCallable(Intent intent) {
            List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, 
                PackageManager.MATCH_DEFAULT_ONLY);
            return list.size() > 0;
    }
    

    【讨论】:

    • 这个怎么用?
    【解决方案2】:

    这是最简单的方法:

    boolean activityExists = intent.resolveActivityInfo(getPackageManager(), 0) != null;
    

    也是那个recommended by Google

    要首先验证是否存在接收 Intent 的应用,请在 Intent 对象上调用 resolveActivity()。如果结果不为空,则至少有一个应用程序可以处理该意图,并且可以安全地调用startActivity()。如果结果为 null,则不应使用该意图,并且如果可能,应禁用调用该意图的功能。

    【讨论】:

    • 对于不存在的活动返回 true。恐怕这不是最好的解决方案。我使用了另一个答案中发布的 isCallable 方法,它按预期工作。
    • @toro intent.resolveActivity(getPackageManager()) 那么返回什么?如果这个方法真的返回了一个不存在的活动,这绝对看起来像一个错误。此外,根据 Google 文档,List&lt;ResolveInfo&gt; list = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); 的作用完全相同,只是它不只是返回具有最高优先级的活动。
    • 我的意图是这样创建的:intent.setComponent(new ComponentName("package", "package.activity-name)); 你问它返回什么 - ComponentInfo{"package"/"package.activity-name}。但实际上该活动并不存在,因此调用此意图最终会导致运行时崩溃。
    • @toro 哦,我明白发生了什么。我查看了源代码,此方法不检查设置的组件名称是否有效。我已经更新了答案。再试一次,现在应该可以了。
    【解决方案3】:

    我最终做了:

            Intent intent = new Intent();
            intent.setClassName( "com.google.android.gsf", "com.google.android.gsf.login.AccountIntroActivity" );
    
            if(getContext().getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
                getContext().startActivity( intent );
            } else {
                getContext().startActivity(new Intent(Settings.ACTION_ADD_ACCOUNT));
            }
    

    这可确保存在特定于 google 的添加帐户意图,如果不存在,则使用更通用的 ACTION_ADD_ACCOUNTS。

    【讨论】:

      【解决方案4】:

      我认为我无法赶上运行时 异常

      实际上,这是可行的:

      try {
          startActivity(new Intent(..));
      } catch (ActivityNotFoundException e) {
          Toast.makeText(this, "Not installed.", LENGTH_SHORT).show();
      }
      

      【讨论】:

      • 这当然可行,但通常认为这样做是不好的做法。 Samuh (*.com/a/2879403/15695) 的答案是正确的方法。
      • 这不仅是不好的做法,而且如果您需要使用 startActivityForResult,在我测试的设备上会出现一些严重的效率/冻结问题。
      【解决方案5】:

      以下是我检查设备上是否存在Activity 的方法:

              Intent intent = new Intent(Intent.ACTION_CALL);
              intent.setData(Uri.parse("tell//:" + phoneNumber));
      
              PackageManager manager = context.getPackageManager();
              List<ResolveInfo> activities = manager.queryIntentActivities(
                      intent, 0);
              if (!manager.hasSystemFeature(
                      PackageManager.FEATURE_TELEPHONY) || activities == null || activities
                      .size() < 1) {
                  Toast.makeText(
                          context,
                          "Sorry, there were no apps that worked with that request.",
                          Toast.LENGTH_SHORT).show();
              } else {
                  context.startActivity(intent);
              }
      

      【讨论】: