android系統(tǒng)分享分析Intent.createChooser

系統(tǒng)提供的分享實(shí)現(xiàn)代碼如下:

Intent send = new Intent(Intent.ACTION_SEND);  
        send.setType("text/plain");  
        send.putExtra(Intent.EXTRA_TEXT, url);  
        send.putExtra(Intent.EXTRA_SUBJECT, title);    
        c.startActivity(Intent.createChooser(send, "share title"));

我們先扒一扒源碼這個(gè)是怎么實(shí)現(xiàn)分享

  • Intent.ACTION_SEND很好理解,一個(gè)隱式intent的action,在這里調(diào)用會(huì)打開(kāi)對(duì)應(yīng)的暴漏出該action的app對(duì)應(yīng)頁(yè)面(可以自己寫(xiě)個(gè)app胳赌,然后暴漏該action 也會(huì)出現(xiàn)在分享列表中)
  • 剩下就是通過(guò)intent把分享參數(shù)title text add進(jìn)去

重點(diǎn)扒一扒Intent.createChooser

  1. createChooser()方法new Intent(ACTION_CHOOSER)司致,返回的是一個(gè)Intent對(duì)象惧浴,彈出的選擇框是一個(gè)Activity,在源碼中搜索一下Action為com.android.internal.app.ChooserActivity的Activity
/android/frameworks/base/core/res/AndroidManifest.xml  

<activity android:name="com.android.internal.app.ChooserActivity"  
                android:theme="@style/Theme.Holo.Dialog.Alert"  
                android:finishOnCloseSystemDialogs="true"  
                android:excludeFromRecents="true"  
                android:multiprocess="true">  
            <intent-filter>  
                <action android:name="android.intent.action.CHOOSER" />  
                <category android:name="android.intent.category.DEFAULT" />  
            </intent-filter>  
        </activity>

  1. ChooserActivity調(diào)用了其父類(lèi)ResolverActivity的OnCreate(),ResolverActivity相當(dāng)于一個(gè)Activity的選擇器烟逊,ChooserActivity在onCreate()方法里先獲取傳遞進(jìn)來(lái)的Intent對(duì)象,取得其中攜帶的目標(biāo)Intent铺根。如果只有一個(gè)Activity適配宪躯,將直接啟動(dòng)。 ResolverActivity(queryIntentActivities)就是這個(gè)選擇對(duì)話框的Activity位迂,這里獲得適配Activity的icon和title等信息顯示到對(duì)話框访雪。如果沒(méi)有調(diào)用createChooser()方法,如果有多個(gè)Activity適配一個(gè)intent的話也會(huì)打開(kāi)一個(gè)選擇對(duì)話框掂林,不過(guò)這個(gè)對(duì)話框多了兩個(gè)選項(xiàng).

總結(jié):這下大家應(yīng)該清楚了臣缀,原來(lái)在調(diào)用createChooser()方法時(shí)候,系統(tǒng)又創(chuàng)建了一個(gè)新的Action為ACTION_CHOOSER的Intent ,并把我們的原始Intent當(dāng)成了參數(shù)傳進(jìn)去 泻帮。選擇器的title是通過(guò) EXTRA_TITLE傳入進(jìn)去的精置。

Custom choose intent

產(chǎn)品或者我們自己這個(gè)分享列表提出自己的要求,比如是否可以監(jiān)聽(tīng)這個(gè)列表點(diǎn)擊自定義跳轉(zhuǎn)锣杂、把facebook whatsapp這兩個(gè)app放在第一個(gè)脂倦、或者某個(gè)app不要出現(xiàn)在分享列表中 等這些需求該如何實(shí)現(xiàn);

  1. 監(jiān)聽(tīng)這個(gè)列表點(diǎn)擊自定義跳轉(zhuǎn)操作 答案是 NO,彈框是系統(tǒng)的ChooserActivity,并不存在暴漏出列表item點(diǎn)擊的監(jiān)聽(tīng)回調(diào)元莫,而且從隱式intent設(shè)計(jì)來(lái)講狼讨,列表中的app都是與其暴漏出的intent對(duì)應(yīng)匹配上的,它的初衷就是匹配上來(lái)就跳轉(zhuǎn)柒竞。參考回答 想實(shí)現(xiàn)監(jiān)聽(tīng)跳轉(zhuǎn)只能自定義分享列表list adapter填充列表數(shù)據(jù) 跳轉(zhuǎn)等政供,我們上個(gè)版本就是這樣實(shí)現(xiàn)的。核心代碼是獲取能分享的列表數(shù)據(jù)

         Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
         sharingIntent.setType("text/plain");
         PackageManager pm = App.getInstance().getPackageManager();
         List<List<ResolveInfo>> listArrayList = new ArrayList<>();
         List<ResolveInfo> activityList = pm.queryIntentActivities(sharingIntent, 0);
         List<ResolveInfo> newActivityList = new ArrayList<>();
    
         for (Iterator<ResolveInfo> it = activityList.iterator(); it.hasNext(); ) {
             ResolveInfo info = it.next();
             //過(guò)濾出facebook google+  whatapp  分享app單獨(dú)處理
             if (info.activityInfo.packageName.equals("com.facebook.katana") || info.activityInfo.packageName.equals("com.google.android.apps.plus") || info.activityInfo.packageName.equals("com.facebook.orca") || info.activityInfo.packageName.contains("whatsapp")) {
                 it.remove();
                 newActivityList.add(info);
             }
         }
    
    
  2. 從上面的核心代碼看既然能實(shí)現(xiàn)分享列表數(shù)據(jù)的過(guò)濾朽基,那么排序和刪除數(shù)據(jù)都可以簡(jiǎn)單實(shí)現(xiàn)布隔。但也必須是自己自定義分享彈框列表實(shí)現(xiàn)。上個(gè)版本就是這么做的

  3. 放google+分享列表實(shí)現(xiàn)(先談一個(gè)BottomSheetDialog展示特異強(qiáng)調(diào)的分享app和一個(gè)other按鈕稼虎,點(diǎn)other再進(jìn)入系統(tǒng)的分享列表) 1.難點(diǎn)是用過(guò)濾的分享數(shù)據(jù)實(shí)現(xiàn)系統(tǒng)的分享衅檀。之前系統(tǒng)的分享數(shù)據(jù)是在ChooserActivity中自己匹配的■可喜的找到了Intent中EXTRA_INITIAL_INTENTS參數(shù)哀军。具體看代碼源碼

         List<Intent> targetIntents = new ArrayList<Intent>();
         Intent shareIntent = new Intent(Intent.ACTION_SEND);
         shareIntent.setType("text/plain");
         for (ResolveInfo candidate : packages) {
             String packageName = candidate.activityInfo.packageName;
             Intent target = new Intent(android.content.Intent.ACTION_SEND);
             target.setType("text/plain");
             if (uri != null) {
                 shareIntent.setType("image/*");
                 shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
             }
             target.putExtra(Intent.EXTRA_TEXT, shareText);
             target.setComponent(new ComponentName(packageName, candidate.activityInfo.name));
    
             targetIntents.add(target);
         }
         Intent chooserIntent = Intent.createChooser(targetIntents.remove(0), title);
         chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]{}));
         context.startActivity(chooserIntent);
    
    

最終展現(xiàn)給用戶(hù)的選擇包括沉眶,符合createChooser第一個(gè)參數(shù)的應(yīng)用(其實(shí)是指定了packageName和className的Intent),以及由EXTRA_INITIAL_INTENTS指定的應(yīng)用

疑問(wèn)

  1. 注意杉适,這里沒(méi)有使用Intent.setComponent來(lái)明確指定要啟動(dòng)的Activity谎倔,而是通過(guò)setPackageName和setClass來(lái)指定。這是因?yàn)樵惩疲赾reateChooser處理過(guò)程中片习,第一個(gè)參數(shù)intent指定的component會(huì)在ResolverActivity中強(qiáng)制被設(shè)置為null。這樣的結(jié)果是什么呢?當(dāng)component被設(shè)置為null后蹬叭,targetIntents.remove(0)其實(shí)就是emailIntent藕咏,那么createChooser會(huì)顯示所有滿(mǎn)足emailIntent的應(yīng)用,然后在加上由EXTRA_INITIAL_INTENTS指定的應(yīng)用秽五。你會(huì)發(fā)現(xiàn)選擇界面中出現(xiàn)了重復(fù)的應(yīng)用孽查。

2.過(guò)濾數(shù)據(jù)處理后的系統(tǒng)分享彈框,與原聲系統(tǒng)分享彈框少了下面兩個(gè)按鈕坦喘,也少了上面最佳常用app的列表

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盲再,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子起宽,更是在濱河造成了極大的恐慌洲胖,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坯沪,死亡現(xiàn)場(chǎng)離奇詭異绿映,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)腐晾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)叉弦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人藻糖,你說(shuō)我怎么就攤上這事淹冰。” “怎么了巨柒?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵樱拴,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我洋满,道長(zhǎng)晶乔,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任牺勾,我火速辦了婚禮正罢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘驻民。我一直安慰自己翻具,他們只是感情好履怯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著裆泳,像睡著了一般叹洲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上晾虑,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天疹味,我揣著相機(jī)與錄音仅叫,去河邊找鬼帜篇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛诫咱,可吹牛的內(nèi)容都是我干的笙隙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼坎缭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼竟痰!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起掏呼,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤坏快,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后憎夷,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體莽鸿,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年拾给,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了祥得。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蒋得,死狀恐怖级及,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情额衙,我是刑警寧澤饮焦,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站窍侧,受9級(jí)特大地震影響县踢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜疏之,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一殿雪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锋爪,春花似錦丙曙、人聲如沸爸业。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)扯旷。三九已至,卻和暖如春索抓,著一層夾襖步出監(jiān)牢的瞬間钧忽,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工逼肯, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留耸黑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓篮幢,卻偏偏與公主長(zhǎng)得像大刊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子三椿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容