Android:调用另一个应用程序的活动

14

我有两个Android应用程序,假设它们是“A”和“B”,“A”有五个活动,我想从“B”的按钮单击事件中调用其特定活动。

我测试了通过另一个应用程序调用一个应用程序的方式:

Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage("com.testapp.ws");
startActivity(LaunchIntent);

"com.testapp.ws"是"A"的包名。

这会从"A"的第一个活动再次运行,而不是从指定的活动运行。如何调用A的指定活动?

4个回答

43

Grant,

这里的问题显然是对Android应用程序模型的误解。Commonsware关于如何解决这个问题的建议是绝对正确的。但是,如果不理解Android基础知识,我可以理解为什么您很难应用它。那么,以下是一个快速说明:

在Android中,每个操作都始于一个Intent。特别是针对Activities。每个Activity都有一个Intent。为了使开发人员的界面易于使用,您可以从操作系统响应Intent,也可以从Activities类创建Intent并使用。一般而言,最好采用第一种选项。

响应Intent

在选择要响应的Intent时,您可以对任何Intent进行响应。这称为操作。例如,如果我创建了一个名为“FOO”的Intent,则Bar Activity可以捕获并响应该Intent。但是我们通常会遵循惯例,其中主要的约定之一是将包名称前缀添加到任何Intent中。例如,“com.company.package.FOO”。简单地说,这样我们就可以避免与其他应用程序产生冲突。

每个Activity可能响应不同的事件。这在AndroidManifest.xml中定义。

<activity android:name="Activity3" ... >
    <intent-filter>
      <action android:name="com.company.package.FOO"/>
      <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

我们还将类别设置为DEFAULT,这样除非用户更改它,否则我们将是唯一响应我们自定义Intent的应用。然后调用Intent的方式是使用我们创建的相同名称(即"com.company.package.FOO")。

startActivity(new Intent("com.company.package.FOO"));

这就是它的工作方式!您只需将上述“com.company.package.FOO”更改为您的包名(由您的应用程序定义)和有意义的内容即可。例如,“com.testapp.ws.SWAT_FLIES”。

为什么您的代码不起作用

Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage("com.testapp.ws");

以上代码寻找特定类型的Intent动作。还记得您创建AndroidManifest和第一个Activity时放置的内容:

 <action android:name="android.intent.action.MAIN">
 <category android:name="android.intent.category.LAUNCHER">

使用getLaunchIntentForPackage()只会获取第一个Activity的Intent。这就是为什么我们需要创建自定义的Intent...首先,我们不想让第三个Activity成为启动项...其次,操作系统只会告诉我们启动Activity,我们必须使用自己的操作(即“com.testapp.ws.SWAT_FLIES”)来告诉它。

希望能对您有所帮助,

FuzzicalLogic


感谢Fuzzical Logic先生提供的详细说明。在参考了您的解释后,我已经成功地实现了这个应用程序。非常感谢! - Grant
如果我想将一个应用程序中的数据从一个活动发送到另一个应用程序中的服务,该如何实现? - Aada
实际上,在触发startService()之前,您只需要使用Intent ACTION并通过setExtra发送数据即可。您可能需要先构造Intent(例如,Intent myIntent = new Intent(“com.company.app.ACTION”))。 - Fuzzical Logic
有没有可能在TabHost内调用Activity...我已经尝试过 "firstTabSpec.setIndicator("Second Tab Name").setContent(new Intent("com.company.package.FOO"));" 但是我得到了一个“ java.lang.SecurityException: Requesting code from com.company.package (with uid 10036) to be run in process com.example.test (with uid 10037)” 的错误。 - kAnNaN
@FuzzicalLogic 我在单个活动应用程序中使用导航图尝试了相同的操作。第二个应用程序打开,但回调没有得到执行。有什么猜测吗?我的两个应用程序都只有一个活动和导航图。 - vishnuc156
显示剩余2条评论

28

步骤1:在第三个活动中添加一个自定义操作的<intent-filter>

<intent-filter>
  <action android:name="com.testapp.ws.SOMETHING_USEFUL"/>
  <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

步骤#2:使用适当的Intent启动该活动:

startActivity(new Intent("com.testapp.ws.SOMETHING_USEFUL"));

我应该在xml和Activity类中添加什么?你能详细解释一下吗?谢谢! - Grant
1
这里需要category吗? - Eng.Fouad
1
@Eng.Fouad:是的,在那个 <intent-filter> 中,你需要为 DEFAULT 类别添加一个 <category> 元素 -- 不好意思。 - CommonsWare
我需要用我的活动类名替换“SOMETHING_USEFUL”吗?请解释一下,我是编程新手! - Grant
我们是否应该像这里https://dev59.com/iGHVa4cB1Zd3GeqPrOEe#9839254中提到的那样在调用应用程序的清单中声明活动? - Muhammed Refaat
显示剩余6条评论

3

有些情况下,您可能不会使用两个特定的应用程序进行编辑,或者您可能不想创建自定义意图,在这种情况下,有一个替代方案(具有更好的可用性错误检查):

Intent intent = new Intent();
intent.setClassName("PACKAGE_NAME", "PACKAGE_NAME.TARGET_ACTIVITY");
if (isCallable(context, intent)) {
    // Attach any extras, start or start with callback
} else {
    // Respond to the application or activity not being available
}

在主类或处理通用方法的子类中:

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

如果该应用程序已在前台运行,然后仍然调用了新的意图,会发生什么? - R.singh
1
如果应用程序正在前台运行并且您输入了有效的活动,则它将返回true。此代码不会启动任何意图。意图的处理方式取决于您如何启动它以及接收应用程序如何接受它。如果重写了onNewIntent,则很可能会触发它。如果没有,则很可能会恢复。这个问题有点过于模糊,无法给出明确的答案。 - Abandoned Cart

1

这里是打开一个应用程序(例如 WhatsApp)的代码示例:

public class MainActivity extends Activity {

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button bClock = (Button) findViewById(R.id.button1);
    bClock.setOnClickListener(new OnClickListener() {
    public void onClick(View v) {
    Intent i = new Intent(Intent.ACTION_MAIN);
    PackageManager managerclock = getPackageManager();
    i = managerclock.getLaunchIntentForPackage("com.whatsapp");
    i.addCategory(Intent.CATEGORY_LAUNCHER);
    startActivity(i);
    }
    });

} }


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