创建无图标的APP并用另一个APP启动它

  工作之余,想搞些感兴趣的东西,过程中涉及到隐藏原有APP的桌面图标并用另一个APP拉起隐藏图标的APP,于是我就想从头完整摸索一下,尽量把所有情况都测试一遍。

声明,以下测试均是针对需要拉起的APP的入口Activity进行的测试,如果想要被拉起的不是入口Activity,请另行测试

  下面就开始吧!!(ps.测试过程中被拉起的APP取名为“PulledApp”,包名为“com.peng.administrator.pulledapp”,主动拉起PulledApp的项目取名为“PullApps”

  对于被拉起的APP。一般设置隐藏图标网上有很多说法,我们都尝试一下。

1. 修改Launcher Activity的intent-filter标签,把<category android:name="android.intent.category.LAUNCHER"/>修改为<category android:name="android.intent.category.DEFAULT"/>

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

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

1.1(错误方式)在PullApps中,首先测试通过packageManager拉起APP

        val intent = packageManager.getLaunchIntentForPackage("com.peng.administrator.pulledapp")
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        startActivity(intent)

经过测试,应用直接崩溃java.lang.IllegalStateException: intent must not be null,因为intent为null,原因是我们在PulledApp的配置文件中找不到category为LAUNCHER的组件,因此无法获取到LaunchIntent。

1.2 (正确方式)其次测试设置Action和包名启动APP

        val intent = Intent()
        intent.action = Intent.ACTION_MAIN
        intent.setPackage("com.peng.administrator.pulledapp")
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        startActivity(intent)

经过测试,该方式可以顺利拉起PulledApp。代码中为intent设置了包名,目的是让程序准确找到我们想要的应用,如果不设置包名,程序会弹出一个应用选择列表,其中包含了所有声明action为android.intent.action.MAIN的应用,在列表中我们可以选择PulledApp启动它。
1.3 (正确方式)使用显式intent启动,设置component

        val intent = Intent()
        val componentName = ComponentName("com.peng.administrator.pulledapp","com.peng.administrator.pulledapp.MainActivity")
        intent.component = componentName
        startActivity(intent)

经过测试,该方式可以顺利拉起PulledApp。

2. 修改Launcher Activity的intent-filter标签,删除<category android:name="android.intent.category.LAUNCHER"/>

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

            </intent-filter>
        </activity>

2.1(错误方式)在PullApps中,首先测试通过packageManager拉起APP
代码同1.1, 经测试,该情况与1.1相同,均是java.lang.IllegalStateException: intent must not be null
2.2 (错误方式)其次测试设置Action和包名启动APP

代码同1.3

经过测试,设置action、category、package三者的任意组合都不能拉起app。android.content.ActivityNotFoundException: No Activity found to handle Intent

2.3 (正确方式)使用显式intent启动,设置component

        val intent = Intent()
        val componentName = ComponentName("com.peng.administrator.pulledapp","com.peng.administrator.pulledapp.MainActivity")
        intent.component = componentName
        startActivity(intent)

经过测试,该方式可以顺利拉起PulledApp。

3. 修改Launcher Activity的intent-filter标签,添加data声明。

        <!-- PulledApp -->
        <activity android:name=".MainActivity" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>

                <data android:scheme="pulled_app"/>
                <data android:scheme="pulled_app1" android:host="com.peng.administrator.pulledapp.mainactivity"/>
                <data android:scheme="pulled_app2" android:host="com.peng.administrator.pulledapp.mainactivity"
                      android:path="/path"/>
            </intent-filter>
        </activity>

3.1(错误方式)使用packageManager启动APP或者为intent设置data启动APP
经过测试,当Activity的category仍然声明为LAUNCHER时,无法通过pachageManager启动APP,并且不管data怎么写,都无法拉起PulledApp(android.content.ActivityNotFoundException: No Activity found to handle Intent

3.2 (正确方式)使用显式intent启动,设置component

代码同1.3

经过测试,该方式可以启动APP。

4. 修改Launcher Activity的intent-filter标签,把<category android:name="android.intent.category.LAUNCHER"/>修改为<category android:name="android.intent.category.DEFAULT"/>添加data声明。

<!-- PulledApp -->
        <activity android:name=".MainActivity" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.DEFAULT"/>

                <data android:scheme="pulled_app"/>
                <data android:scheme="pulled_app1" android:host="com.peng.administrator.pulledapp.mainactivity"/>
                <data android:scheme="pulled_app2" android:host="com.peng.administrator.pulledapp.mainactivity"
                      android:path="/path"/>
            </intent-filter>
        </activity>

4.1 使用隐式Intent启动APP
测试结果请看注释

//val uri = Uri.parse("pulled_app:")  //不行
//val uri = Uri.parse("pulled_app://")    //不行
//val uri = Uri.parse("pulled_app://com.peng.administrator.pulledapp.mainactivity")   //不行
//val uri = Uri.parse("pulled_app://com.peng.administrator.pulledapp.mainactivity/path")  //行
//val uri = Uri.parse("pulled_app1:")     //不行
//val uri = Uri.parse("pulled_app1://")   //不行
//val uri = Uri.parse("pulled_app1://com.peng.administrator.pulledapp.mainactivity")  //不行
//val uri = Uri.parse("pulled_app1://com.peng.administrator.pulledapp.mainactivity/path") //行
//val uri = Uri.parse("pulled_app2:")     //不行
//val uri = Uri.parse("pulled_app2://")   //不行
//val uri = Uri.parse("pulled_app2://com.peng.administrator.pulledapp.mainactivity")  //不行
//val uri = Uri.parse("pulled_app2://com.peng.administrator.pulledapp.mainactivity/path") //行
val uri = Uri.parse("pulled_app2://com.peng.administrator.pulledapp.mainactivity:200/path") //行

val intent = Intent()
intent.action = Intent.ACTION_MAIN
intent.addCategory(Intent.CATEGORY_DEFAULT)
intent.setPackage("com.peng.administrator.pulledapp")   //可以设置也可以不设置
intent.data = uri
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)

所有测试不行的原因都是android.content.ActivityNotFoundException: No Activity found to handle Intent
可以看到只有scheme、host、path三者都参与uri的构建时才能成功调起app,由于PulledApp里面没有设定port,所以任意给一个port也可以。

注意:测试中在同一个intent-filter标签下定义了三个data,且有的之定义了scheme,有的定义了scheme、host,还有的定义了scheme、host、path。这种情况下的匹配规则是:(1) 在隐式intent定义时,必须将所有定义的字段都进行匹配,即在创建uri时需要填写的字段应与data定义最多的保持一致。例如测试中PulledApp同一个intent-filter中的三个data标签,第三个定义了三个字段,则在PullApps创建隐式intent时需要填写scheme、host、path的值,缺一不可。(2)在填写字段的值时,只要data中定义过的都可以使用,不一定非得根据某条data填写,例如scheme的值我们可以使用pulled_app、pulled_app1、pulled_app2,host的值我们可以使用com.peng.administrator.pulledapp.mainactivity,path的值我们可以使用/path。任何一个字段的值只要是在intent-filter中定义了就可以使用。

特别声明:
经过测试,如果PulledApp的intent-filter只有一个data,即如下代码时:

		<!-- PulledApp -->
        <activity android:name=".MainActivity" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.DEFAULT"/>

                <data android:scheme="pulled_app"/>
            </intent-filter>
        </activity>

我们可以使用Uri.parse("pulled_app:")或Uri.parse("pulled_app://")来创建隐式intent。

4.2 使用显式Intent启动APP

代码同1.3
测试通过

结束语:
测试过程不全,望补充!!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值