android intent 打开应用,【专题分析】使用Intent打开三方应用

[TOC]

# 使用Intent打开第三方应用的方式

## 通过包名打开

**必要条件**

需要第三方应用配置有默认的入口Activity。

**打开方式**

```java

Intent intent = context.getPackageManager().getLaunchIntentForPackage("com.mmbox.xbrowser.pro");

startActivity(intent);

```

当目标应用不存在或没有默认的入口Activity时,会报如下错误:

```plain

Attempt to invoke virtual method 'java.lang.String android.content.Intent.toString()' on a null object reference

```

因此启动三方应用前应进行非空判断:

```java

Intent intent = context.getPackageManager().getLaunchIntentForPackage("com.mmbox.xbrowser.pro");

if (intent == null) {

Toast.makeText(context, "找不到该应用", Toast.LENGTH_SHORT).show();

} else {

startActivity(intent);

}

```

## 通过包名和Activity打开

**必要条件**

1、需要知道三方应用的包名和Activity名

2、三方应用清单文件中,目标Activity的属性`Export`需配置为`true`

**打开方式**

```java

Intent intent = new Intent();

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

ComponentName componentName = new ComponentName("com.mmbox.xbrowser.pro", "com.mmbox.xbrowser.BrowserActivity");

intent.setComponent(componentName);

startActivity(intent);

```

当目标应用不存在、目标Activity不存在、目标Activity未被设置为`Exported=true`时,会报如下错误:

```plain

android.content.ActivityNotFoundException: Unable to find explicit activity class {xx.xx.xx/xx.xx.xxActivity}; have you declared this activity in your AndroidManifest.xml?

```

因此启动前需进行判断:

```java

Intent intent = new Intent();

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

ComponentName componentName = new ComponentName("com.mmbox.xbrowsesr.pro", "com.mmbox.xbrowser.BrowserActivity");

intent.setComponent(componentName);

if (intent.resolveActivityInfo(getPackageManager(), PackageManager.MATCH_DEFAULT_ONLY) != null) {

startActivity(intent);

} else {

Toast.makeText(context, "找不到应用", Toast.LENGTH_SHORT).show();

}

```

此处不能使用Intent.resolveActivty方法判断,具体可参考后面的源码部分。

## 隐式启动

**必要条件**

1、IntentFilter中至少有一个action,至少有一个Category,可没有Data和Type

2、如果有Data,参数中Data必须符合Data规则

3、Action和Category必须同时匹配Activity中的一个Action和一个Category

**打开方式**

```java

Uri uri = Uri.parse("http://www.baidu.com");

Intent intent = new Intent(Intent.ACTION_VIEW, uri);

startActivity(intent);

```

启动前需进行判断:

```java

Uri uri = Uri.parse("http://www.baidu.com");

Intent intent = new Intent(Intent.ACTION_VIEW, uri);

if (intent.resolveActivity(getPackageManager()) != null) {

startActivity(intent);

} else {

Toast.makeText(context, "找不到应用", Toast.LENGTH_SHORT).show();

}

```

## 源码分析

Intent的resolveActivity方法源码如下:

```java

public ComponentName resolveActivity(@NonNull PackageManager pm) {

if (mComponent != null) {

return mComponent;

}

ResolveInfo info = pm.resolveActivity(this, PackageManager.MATCH_DEFAULT_ONLY);

if (info != null) {

return new ComponentName(

info.activityInfo.applicationInfo.packageName,

info.activityInfo.name);

}

return null;

}

```

Intent的resolveActivityInfo方法源码如下:

```java

public ActivityInfo resolveActivityInfo(PackageManager pm, @PackageManager.ComponentInfoFlags int flags) {

ActivityInfo ai = null;

if (mComponent != null) {

ai = pm.getActivityInfo(mComponent, flags);

} else {

ResolveInfo info = pm.resolveActivity(this, PackageManager.MATCH_DEFAULT_ONLY | flags);

if (info != null) {

ai = info.activityInfo;

}

}

return ai;

}

```

resolveActivity和resolveActivityInfo两个方法名称相似,但是返回值却是不同的。前者返回的是ComponentName,后者返回的是ActivityInfo。在打开三方应用指定Activity时,需使用resolveActivityInfo方法进行判断。

# 总结

1、使用PackageManager.getLaunchIntentForPackage方法时,直接判断返回的Intent是否为空即可

2、使用Intent.setComponent方法时,需使用`Intent.resolveActivityInfo()`或者`packageManager.queryIntentActivities()`两种方式判断

3、隐式启动时,使用`Intent.resolveActivity()`、`Intent.resolveActivityInfo()`、`packageManager.queryIntentActivities()`三种方式均可

参考文档:[https://likfe.com/2017/08/30/android-is-intent-available/](https://likfe.com/2017/08/30/android-is-intent-available/)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值