2019-03-19 android 模擬點(diǎn)擊Lanucher啟動(dòng)

問題

最近在做需求,需要從外部APP跳轉(zhuǎn)到本APP的目標(biāo)面處理完結(jié)果后,返回目標(biāo)的APP。

要求不能重復(fù)打開外部APP的某個(gè)activity,必須將外部APP模擬在Launcher點(diǎn)擊啟動(dòng)一樣。

分析

在系統(tǒng)的桌面上,我們點(diǎn)擊圖標(biāo),如果應(yīng)用沒有啟動(dòng),那么應(yīng)用會(huì)從首頁(yè)啟動(dòng),如果應(yīng)用已經(jīng)啟動(dòng)過,那么應(yīng)用就會(huì)直接打開,系統(tǒng)是如何做到的呢?

經(jīng)查詢(一陣百度騷搜索),intent數(shù)據(jù)為從桌面程序中l(wèi)aucher.db數(shù)據(jù)庫(kù)favorite表中intent字段所取得的數(shù)據(jù) 為

數(shù)據(jù)可以簡(jiǎn)單理解為Intent序列化后的數(shù)據(jù)。也就是Intent需要設(shè)置為以上數(shù)據(jù)才能達(dá)到你希望的效果。

ACTION為android.intent.action.MAIN,
category為android.intent.category.LAUNCHER,
launchFlags為0x10200000,
component可以簡(jiǎn)單理解為該應(yīng)用的啟動(dòng)頁(yè)activity。
launchFlags是用來表示應(yīng)用頁(yè)的啟動(dòng)屬性,
此處0x10200000表示屬性為Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

代碼

那這樣的話,我們模擬Intent去配置相應(yīng)的flag就行了唄

  1. 通過包名找到APP啟動(dòng)頁(yè)
public static Intent getAppOpenIntentByPackageName(Context context,String packageName){
        // MainActivity完整名
        String mainAct = null;
        // 根據(jù)包名尋找MainActivity
        PackageManager pkgMag = context.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED|Intent.FLAG_ACTIVITY_NEW_TASK);

        List<ResolveInfo> list = pkgMag.queryIntentActivities(intent,
                PackageManager.GET_ACTIVITIES);
        for (int i = 0; i < list.size(); i++) {
            ResolveInfo info = list.get(i);
            if (info.activityInfo.packageName.equals(packageName)) {
                mainAct = info.activityInfo.name;
                break;
            }
        }
        if (TextUtils.isEmpty(mainAct)) {
            return null;
        }
        intent.setComponent(new ComponentName(packageName, mainAct));
        return intent;
    }

2.Intent現(xiàn)在已經(jīng)構(gòu)造好了,那么就啟動(dòng)吧,但通過搜索,對(duì)于啟動(dòng)的Context,還有這樣的處理

public static Context getPackageContext(Context context, String packageName) {
        Context pkgContext = null;
        if (context.getPackageName().equals(packageName)) {
            pkgContext = context;
        } else {
            // 創(chuàng)建第三方應(yīng)用的上下文環(huán)境
            try {
                pkgContext = context.createPackageContext(packageName,
                        Context.CONTEXT_IGNORE_SECURITY
                                | Context.CONTEXT_INCLUDE_CODE);
            } catch (NameNotFoundException e) {
                e.printStackTrace();
            }
        }
        return pkgContext;
    }

為什么要判斷context是否為被啟動(dòng)的acticity的包名呢?我在這里很迷惑

但讓我更迷惑的地方在于context.createPackageContext
注釋里面說主要作用是:創(chuàng)建其它程序的Context,通過創(chuàng)建的這個(gè)Context,就可以訪問該軟件包的資源,甚至可以執(zhí)行其它軟件包的代碼
但是有限制條件,除非他們擁有想用的用戶ID和簽名,用戶ID是什么?待解決
最后,啟動(dòng)代碼

public static boolean openPackage(Context context, String packageName) {
        Context pkgContext = getPackageContext(context, packageName);
        Intent intent = getAppOpenIntentByPackageName(context, packageName);
        if (pkgContext != null && intent != null) {
            pkgContext.startActivity(intent);
            return true;
        }
        return false;
    }

總結(jié)和問題

筆者在測(cè)試的時(shí)候遇到過兼容性問題,經(jīng)過查詢加入了** Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)**
查詢?cè)蚩刹榭磻?yīng)用launchMode

https://www.zhihu.com/question/30153342/answer/47080956
https://blog.csdn.net/wangguidong520/article/details/53331186
https://blog.csdn.net/wangbole/article/details/22876179
https://www.cnblogs.com/JianXu/p/5376642.html
http://www.itdecent.cn/p/62ee47a659f1

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容