Pro Android學習筆記(十一):瞭解Intent(中)

來源:互聯網
上載者:User

標籤:android   style   blog   http   io   color   ar   os   使用   

Intent的構成

Intent能夠帶有action,data(由URI表達),extra data(key/value map,鍵值對),指定的類名(成為component name)。一個intent至少攜帶上述的一個內容。

Action。Action名,在上一筆記中已經給出兩種範例,一種是系統內建的,如Intent.ACTION_DAIL,一種是開發人員通過AndroidManifest.xml進行注冊的,在建立intent時給出:Intent intent=new Intent(String action_name);。action_name字串的名字首碼是類名。

Data。由不同action決定有效URI的格式。intent.setData(Uri.parse(”xxxxxx”));。被喚起的activity能夠同activity.getIntent()來獲得intent,然後通該intent的getData()來擷取資料。

//觸發方。 
Intent i = new Intent(actionName);
String uriStr = "wei://www.flowingflying.com";
i.setData(Uri.parse(uriStr));
this.startActivity(i);


//被觸發方。須要在AndroidManifest.xml中在intent-filter中注冊data資訊,後文具體說明
Intent intent = this.getIntent();
String data = intent.getData();

通用的action即資料傳遞。Action和喚起的並不是是一對一的,比如Intent.ACTION_VIEW依據data,喚起不同的應用。這樣的一對多,也就是通用的action,在manifest中注冊時,須要聲明資料(URI)的要求。詳細能夠參考:http://developer.android.com/guide/topics/manifest/data-element.html。ACTION_VIEW是通過schema進行區分。通過class名字、action名字等方式進行指定的稱為explicit intent,能夠一對多的稱為implicit intent。

<activity......>
    <intent-filter> 
         <action android:name="android.intent.action.VIEW" />
         <data android:scheme="http"/>
         <data android:scheme="https"/>

    </intent-filter>
</activity>

假設我們自己的intent要傳遞data,也必需要在manifest中注冊data,否則intent會喚起失敗,報告ActivityNotFoundException的異常。

比較經常使用的還有MIME type,比如注冊<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />表示要查看notes的集合(即檔案夾),而注冊<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />則表示查看詳細item,即查看詳細的note。

擴充資料(Extra data)傳遞。uri的方式限制了資訊的傳遞量。Extra的格式key/value對,key名字通常以包名開頭,而value能夠是不論什麼基礎資料類型,或者是實現android.os.Parcelable的對象。

在IntentTestDemo.java(通過intent i喚起IntentBasicViewActivity)通過以下傳遞extra資料。
1、extra資料以bundle的方式在intent中存放,假設已經有bundle,將新的鍵值對增加當中,假設沒有bundle,則建立一個。未來確保key的唯一性
2、key名通常以包名開頭,本例以常量方式,實際為:cn.flowingflying.android.pro.extra.string。
3、以下是最最簡單據類型,還能夠是array,比如putExtra(String name, int[] values);
      能夠是Serializable對象,如putExtra(String name, Serializable value);以及Parcelable對象,如putExtra(String name,Parcelable value); 。
      能夠將bundle進行傳遞,如putExtra(String name, Bundle value);,
      能夠將Intent進行傳遞,如putExtra(String name, Intent anotherIntent);
      能夠支援Array list:如putIntegerArrayListExtra(String name, ArrayList arrayList); putParcelableArrayListExtra(String name, ArrayList arrayList);和putStringArrayListExtra(String name, ArrayList arrayList)
     【注意】在intent中傳遞的不是reference(指標),而是copy一份,我們改動對象,並不會影響已經copy進intent中bundle的資料,這點須要很注意。
i.putExtra(IntentBasicViewActivity.EXTRA_FLOWINGFLYING_STRING, "Hello, Intent! ");

在IntentBasicViewActivity.java中通過下面代碼擷取extra資料。
Intent intent = this.getIntent();
Bundle b = intent.getExtras(); 
String s =  b.getString(EXTRA_FLOWINGFLYING_STRING));

Android系統有已定義的key值,詳細參見http://developer.android.com/reference/android/content/Intent.html#EXTRA_ALARM_COUNT

使用Component來喚起Activity

之前範例,我們通過action name來喚起Activity。對於explicit intent,即明白指定調用哪個activity,能夠通過給出該Component的的package name和class name來進行調用。以下我們實驗採用四種類似的方式進行調用,這四種方式本質沒有差別。

private void basicTest1(){
    Intent intent = new Intent();
   //方式1:setComponent(ComponentName name);
    intent.setComponent(new ComponentName("cn.flowingflying.android.pro",
                                                                                 "cn.flowingflying.android.pro.IntentBasicViewActivity"));
    startActivity(intent);
}

//要寫完整的class Name,不能寫IntentBasicViewActivity或者.IntentBasicViewActivity,否則報告找不到Activity的錯誤
private void basicTest2(){
    Intent intent = new Intent(); 
    //方式2:setClassName(String packageName, String classNameInThatPackage); 
   intent.setClassName("cn.flowingflying.android.pro",   
                                       "cn.flowingflying.android.pro.IntentBasicViewActivity");

    startActivity(intent);
}
//要寫完整的class Name,不能寫IntentBasicViewActivity或者.IntentBasicViewActivity,否則報告找不到Activity的錯誤
private void basicTest3(){
    Intent intent = new Intent();
   //方式3:setClassName(Context context, String classNameInThatContext);
    intent.setClassName(this,"cn.flowingflying.android.pro.IntentBasicViewActivity");
    startActivity(intent);
}

private void basicTest4(){
    Intent intent = new Intent();
    //方式4:setClass(Context context, Class classObjectInThatContext);
   intent.setClass(this,IntentBasicViewActivity.class);
    startActivity(intent);
}

Intent的Category屬性

在AndroidManifest.xml中,我們能夠設定intent的category,比如:

<activity ……>
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

在應用啟動是,將尋找Activity標記為CATEGORY_LAUNCHER來載入。Android定義了多個Category,詳細能夠在http://developer.android.com/reference/android/content/Intent.html#CATEGORY_ALTERNATIVE中查閱。比如CATEGORY_HOME能夠作為該應用的home screen,而CATEGORY_GADGET適合嵌入到某個activity中。

以下是兩個範例。範例1指明了action name,因為存在多個匹配,系統將列出來,供使用者進行選擇,例如以下。

範例2在範例1的基礎上添加了intent.addCategory(Intent.CATEGORY_LAUNCHER);,添加對Category名字的匹配,能夠看到系統進行了進一步的過濾。:

我們能夠通過PackageManager在代碼中,能夠不喚起intent就獲得匹配的activity資訊。例如以下

Intent intent = new Intent(Intent.ACTION_MAIN,null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
PackageManager pm = getPackageManager();
List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);


for(ResolveInfo ri : list){ 
    String packageName = ri.activityInfo.packageName;
    String className = ri.activityInfo.name
    ... ....
    //有了packageName和className,就能夠進行分析,然後通過Intent i= new Intent(packaname,className); startActivity(i);喚起我們所需的acitivity。 
}

然而,通過PackageManager獲得匹配的Activity的數量多於範例中系統提供給使用者選擇的activities的數量,為何?特別是沒有將本應用顯示出來。通過category篩選屬於implicit intent的調用方式,不屬於指定軟體包名及類名的explicit intent的精確調用方式,對於implicit intent調用須要進行聲明,例如以下:

<activity  android:name="……"  android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" /> 
        <category android:name="android.intent.category.LAUNCHER" />
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

activity的intent-filter中能夠有多個category描寫敘述,當中CATEGORY_DEFAULT表示能夠使用implicit intent調用,當我們添加此項聲明後,本應用就出如今匹配的activity列表中。相同,對於通過action name來調用的,不指定包名和類名的,也屬於implicit intent,相同須要進行CATEGORY_DEFAULT的聲明,否則會出現ActivityNotFoundException的錯誤。假設activity沒有在intent fliter中設定為CATEGORY_DEFAULT,我們能夠用PackageManager擷取匹配的activities的資訊,分析後得到確切的包名和類名,通過explicit的方式喚起該activity。

此外Android說假設從launcher screen喚起時不須要DEFAULT,也就是此時acitivty僅僅需MAIN和LAUNCHER,當然我們也能夠DEFAULT設上。Android在DEFAULT上似乎有些繁雜,簡單說假設我們不希望App被其它App通過implicit調用,我們就不要設定DEFAULT。

在category中有一個有趣的類別:<category android:name="android.intent.category.HOME"/>,我們在MainActivity以及另外一個Activity添加該類別。

<application ...... >
    <activity ...... >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.HOME"/>
            <category android:name="android.intent.category.LAUNCHER" />
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </activity>
    <activity android:name=".IntentBasicViewActivity" android:label="@string/intent_basic_test">
        <intent-filter>
                <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.HOME"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </activity>
    ......
</application>

左圖在代碼中通過PackageManager來查看匹配CATEGORY_HOME的資訊;中圖通過StartActivity(intent)來喚起匹配CATEGORY_HOME的Activities時,系統給予使用者的選擇,假設在應用中按Home鍵,有相同效果;右圖為退出應用,按Home鍵,要求進入Home UI時,系統給予使用者的選擇。

相關連結: 我的Android開發相關文章

Pro Android學習筆記(十一):瞭解Intent(中)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.