編輯:關於Android編程
Android應用框架鼓勵開發者在開發應用時重用組件,本文將闡述如何用組件構建應用程序以及如何用intent將組件聯系起來。
如需閱讀官方原文,請您點擊這個鏈接:
《App Components》。
您還可以參考這些博文:
《Using DialogFragments》
《Fragments For All》
《Multithreading For Performance》
以及這些Training:
《Managing the Activity Lifecycle》
《Building a Dynamic UI with Fragments》
《Sharing Content》
Intent是一個傳遞消息的對象,您可以為Intent指定action來啟動其他應用組件,Intent使組件之間通信更加便利,並且通信方式有很多,這裡列舉了主要的三點:
啟動Activity:
您可以將intent作為參數調用startActivity()方法啟動一個activity。該intent描述了將要啟動的目標activity的特性並攜帶必要的數據信息。您還可以調用startActivityForResult()方法回傳信息。
啟動Service:
Service用於在後台執行任務,不與用戶交互。您可以使用startService()方法執行一次性的操作(比如後在台下載一個文件),這需要Intent參數。
如果組件之間需要向CS結構一樣通訊,您可以把Service想成一端,並調用bindService(),這同樣需要Intent參數。
傳遞一個broadcast:
broadcast是一種可以被任何應用程序截獲的廣播機制。系統會基於當前發生的事件發出各式broadcast(比如設備開機時、開始充電時等),您可以調用sendBroadcast(),、sendOrderedBroadcast()、 sendStickyBroadcast()方法發送一條廣播,這需要傳入Intent參數。
顯式Intent:通過指定具體類名啟動一個組件。顯式Intent一般用於同一應用程序內,因為您可以確定地知道要啟動的組件名。另外,Android 5.0以後規定必須顯式啟動Service。
隱式Intent:當希望啟動具備某種特性的組件時,可以使用隱式Intent,隱式Intent無需指定類名,通常用於啟動其他應用程序的組件,比如您打算啟動一個地圖定位的activity。
當您隱式地啟動一個service或activity時,Intent會根據其中的內容,匹配其他組件中manifest文件的Intent-filter,啟動符合條件的組件,並把Intent中的參數傳過去,如果有多個intent-filter滿足條件,那麼系統會彈出一個對話框,由用戶決定啟動哪個組件。下面是intent與intent-filters配合啟動組件的示意圖:
見上圖:
1、首先Activity A利用傳入的Intent調用startActivity();
2、系統會根據該Intent的條件搜索Android系統中所有匹配的組件;
3、若找到了匹配intent的intent-filters所屬的組件(Activity B),則啟動該組件,並回調onCreate()方法,同時將Intent傳遞過去。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxociAvPg0KPHA+aW50ZW50LWZpbHRlcnPKx21hbmlmZXN0zsS8/tbQ1+m8/sTasr+1xNK7uPax6sepo6y4w7Hqx6nD6Mr2wcvX6bz+vt+xuMqyw7TM2NDUo6zI57n7xPrOtMXk1sNpbnRlbnQtZmlsdGVyc6OsxMe49rjD1+m8/ta7xNyxu8/Uyr3G9LavoaM8L3A+DQo8aHIgLz4NCjxoMiBpZD0="創建intent對象building-an-intent">創建Intent對象(Building an Intent)
Intent中包含了目標組件需滿足的特性。Intent中應包含以下信息:
Component name:目標組件的名字。對於顯式啟動,這是不可缺省的,您可以使用Intent的構造方法傳入組件名稱,也可以調用setComponent(), setClass(), setClassName()這些方法傳入組件名;若是隱式啟動,這是可選的,但intent應包含其他信息(action、category、data);
Action:是一個可以指明目標組件行為的字符串。action很大程度上決定了category和data中應傳入的信息;您也可以在自己的應用程序組件中指定action,以便讓其他應用程序啟動自己的組件。對應action中字符串,不建議使用硬編碼的形式,而應在所屬組件的類中設置為常量。
常見的action有:
ACTION_VIEW:用ACTION _VIEW啟動的activity一般可以向用戶展示一些信息,比如啟動一個相冊APP中展示圖片的activity,或是啟動一個地圖APP中展示地址信息的activity。 ACTION_SEND:一般需要向 通過ACTION _SEND啟動的activity 附帶著發送一些信息,這些信息由由目標activity決定該發送給誰,比如社交類APP或是發送郵件的APP。您可以將action作為參數傳入Intent的構造方法或setAction()方法中。
如需定義在自己的組件中定義action,應以應用的包名作為前綴,比如:
static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
Data:一個URI對象是一個引用的data的表現形式,或是data的MIME類型;data的類型由Intent的action決定,比如說若action是ACTION_EDIT,那麼data的URI應指向一個可編輯的文件。當創建一個Intent時,除了為data指定URI以外,還應該指定data的MIME類型,比如說,一個用於展示圖片的activity是不能用來放音樂的,如果您要啟動這個activity,就需要將data的MIME類型指定為”image/png”、”image/jpeg”等。有些時候,從data的URI中就能推斷出MIME的類型,比如當一個URI的schema是”content://”時,表明該URI指向了設備內部的一個文件並由ContentProvider管理著,系統可以根據該文件推斷出data的MIME類型。
您可以調用setData()方法設置URI,調用setType()方法設置MIME類型,或調用setDataAndType()方法同時設置URI和MIME類型。
!請注意:如果您需要同時設置URI和MIME類型,只能調用setDataAndType()方法,而不能分別調用setData()和setType(),因為調用setData()時會首先將setType()中的內容置空,反之亦然( they each nullify the value of the other)
Category:是一個字符串,表示目標組件的附加信息,大部分intent不需要category。以下是依稀而常用的category:
CATEGORY_BROWSABLE:表示目標activity可以被網頁上的某個鏈接啟動,如圖片activity或e-mail信息activity。 CATEGORY_LAUNCHER:目標activity是任務棧的第一個activity,也就是應用程序的啟示activity。您可以將category參數傳入addCategory()方法中。
上述的參數(component name, action, data, and category)代表了intent的屬性,通過這些參數,系統可以篩選出符合條件的目標組件。除此之外,intent還可以包含下列參數,與上面的參數不同的是,系統不會使用這些參數來篩選目標組件:
Extras:一些intent可以攜帶的附加信息,以鍵值對的形式存儲。可以使用putExtra()方法將鍵值對信息傳入,也可以將鍵值對信息放在Bundle對象中,再通過將Bundle對象傳入putExtra()中。
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
Flags:該參數可以為intent添加元數據(meta-data),flag可以指導系統以何種方式啟動一個activity、是否將啟動的activity放在該應用的任務棧中,等等。
!請注意:若系統中沒有滿足隱式Intent的目標組件,則應用將崩潰(crash),所以首先應判斷,在調用startActivity()。
以下是一個通過隱式intent啟動一個“發送信息的Activity”的例子:
// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(sendIntent);
}
如果有一個目標組件滿足intent,則啟動該組件;若有多個滿足intent的目標組件,則系統彈出一個列表以供選擇。
正如向上面說,系統中可能存在多個目標組件滿足隱式intent,這時會彈出一個列表供用戶選擇,有些時候,用戶希望每次都啟動一個相同的組件(比如用戶每次都想啟動chrome浏覽器而不是系統自帶的浏覽器),這時只需要勾選“不再詢問”選項就行了,下次再啟動時,列表將不再彈出;還有些時候,用戶每次都需要對列表中的Activity進行篩選,比如啟動用於分享的Activity,用戶希望每次分享到不同的平台,這時需要調用Intent.createChooser()方法以保證每次都彈出選擇列表,如下所示:
Intent sendIntent = new Intent(Intent.ACTION_SEND);
...
// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);
// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
通過在manifest文件中配置intent-filter標簽中的action, data, and category,可以設置篩選信息,只有同時符合上述三個標簽設置的篩選信息,Intent才能開啟您的應用程序組件:
action標簽:
可匹配Intent中的action參數。
data標簽:
可匹配Intent中的data參數(URI地址以及MIME 類型)。
category標簽:
可匹配Intent中的category 參數。
!請注意:如組件需要被隱式啟動,必須配置CATEGORY_DEFAULT
如想隱式啟動一個分享的Activity,則目標Activity如下配置:
一個intent-filter中可以包含多個 action, data, category 標簽。
若組件僅希望通過本應用啟動,可將組件中的exported屬性設為false。
!請注意:為了避免隱式intent匹配上了您的Service組件,請不要在service中配置intent-filter(Service必須顯式啟動)
下面是一個社交APP的manifest文件示例:
action為 “android.intent.action.MAIN”表示該Activity是應用的主入口,且無需配置data。
category為 “android.intent.category.LAUNCHER”表示該activity的啟動圖標(通過icon屬性配置)應添加到系統的launcher中,若未配置icon,則會使用application標簽下的icon。
以上兩個屬性應成對出現。
如需隱式啟動ShareActivity,僅需匹配一個intent-filter就行了。
PendingIntent是一個包裝Intent的類,主要用於實現Intent的延時啟動,PendingIntent的主要使用場合:
包裝一個Notification的啟動Intent; 包裝一個App Widget的Intent(按Home鍵啟動的activity); 包裝一個延時啟動的activity(如AlarmManager)。使用PendingIntent啟動的activity無需使用startActivity()就能啟動,您應當使用對應組件的方法啟動相應組件:
通過PendingIntent.getActivity()啟動一個activity; 通過PendingIntent.getService()啟動一個Service; 通過PendingIntent.getBroadcast()啟動一個BroadcastReceiver;目標組件通過以下三點匹配相應的Intent:
The intent action; The intent data (both URI and data type); The intent category。intent filter可定義零到多個action標簽:
...
intent需要匹配上其中一個action標簽。如果intent-filter中沒有action標簽,則intent無需action就能匹配。
intent filter可定義零到多個category標簽:
...
intent中的定義的每一個category都需要匹配上intent-filter中的category標簽,反之不成立(intent-filter中的category標簽可能比intent中的定義的category多)。所以無論intent-filter中是否定義了category標簽,未添加category的intent總能匹配上該intent-filter。
!請注意:通過startActivity()或startActivityForResult()方法隱式啟動的intent中,將自動被添加一個CATEGORY_DEFAULT的category,所以若您希望自己的activity能夠被隱式啟動,則需要在intent-filter中添加一個android.intent.category.DEFAULT的category標簽。
intent filter可定義零到多個data標簽:
...
每個data標簽都能設置mimeType和URI 結構,其中URI可分成四部分:scheme, host, port 和 path;其結構如下:
://:/
比如:
content://com.example.project:200/folder/subfolder/etc
其中
scheme為content; host為com.example.project; port為200; path為folder/subfolder/etc。每一部分在data標簽中都不是必須定義的,但存在一個線性依賴:
若scheme 未指定,則host被忽略; 若host未指定,則port被忽略; 若scheme和host均未指定,則path被忽略;在intent中添加的data只需要匹配一部分intent-filter中的data(URI匹配):
若filter只定義了scheme,則intent的data定義的URI中只要包含了相同的scheme,就能匹配; 若filter只定義了scheme和host,則intent的data定義的URI中只要包含了相同的scheme和host,就能匹配; 若filter只定義了scheme、host和port,則intent的data定義的URI中只要包含了相同的scheme、host和port,就能匹配;intent-filter匹配intent的data中URI和mimeType類型的規則如下:
如果intent-filter中未指定data,則未添加data的intent可以匹配; 如果intent-filter中指定了URI,但未指定mimeType,則按照上一段的規則匹配(intent中也應未指定mimeType); 如果intent-filter中指定了mimeType,而未指定URI,則可以匹配intent中指定了相同mimeType,而未指定URI的組件; 如果intent-filter中同時指定了mimeType和URI,則:這篇介紹第二種自定義View方法,創建復合控件。創建復合控件創建復合控件可以很好地創建出具有重用功能的控件集合。這種方式通常需要繼承一個合適的ViewGroup,再給它添
我們知道,Android系統基於Linux實現。針對傳統Linux系統,NSA開發了一套安全機制SELinux,用來加強安全性。然而,由於Android系統有著獨特的用戶
總結下近一年的學習經歷,以中國的新年為節點。時間從2015年年後到今天,2015年年末。首先我必須要感謝前輩的書籍和高質量的博客。1、重新學習了一遍《Linux內核源代碼
對於Android的學習,需要掌握的東西有點多,需要我們認真,小心,不斷的進取。前天突然有個想法,覺得Mp3播放器是一個可以練習的項目,於是在網上搜了下,發現有人已經寫了