android 常用知識點

Android常用知識點總彙

一、系統上安裝了多種瀏覽器,能否指定某瀏覽器訪問指定頁面?請說明原由。

  如果在你的android系統上安裝了多種瀏覽器,能否指定某瀏覽器訪問指定頁面?答案當然是:肯定的。

  具體方法如下:

複製代碼
Intent intent = new Intent();        

intent.setAction("android.intent.action.VIEW");        
Uri content_uri_browsers = Uri.parse("http://isomobile.com");      
intent.setData(content_uri_browsers);        
intent.setClassName("com.android.browser",  "com.android.browser.BrowserActivity");        
startActivity(intent);
複製代碼

  問題的關鍵在於我們設置了class name,也就是我們想要跳轉的pakcage的activity。如果你想要跳轉到其它的瀏覽器,只需要修改一下這個函數就OK了。

  好,我們現在來讓剛剛的思路來指導我們的實踐。假如我們現在要直接啓動UC瀏覽器,那麼我們該怎麼做呢?讓我們step by step吧。
  1)下載UC apk:
http://i-uc.net/read.php?2
  2)用7zip解壓apk文件,得到classes.dex文件
  3)下載反編譯dex文件工具:
http://nchc.dl.sourceforge.net/project/dedexer/dedexer/1.5/ddx1.5.jarDedexer 項目主頁:  http://dedexer.sourceforge.net/
  4)執行命令:java -jar ddx1.5.jar -o -D -d c:\     c:\classes.dex
  5)得到package name是:com.uc.browser,啓動的activity是:com.uc.browser.ActivityUpdate(補充:當我在這裏選擇採用ActivityBrowser的時候發覺權限不夠,報permiss denied 異常,而且也不是我們要的那個activity,幸運的是在第二次嘗試用ActivityUpdate,剛好能滿足要求)
  6)修改上面的代碼爲intent.setClassName("com.uc.browser","com.uc.browser.ActivityUpdate");

二、請解釋下Android程序運行時權限與文件系統權限的區別

  要區分apk運行時的擁有的權限與在文件系統上被訪問(讀寫執行)的權限兩個概念。apk程序是運行在虛擬機上的,對應的是Android獨特的權限機制,只有體現到文件系統上時才使用linux的權限設置。
  (一)linux文件系統上的權限
  -rwxr-x--x system   system       4156 2010-04-30 16:13 test.apk
  代表的是相應的用戶/用戶組及其他人對此文件的訪問權限,與此文件運行起來具有的權限完全不相關。比如上面的例子只能說明system用戶擁有對此文件的讀寫執行權限;system組的用戶對此文件擁有讀、執行權限;其他人對此文件只具有執行權限。而test.apk運行起來後可以幹哪些事情,跟這個就不相關了。千萬不要看apk文件系統上屬於system/system用戶及用戶組,或者root/root用戶及用戶組,就認爲apk具有system或root權限
  (二)Android的權限規則

  (1)Android中的apk必須簽名
  這種簽名不是基於權威證書的,不會決定某個應用允不允許安裝,而是一種自簽名證書。重要的是,android系統有的權限是基於簽名的。比如:system等級的權限有專門對應的簽名,簽名不對,權限也就獲取不到。默認生成的APK文件是debug簽名的。獲取system權限時用到的簽名,見:如何使Android應用程序獲取系統權限

  (2)基於UserID的進程級別的安全機制

  大家都知道,進程有獨立的地址空間,進程與進程間默認是不能互相訪問的,是一種很可靠的保護機制。Android通過爲每一個安裝在設備上的包(apk)分配唯一的linux userID來實現,名稱爲"app_"加一個數字,比如app_43不同的UserID,運行在不同的進程,所以apk之間默認便不能相互訪問。Android提供瞭如下的一種機制,可以使兩個apk打破前面講的這種壁壘。在AndroidManifest.xml中利用sharedUserId屬性給不同的package分配相同的userID,通過這樣做,兩個package可以被當做同一個程序,系統會分配給兩個程序相同的UserID。當然,基於安全考慮,兩個package需要有相同的簽名,否則沒有驗證也就沒有意義了。(這裏補充一點:並不是說分配了同樣的UserID,兩程序就運行在同一進程, 下面爲PS指令摘取的,顯然,system、app_2分別對應的兩個進程的PID都不同,不知Android到底是怎樣實現它的機制的)

User   PID PPID
system    953   883   187340 55052 ffffffff afe0cbcc S system_server
app_2     1072 883   100264 19564 ffffffff afe0dcc4 S com.android.inputmethod.
system    1083 883   111808 23192 ffffffff afe0dcc4 S android.process.omsservi
app_2     1088 883   156464 45720 ffffffff afe0dcc4 S android.process.acore

  (3)默認apk生成的數據對外是不可見的
  實現方法是:Android會爲程序存儲的數據分配該程序的UserID。藉助於Linux嚴格的文件系統訪問權限,便實現了apk之間不能相互訪問似有數據的機制。
例:我的應用創建的一個文件,默認權限如下,可以看到只有UserID爲app_21的程序才能讀寫該文件。
  -rw------- app_21   app_21      87650 2000-01-01 09:48 test.txt

如何對外開放?
  <1> 使用MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE 標記。
When creating a new file with getSharedPreferences(String, int), openFileOutput(String, int), or openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory), you can use the MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE flags to allow any other package to read/write the file. When setting these flags, the file is still owned by your application, but its global read and/or write permissions have been set appropriately so any other application can see it.

  (4)AndroidManifest.xml中的顯式權限聲明
Android默認應用是沒有任何權限去操作其他應用或系統相關特性的,應用在進行某些操作時都需要顯式地去申請相應的權限。
一般以下動作時都需要申請相應的權限:

A particular permission may be enforced at a number of places during your program's operation: 

  • At the time of a call into the system, to prevent an application from executing certain functions.
  • When starting an activity, to prevent applications from launching activities of other applications.
  • Both sending and receiving broadcasts, to control who can receive your broadcast or who can send a broadcast to you.
  • When accessing and operating on a content provider.
  • Binding or starting a service.

  在應用安裝的時候,package installer會檢測該應用請求的權限,根據該應用的簽名或者提示用戶來分配相應的權限。在程序運行期間是不檢測權限的。如果安裝時權限獲取失敗,那執行就會出錯,不會提示用戶權限不夠。大多數情況下,權限不足導致的失敗會引發一個 SecurityException, 會在系統log(system log)中有相關記錄。

  (5)權限繼承/UserID繼承
當我們遇到apk權限不足時,我們有時會考慮寫一個linux程序,然後由apk調用它去完成某個它沒有權限完成的事情,很遺憾,這種方法是行不通的。前面講過,android權限是經營在進程層面的,也就是說一個apk應用啓動的子進程的權限不可能超越其父進程的權限(即apk的權限),即使單獨運行某個應用有權限做某事,但如果它是由一個apk調用的,那權限就會被限制。實際上,android是通過給子進程分配父進程的UserID實現這一機制的。

  (三)常見權限不足問題分析
  首先要知道,普通apk程序是運行在非root、非system層級的,也就是說看要訪問的文件的權限時,看的是最後三位。另外,通過system/app安裝的apk的權限一般比直接安裝或adb install安裝的apk的權限要高一些。
  言歸正傳,運行一個android應用程序過程中遇到權限不足,一般分爲兩種情況:
  (1)Log中可明顯看到權限不足的提示。
  此種情況一般是AndroidManifest.xml中缺少相應的權限設置,好好查找一番權限列表,應該就可解決,是最易處理的情況。有時權限都加上了,但還是報權限不足,是什麼情況呢?Android系統有一些API及權限是需要apk具有一定的等級才能運行的。比如 SystemClock.setCurrentTimeMillis()修改系統時間,WRITE_SECURE_SETTINGS權限好像都是需要有system級的權限才行。也就是說UserID是system。

  (2)Log裏沒有報權限不足,而是一些其他Exception的提示,這也有可能是權限不足造成的。比如:我們常會想讀/寫一個配置文件或其他一些不是自己創建的文件,常會報java.io.FileNotFoundException錯誤。系統認爲比較重要的文件一般權限設置的也會比較嚴格,特別是一些很重要的(配置)文件或目錄。
  -r--r----- bluetooth bluetooth      935 2010-07-09 20:21 dbus.conf
  drwxrwx--x system   system            2010-07-07 02:05 data 
  dbus.conf好像是藍牙的配置文件,從權限上來看,根本就不可能改動,非bluetooth用戶連讀的權利都沒有。/data目錄下存的是所有程序的私有數據,默認情況下android是不允許普通apk訪問/data目錄下內容的,通過data目錄的權限設置可知,其他用戶沒有讀的權限。所以adb普通權限下在data目錄下敲ls命令,會得到opendir failed, Permission denied的錯誤,通過代碼file.listfiles()也無法獲得data目錄下的內容。

  上面兩種情況,一般都需要提升apk的權限,目前我所知的apk能提升到的權限就是system(具體方法見:如何使Android應用程序獲取系統權限),
至於是否有root級的,如何提升至root級不得而知,知道的朋友勞煩告知,感激不盡。

三、AIDL的全稱是什麼?如何工作?能處理哪些類型的數據?

  詳情請參看:http://buaadallas.blog.51cto.com/399160/372090

  部分概念: 在Android每個應用程序都可以有自己的進程在寫UI應用的時候經常要用到Service. 在不同的進程中怎樣傳遞對象呢?  顯然, Java中不允許跨進程內存共享因此傳遞對象只能把對象拆分成操作系統能理解的簡單形式以達到跨界對象訪問的目的J2EE,採用RMI的方式可以通過序列化傳遞對象Android則採用AIDL的方式。 理論上AIDL可以傳遞Bundle,實際上做起來卻比較麻煩.

  AIDL(AndRoid接口描述語言)是一種藉口描述語言編譯器可以通過aidl文件生成一段代碼,通過預先定義的接口達到兩個進程內部通信進程的目的如果需要在一Activity訪問另一個Service中的某個對象需要先將對象轉化成AIDL可識別的參數(可能是多個參數), 然後使用AIDL來傳遞這些參數在消息的接收端使用這些參數組裝成自己需要的對象

  AIDLIPC的機制和COMCORBA類似是基於接口的,但它是輕量級的。它使用代理類在客戶端和實現層間傳遞值如果要使用AIDL, 需要完成2件事情: 1. 引入AIDL的相關類; 2. 調用aidl產生的class。

  AIDL的創建方法:

  AIDL語法很簡單,可以用來聲明一個帶一個或多個方法的接口,也可以傳遞參數和返回值。由於遠程調用的需要這些參數和返回值並不是任何類型.下面是些AIDL支持的數據類型:

  1. 不需要import聲明的簡單Java編程語言類型(int,boolean)

  2. String, CharSequence不需要特殊聲明

  3. List, MapParcelables類型, 這些類型內所包含的數據成員也只能是簡單數據類型, String等其他比支持的類型。

四、請解釋下在單線程模型中Message、Handler、Message Queue、Looper之間的關係。

1. Android進程
  在瞭解Android線程之前得先了解一下Android的進程。當一個程序第一次啓動的時候,Android會啓動一個LINUX進程和一個主線程。默認的情況下,所有該程序的組件都將在該進程和線程中運行。同時,Android會爲每個應用程序分配一個單獨的LINUX用戶。Android會盡量保留一個正在運行進程,只在內存資源出現不足時,Android 會嘗試停止一些進程從而釋放足夠的資源給其他新的進程使用,也能保證用戶正在訪問的當前進程有足夠的資源去及時地響應用戶的事件。Android會根據進程中運行的組件類別以及組件的狀態來判斷該進程的重要性,Android會首先停止那些不重要的進程。按照重要性從高到低一共有五個級別:

  前臺進程
  前臺進程是用戶當前正在使用的進程。只有一些前臺進程可以在任何時候都存在。他們是最後一個被結束的,當內存低到根本連他們都不能運行的時候。一般來說,在這種情況下,設備會進行內存調度,中止一些前臺進程來保持對用戶交互的響應。

  可見進程
  可見進程不包含前臺的組件但是會在屏幕上顯示一個可見的進程是的重要程度很高,除非前臺進程需要獲取它的資源,不然不會被中止。

  服務進程
  運行着一個通過startService() 方法啓動的service,這個service不屬於上面提到的2種更高重要性的。service所在的進程雖然對用戶不是直接可見的,但是他們執行了用戶非常關注的任務(比如播放mp3,從網絡下載數據)。只要前臺進程和可見進程有足夠的內存,系統不會回收他們。

  後臺進程
  運 行着一個對用戶不可見的activity(調用過 onStop() 方法).這些進程對用戶體驗沒有直接的影響,可以在服務進程、可見進程、前臺進程需要內存的時候回收。通常,系統中會有很多不可見進程在運行,他們被保存在LRU (least recently used) 列表中,以便內存不足的時候被第一時間回收。如果一個activity正確的執行了它的生命週期,關閉這個進程對於用戶體驗沒有太大的影響。

  空進程
  未運行任何程序組件。運行這些進程的唯一原因是作爲一個緩存,縮短下次程序需要重新使用的啓動時間。系統經常中止這些進程,這樣可以調節程序緩存和系統緩存的平衡。Android 對進程的重要性評級的時候,選取它最高的級別。另外,當被另外的一個進程依賴的時候,某個進程的級別可能會增高。一個爲其他進程服務的進程永遠不會比被服務的進程重要級低。因爲服務進程比後臺activity進程重要級高,因此一個要進行耗時工作的activity最好啓動一個service來做這個工作,而不是開啓一個子進程――特別是這個操作需要的時間比activity存在的時間還要長的時候。例如,在後臺播放音樂,向網上上傳攝像頭拍到的圖片,使用service可以使進程最少獲取到“服務進程”級別的重要級,而不用考慮activity目前是什麼狀態。broadcast receivers做費時的工作的時候,也應該啓用一個服務而不是開一個線程。

2. 單線程模型
  當一個程序第一次啓動時,Android會同時啓動一個對應的主線程(Main Thread),主線程主要負責處理與UI相關的事件,如用戶的按鍵事件,用戶接觸屏幕的事件以及屏幕繪圖事件,並把相關的事件分發到對應的組件進行處理。所以主線程通常又被叫做UI線程。在開發Android應用時必須遵守單線程模型的原則: Android UI操作並不是線程安全的並且這些操作必須在UI線程中執行。

2.1 子線程更新UI
  Android的UI是單線程(Single-threaded)的。爲了避免拖住GUI,一些較費時的對象應該交給獨立的線程去執行。如果幕後的線程來執行UI對象,Android就會發出錯誤訊息
CalledFromWrongThreadException。以後遇到這樣的異常拋出時就要知道怎麼回事了!

2.2 Message Queue
  在單線程模型下,爲了解決類似的問題,Android設計了一個Message Queue(消息隊列), 線程間可以通過該Message Queue並結合Handler和Looper組件進行信息交換。下面將對它們進行分別介紹:
1. Message
  Message消息,理解爲線程間交流的信息,處理數據後臺線程需要更新UI,則發送Message內含一些數據給UI線程。
2. Handler
  Handler處理者,是Message的主要處理者,負責Message的發送,Message內容的執行處理。後臺線程就是通過傳進來的 Handler對象引用來sendMessage(Message)。而使用Handler,需要implement該類的 handleMessage(Message)方法,它是處理這些Message的操作內容,例如Update UI。通常需要子類化Handler來實現handleMessage方法。
3. Message Queue
  Message Queue消息隊列,用來存放通過Handler發佈的消息,按照先進先出執行。
  每個message queue都會有一個對應的Handler。Handler會向message queue通過兩種方法發送消息:sendMessage或post。這兩種消息都會插在message queue隊尾並按先進先出執行。但通過這兩種方法發送的消息執行的方式略有不同:通過sendMessage發送的是一個message對象,會被 Handler的handleMessage()函數處理;而通過post方法發送的是一個runnable對象,則會自己執行。
4. Looper
  Looper是每條線程裏的Message Queue的管家。Android沒有Global的Message Queue,而Android會自動替主線程(UI線程)建立Message Queue,但在子線程裏並沒有建立Message Queue。所以調用Looper.getMainLooper()得到的主線程的Looper不爲NULL,但調用Looper.myLooper() 得到當前線程的Looper就有可能爲NULL。
  對於子線程使用Looper,API Doc提供了正確的使用方法:

  這個Message機制的大概流程:
  1)在Looper.loop()方法運行開始後,循環地按照接收順序取出Message Queue裏面的非NULL的Message。
  2)一開始Message Queue裏面的Message都是NULL的。當Handler.sendMessage(Message)到Message Queue,該函數裏面設置了那個Message對象的target屬性是當前的Handler對象。隨後Looper取出了那個Message,則調用該Message的target指向的Hander的dispatchMessage函數對Message進行處理。
    在dispatchMessage方法裏,如何處理Message則由用戶指定,三個判斷,優先級從高到低:
    1) Message裏面的Callback,一個實現了Runnable接口的對象,其中run函數做處理工作;
    2) Handler裏面的mCallback指向的一個實現了Callback接口的對象,由其handleMessage進行處理;
    3) 處理消息Handler對象對應的類繼承並實現了其中handleMessage函數,通過這個實現的handleMessage函數處理消息。
    由此可見,我們實現的handleMessage方法是優先級最低的!
3. Handler處理完該Message (update UI) 後,Looper則設置該Message爲NULL,以便回收!
    在網上有很多文章講述主線程和其他子線程如何交互,傳送信息,最終誰來執行處理信息之類的,個人理解是最簡單的方法——判斷Handler對象裏面的Looper對象是屬於哪條線程的,則由該線程來執行!
    1)當Handler對象的構造函數的參數爲空,則爲當前所在線程的Looper;
    2) Looper.getMainLooper()得到的是主線程的Looper對象,Looper.myLooper()得到的是當前線程的Looper對象。

五、註冊廣播有幾種方式,這些方式有何優缺點?請談談Android引入廣播機制的用意。

Android 的廣播機制  
  在 Android 裏面有各種各樣的廣播,比如電池的使用狀態,電話的接收和短信的接收都會產生一個廣播,應用程序開發者也可以監聽這些廣播並做出程序邏輯的處理。下面我畫一張粗略的圖來幫助大家理解廣播的運行機制。

  Android 中有各式各樣的廣播,各種廣播在Android 系統中運行,當系統/應用程序運行時便會向 Android 註冊各種廣播,Android 接收到廣播會便會判斷哪種廣播需要哪種事件,然後向不同需要事件的應用程序註冊事件,不同的廣播可能處理不同的事件也可能處理相同的廣播事件,這時就需要 Android 系統爲我們做篩選。

案例分析:
  一個經典的電話黑名單,首先通過將黑名單號碼保存在數據庫裏面,當來電時,我們接收到來電廣播並將黑名單號碼與數據庫中的某個數據做匹配,如果匹配的話則做出相應的處理,比如掛掉電話、比如靜音等等...

Demo 分析:
  下面通過一個小DEMO 來講解一下廣播在Android 中如何編寫,在Demo中我們設置了一個按鈕爲按鈕設置點擊監聽通過點擊發送廣播,在後臺中接收到廣播並打印LOG信息。代碼如下:

複製代碼
//BroadCastActivity 頁面代碼
public class BroadCastActivity extends Activity {
    public static final String ACTION_INTENT_TEST = "com.terry.broadcast.test";
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button btn = (Button) findViewById(R.id.Button01);
        btn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent intent = new Intent(ACTION_INTENT_TEST);
                sendBroadcast(intent);
            }
        });
    }
}

//接收器代碼如下:  

public class myBroadCast extends BroadcastReceiver {
    public myBroadCast() {
        Log.v("BROADCAST_TAG", "myBroadCast");
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        Log.v("BROADCAST_TAG", "onReceive");
    }
}
複製代碼

  Android 廣播的生命週期 在上面的接收器中,繼承了BroadcastReceiver 並重寫了它的onReceive 並構造了一個函數,下面通過圖片來一步一步認識 Android 廣播的生命週期。當我點擊一下按鈕,它向Android 發送了一個廣播,如下圖: 

   這時我們再點擊一下按鈕,它還是會再向 Android 系統發送廣播,此時日誌信息如下: 

  下面本人畫一張圖像,描述了Android 中廣播的生命週期,其次它並不像Activity 一樣複雜,運行原理很簡單如下圖:

  下面來看一下SDK給出的解釋: 

  大意爲:如果一個廣播處理完onReceive 那麼系統將認定此對象將不再是一個活動的對象,也就會finished掉它。 至此,大家應該能明白 Android 的廣播生命週期的原理,代碼也不用多介紹,很簡單的一個發送廣播並處理廣播的Demo。  

   Android 如何判斷並篩選廣播? 前 面說過 Android 的廣播有各式各樣,那麼Android 系統是如何幫我們處理我們需要哪種廣播併爲我們提供相應的廣播服務呢?這裏有一點需要大家注意,每實現一個廣播接收類必須在我們應用程序中的 manifest 中顯式的註明哪一個類需要廣播,併爲其設置過濾器,如下圖: 

  Tip:action 代表一個要執行的動作,在Andriod 中有很action 比如 ACTION_VIEW,ACTION_EDIT

  那麼有些人會問了,如果我在一個廣播接收器中要處理多個動作呢?那要如何去處理?

   在Android 的接收器中onReceive 以經爲我們想到的,同樣的你必須在Intent-filter 裏面註冊該動作,可以是系統的廣播動作也可以是自己需要的廣播,之後你之需要在onReceive 方法中,通過intent.getAction()判斷傳進來的動作即可做出不同的處理,不同的動作。具體大家可以去嘗試測試一下。

   小結:

   在Android 中如果要發送一個廣播必須使用sendBroadCast 向系統發送對其感興趣的廣播接收器中。

  • 使用廣播必須要有一個intent 對象必設置其action動作對象
  • 使用廣播必須在配置文件中顯式的指明該廣播對象
  • 每次接收廣播都會重新生成一個接收廣播的對象
  • 在BroadCast 中儘量不要處理太多邏輯問題,建議複雜的邏輯交給Activity 或者 Service 去處理

  Android廣播機制(兩種註冊方法) 

  在android下,要想接受廣播信息,那麼這個廣播接收器就得我們自己來實現了,我們可以繼承BroadcastReceiver,就可以有一個廣播接受器了。有個接受器還不夠,我們還得重寫BroadcastReceiver裏面的onReceiver方法,當來廣播的時候我們要幹什麼,這就要我們自己來實現,不過我們可以搞一個信息防火牆。具體的代碼:

複製代碼
public class SmsBroadCastReceiver extends BroadcastReceiver    
{   
    @Override  
    public void onReceive(Context context, Intent intent)   
    {   
        Bundle bundle = intent.getExtras();   
        Object[] object = (Object[])bundle.get("pdus");   
        SmsMessage sms[]=new SmsMessage[object.length];   
        for(int i=0;i<object.length;i++)   
        {   
            sms[0] = SmsMessage.createFromPdu((byte[])object[i]);   
            Toast.makeText(context, "來自"+sms[i].getDisplayOriginatingAddress()+" 的消息是:"+sms[i].getDisplayMessageBody(), Toast.LENGTH_SHORT).show();   
        }   
        //終止廣播,在這裏我們可以稍微處理,根據用戶輸入的號碼可以實現短信防火牆。   
        abortBroadcast();   
    }   
}  
複製代碼

  當實現了廣播接收器,還要設置廣播接收器接收廣播信息的類型,這裏是信息:android.provider.Telephony.SMS_RECEIVED。我們就可以把廣播接收器註冊到系統裏面,可以讓系統知道我們有個廣播接收器。這裏有兩種,一種是代碼動態註冊:

複製代碼
//生成廣播處理   
smsBroadCastReceiver = new SmsBroadCastReceiver();   
//實例化過濾器並設置要過濾的廣播   
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); 

//註冊廣播   
BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver, intentFilter);  
複製代碼

  一種是在AndroidManifest.xml中配置廣播

複製代碼
<?xml version="1.0" encoding="utf-8"?>  
<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
      package="spl.broadCastReceiver"  
      android:versionCode="1"  
      android:versionName="1.0">  
    <application android:icon="@drawable/icon" android:label="@string/app_name">  
        <activity android:name=".BroadCastReceiverActivity"  
                  android:label="@string/app_name">  
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />  
                <category android:name="android.intent.category.LAUNCHER" />  
            </intent-filter>  
        </activity>  
           
        <!--廣播註冊-->  
        <receiver android:name=".SmsBroadCastReceiver">  
            <intent-filter android:priority="20">  
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>  
            </intent-filter>  
        </receiver>  
           
    </application>  
       
    <uses-sdk android:minSdkVersion="7" />  
       
    <!-- 權限申請 -->  
    <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>  
       
</manifest>   
複製代碼

  兩種註冊類型的區別是:

     1)第一種不是常駐型廣播,也就是說廣播跟隨程序的生命週期。

     2)第二種是常駐型,也就是說當應用程序關閉後,如果有信息廣播來,程序也會被系統調用自動運行。

 

BroadcastReceiver用於監聽被廣播的事件

必須被註冊,有兩種方法:

1、在應用程序的代碼中註冊

註冊BroadcastReceiver:

registerReceiver(receiver,filter);

取消註冊BroadcastReceiver:

unregisterReceiver(receiver);

當BroadcastReceiver更新UI,通常會使用這樣的方法註冊。啓動Activity時候註冊BroadcastReceiver,Activity不可見時候,取消註冊。

2、在androidmanifest.xml當中註冊

<receiver>

    <intent-filter>

     <action android:name = "android.intent.action.PICK"/>

    </intent-filter>

</receiver>

使用這樣的方法註冊弊端:它會始終處於活動狀態,畢竟是手機開發,cpu和電源資源比較少,一直處於活動耗費大,不利。

六. Android ServiceBinderAIDL?

  作爲Android重要的後臺服務,這些每個Android開發者都應該掌握,這也算是和Java SE最大的不同了,具體的實例大家可以查看Android音樂播放器的源代碼Music.git中的,這裏不再贅述。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章