Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android:Intent and startActivity #64

Open
yunshuipiao opened this issue Jul 17, 2019 · 0 comments
Open

Android:Intent and startActivity #64

yunshuipiao opened this issue Jul 17, 2019 · 0 comments
Labels

Comments

@yunshuipiao
Copy link
Owner

Android:Intent and startActivity

[TOC]

本篇文章介绍在 Android 中打开另一个 Activity 的可行性验证

基础知识

App 的入口 Activity 和 Icon

    <application
    ....
    >
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

任何 App 都有一个默认入口 Activity,一般在 AndroidManifest.xml 中如上配置。

如果将 category 修改为 : <category android:name="android.intent.category.DEFAULT"/>,那么该应用在桌面icon不可见,常见于一些设置 App。

使用 Intent 打开第三方应用或者指定 Activity 的方式

  1. 只知道包名-需要有默认的入口 Activity
  2. 启动指定第三方应用的 Activity,需要包名和 Activity 名,且该 Activity 的 Export="true";
  3. 隐式启动第三方应用

使用 PackageManager.getLaunchIntentForPackage()

String package_name="xx.xx.xx";
PackageManager packageManager = context.getPackageManager();
Intent it = packageManager.getLaunchIntentForPackage(package_name);
startActivity(it);

该方法针对只知道包名,想要启动该应用时使用,对该应用的唯一限制:有默认的入口 Activity

当没有默认的入口 Activity 时,会报 空指针 异常。

因此只需要如下判断即可:

val pkg = "com.android.vending"
val intent = packageManager.getLaunchIntentForPackage(pkg) ?: return
startActivity(intent)

使用 Intent.setComponent()

    fun startActivityWithComponent(){
        val pkg = "com.coolapk.market"
//        val cls = "com.coolapk.market.view.appmanager.AppManagerActivity"
        val cls = "com.coolapk.market.view.main.MainActivity"
        val intent = Intent()
        // 可选
//        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        val comp = ComponentName(pkg, cls)
        intent.component = comp
        startActivity(intent)
    }

此方法可以启动任意的 Activity,但限制比较多。

  1. 知道 App 的包名和 Activity 的全路径名称

  2. 需要目标 Activity 在 AndroidManifest.xml 中的属性为 :Export="true"

    这里需要注意,对于自己私有的 Activity,设置 intent-filter 之后,就会设置 Export="true"

这种情况下应该如何判断该 Activity 是否可以打开:

使用:resolveActivityInfo 方法。

 fun startActivityWithComponent(){
        val pkg = "com.coolapk.market"
        val cls1 = "com.coolapk.market.view.main.MainActi"
        val cls2 = "com.coolapk.market.view.main.MainActivity"
        val arrayList = arrayListOf(cls2)
        // 可以针对 cls1, cls2 做测试
        val intent = Intent()
        // 可选
//        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        arrayList.forEach {
            val comp = ComponentName(pkg, it)
            intent.component = comp
            if (intent.resolveActivityInfo(packageManager, PackageManager.MATCH_DEFAULT_ONLY) != null) {
                startActivity(intent)
            }
        }
    }

隐式启动第三方应用

此方法用于启动系统中的功能性应用:比如电话,邮件,浏览器,图片预览等等。

 Intent intent = new Intent();
 intent.setAction(action);
 intent.addCategory(category);
 intent.setDataAndType("abc://www.dfg.com","image/gif");
 startActivity(intent);

条件:

  1. intent-filter 至少有一个action,一个 Category,可以没有 Data 和 Type。
  2. 如果有 Data,参数中 Data 比如符合规则。
  3. Action 或者 Category 必须同时匹配 Activity 中的一个 Action 和 一个 Category(默认:android.intent.category.DEFAULT)

这是,可以使用 Intent#resolveActivity方法即可判断。

Uri uri = Uri.parse("http://www.abc.xyz");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);

if (intent.resolveActivity(getPackageManager()) != null) {
	startActivity(intent);
} else {
	// 没有安装所需应用
}

总结

尽可能使用 intent.resolveActivityInfo() 方法

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant