Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android系統教程 >> Android開發教程 >> Android 基礎

Android 基礎

編輯:Android開發教程

Android 基礎-給有java基礎的初學者(四大組件)

以前一直是在各大網站,論壇上面看各種技術點和知識點,都是需要用什麼技術點,就去找相關的帖子,從來沒有自己動手寫過;

從今天開始,我為自己定下一個目標,將andorid中用到的技術點和知識點都一條條的寫下來,方便自己以後在工作中遇到類似問題,能快速的找到解決方案------此貼均會有很多知識內容為摘錄整理,和博主自己的一些理解和看法,僅供參考,有錯誤的地方歡迎大神指點。

 

直入主題,說到android就不得說android的四大組件

andorid中的四大組件  

1.Activity (不解釋)

2.Service (服務)

3.Broadcast Receiver (廣播接收者)

4.Content Provider (內容提供者)

 

一、Activity基礎介紹

     首先貼上一張Activity的生命周期圖(圖片來至百度)

1.啟動Activity:系統會先調用onCreate(創建)方法,然後調用onStart(啟動)方法,最後調用onResume(用戶可操作)。

2.當前Activity被其他Activity覆蓋其上或被鎖屏:系統會調用onPause方法,暫停當前Activity的執行。

3.當前Activity由被覆蓋狀態回到前台或解鎖屏:系統會調用onResume方法,再次進入運行狀態。

4.當前Activity轉到新的Activity界面或按Home鍵回到主屏,自身退居後台:系統會先調用onPause方法,然後調用onStop方法,進入停滯狀態。

5.用戶後退回到此Activity:系統會先調用onRestart方法,然後調用onStart方法,最後調用onResume方法,再次進入運行狀態。

6.當前Activity處於被覆蓋狀態或者後台不可見狀態,即第2步和第4步,系統內存不足,殺死當前Activity,而後用戶退回當前Activity:再次調用onCreate方法、onStart方法、onResume方法,進入運行狀態。

7.用戶退出當前Activity:系統先調用onPause方法,然後調用onStop方法,最後調用onDestory方法,結束當前Activity。

此為Activity最基礎的生命周期介紹,後續還會單獨寫一篇Activity 的詳解 介紹四種啟動模式,以及各種菜單設置

----------------------------------------------------

二 、Service 

  Service是運行在後台,不和用戶交互應用組件。每個Service必須在manifest中 通過<service>來聲明。可以通過contect.startservice和contect.bindserverice來啟動。

  Service可以在和多場合的應用中使用,比如播放多媒體的時候用戶啟動了其他Activity這個時候程序要在後台繼續播放,比如檢測SD卡上文件的變化,再或者在後台記錄你地理信息位置的改變等等,總之服務嘛,總是藏在後頭的。

  Service和其他的應用組件一樣,運行在進程的主線程中。這就是說如果service需要很多耗時或者阻塞的操作,需要在其子線程中實現。

  Service的兩種模式(startService()/bindService()不是完全分離的)

 

本地服務 Local Service 用於應用程序內部。

  它可以啟動並運行,直至有人停止了它或它自己停止。在這種方式下,它以調用Context.startService()啟動,而以調用Context.stopService()結束。它可以調用Service.stopSelf() 或 Service.stopSelfResult()來自己停止。不論調用了多少次startService()方法,你只需要調用一次stopService()來停止服務。

  用於實現應用程序自己的一些耗時任務,比如查詢升級信息,並不占用應用程序比如Activity所屬線程,而是單開線程後台執行,這樣用戶體驗比較好。
  遠程服務 Remote Service 用於android系統內部的應用程序之間。

  它可以通過自己定義並暴露出來的接口進行程序操作。客戶端建立一個到服務對象的連接,並通過那個連接來調用服務。連接以調用Context.bindService()方法建立,以調用 Context.unbindService()關閉。多個客戶端可以綁定至同一個服務。如果服務此時還沒有加載,bindService()會先加載它。

  可被其他應用程序復用,比如天氣預報服務,其他應用程序不需要再寫這樣的服務,調用已有的即可。
   三 、Broadcast Receiver     BroadcastReceiver 廣播接收者,主要用於異步接收廣播   ·正常廣播 Normal broadcasts(用 Context.sendBroadcast()發送)是完全異步的。它們都運行在一個未定義的順序,通常是在同一時間。這樣會更有效,但意味著receiver不能包含所要使用的結果或中止的API。

  ·有序廣播 Ordered broadcasts(用 Context.sendOrderedBroadcast()發送)每次被發送到一個receiver。所謂有序,就是每個receiver執行後可以傳播到下一個receiver,也可以完全中止傳播--不傳播給其他receiver。 而receiver運行的順序可以通過matched intent-filter 裡面的android:priority來控制,當priority優先級相同的時候,Receiver以任意的順序運行。

  要注意的是,即使是Normal broadcasts,系統在某些情況下可能會恢復到一次傳播給一個receiver。 特別是receiver可能需要創建一個進程,為了避免系統超載,只能一次運行一個receiver。

  Broadcast Receiver 並沒有提供可視化的界面來顯示廣播信息。可以使用Notification和Notification Manager來實現可視化的信息的界面,顯示廣播信息的內容,圖標及震動信息。

  生命周期

  一個BroadcastReceiver 對象只有在被調用onReceive(Context, Intent)的才有效的,當從該函數返回後,該對象就無效的了,結束生命周期。

  因此從這個特征可以看出,在所調用的onReceive(Context, Intent)函數裡,不能有過於耗時的操作,不能使用線程來執行。對於耗時的操作,請start service來完成。因為當得到其他異步操作所返回的結果時,BroadcastReceiver 可能已經無效了。

  發送廣播

  事件的廣播比較簡單,構建Intent對象,可調用sendBroadcast(Intent)方法將廣播發出。另外還有sendOrderedBroadcast(),sendStickyBroadcast()等方法,請查閱API Doc。

  1.new Intent with action name

  Intent intent = new Intent(String action);

  或者 只是new Intent, 然後

  intent.setAction(String action);

  2.set data等准備好了後,in activity,

  sendBroadcast(Intent); // 發送廣播

  接收廣播

  通過定義一個繼承BroadcastReceiver類來實現,繼承該類後覆蓋其onReceiver方法,並在該方法中響應事件。
  1. public class SMSReceiver extends BroadcastReceiver { 
  2.         @Override 
  3.         public void onReceive(Context context, Intent intent) { 
  4.                 // get data from SMS intent 
  5.                 Bundle bundle = intent.getExtras(); 
  6.                 if (bundle != null){ 
  7.                         // get message by "pdus" 
  8.                         Object[] objArray = (Object[]) bundle.get("pdus"); 
  9.                         // rebuild SMS 
  10.                         SmsMessage[] messages = new SmsMessage[objArray.length]; 
  11.                         for (int i=0; i < objArray.length; i++){ 
  12.                                 messages[i] = SmsMessage.createFromPdu((byte[])objArray[i]); 
  13.                                 StringBuilder str = new StringBuilder("from: "); 
  14.                                 str.append(messages[i].getDisplayOriginatingAddress()); 
  15.                                 str.append("\nmessage:\n"); 
  16.                                 str.append(messages[i].getDisplayMessageBody()); 
  17.                                 Toast.makeText(context, str.toString(), Toast.LENGTH_LONG) 
  18.                                                 .show(); 
  19.                         } 
  20.                 } 
  21.         } 
  22. }
  注冊Receiver

  注冊有兩種方式:

  1. 靜態方式,在AndroidManifest.xml的application裡面定義receiver並設置要接收的action。

  1.   <receiver android:name=".SMSReceiver">
  2.   <intent-filter>
  3.   <action android:name="android.provider.Telephony.SMS_RECEIVED" />
  4.   </intent-filter>
  5.   </receiver>
復制代碼 2. 動態方式, 在activity裡面調用函數來注冊,和靜態的內容差不多。一個形參是receiver,另一個是IntentFilter,其中裡面是要接收的action。
  1. public class HelloDemo extends Activity {    
  2.         private BroadcastReceiver receiver;    
  3.         @Override 
  4.         protected void onStart() { 
  5.                 super.onStart(); 
  6.                 receiver = new CallReceiver(); 
  7.                 registerReceiver(receiver, new IntentFilter("android.intent.action.PHONE_STATE")); 
  8.         } 
  9.         @Override 
  10.         protected void onStop() { 
  11.                 unregisterReceiver(receiver); 
  12.                 super.onStop(); 
  13.         } 
  14. }
復制代碼   一個receiver可以接收多個action的,即可以有多個intent-filter,需要在onReceive裡面對intent.getAction(action name)進行判斷。

  個人推薦使用靜態注冊方式,由系統來管理receiver,而且程序裡的所有receiver,可以在xml裡面一目了然。而動態注冊方式,隱藏在代碼中,比較難發現。

  而且動態注冊,需要特別注意的是,在退出程序前要記得調用Context.unregisterReceiver()方法。一般在activity的onStart()裡面進行注冊, onStop()裡面進行注銷。官方提醒,如果在Activity.onResume()裡面注冊了,就必須在Activity.onPause()注銷。

  Permission權限

  要接收某些action,需要在AndroidManifest.xml裡面添加相應的permission。例如接收SMS:

  1. <uses-permission android:name="android.permission.RECEIVE_SMS" />
復制代碼   下面給出動態注冊的接收來電的廣播處理的CallReceiver的代碼:

  一種方式是直接讀取intent.getStringExtra("incoming_number")來獲取來電號碼:

  1. public class CallReceiver extends BroadcastReceiver { 
  2.         @Override 
  3.         public void onReceive(Context context, Intent intent) { 
  4.                 TelephonyManager teleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 
  5.                  
  6.                 switch(teleManager.getCallState()){ 
  7.                 case TelephonyManager.CALL_STATE_RINGING: //響鈴 
  8.                         Toast.makeText(context, "Ringing: " + intent.getStringExtra("incoming_number"), Toast.LENGTH_LONG).show(); 
  9.                         break; 
  10.                 case TelephonyManager.CALL_STATE_OFFHOOK: //接聽 
  11.                         Toast.makeText(context, "OffHook: " + intent.getStringExtra("incoming_number"), Toast.LENGTH_LONG).show(); 
  12.                         break; 
  13.                 case TelephonyManager.CALL_STATE_IDLE: //掛斷 
  14.                         Toast.makeText(m_context, "Idle: " + incomingNumber, Toast.LENGTH_LONG).show(); 
  15.                         break; 
  16.                 } 
  17.         } 
  18. }
復制代碼   在運行時,發現除了響鈴時可以獲取來電號碼,接聽和掛斷都不能成功獲取的,顯示為null。

  另一種方式是通過PhoneStateListener的onCallStateChanged來監聽狀態的變化:

  1. public class CallReceiver extends BroadcastReceiver { 
  2.         private Context m_context; 
  3.         @Override 
  4.         public void onReceive(Context context, Intent intent) { 
  5.                 m_context = context; 
  6.                 TelephonyManager teleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 
  7.                 teleManager.listen(new PhoneStateListener(){ 
  8.                         @Override 
  9.                         public void onCallStateChanged(int state, String incomingNumber) { 
  10.                                 switch(state){ 
  11.                                 case TelephonyManager.CALL_STATE_RINGING: //響鈴 
  12.                                         Toast.makeText(m_context, "Ringing: " + incomingNumber, Toast.LENGTH_LONG) 
  13.                                                                 .show(); 
  14.                                         break; 
  15.                                 case TelephonyManager.CALL_STATE_OFFHOOK: //接聽 
  16.                                         Toast.makeText(m_context, "OffHook: " + incomingNumber, Toast.LENGTH_LONG) 
  17.                                         .show(); 
  18.                                         break; 
  19.                                 case TelephonyManager.CALL_STATE_IDLE: //掛斷 
  20.                                         Toast.makeText(m_context, "Idle: " + incomingNumber, Toast.LENGTH_LONG) 
  21.                                         .show(); 
  22.                                         break; 
  23.                                 } 
  24.                         }}, PhoneStateListener.LISTEN_CALL_STATE);  
  25.         } 
  26. }
復制代碼   運行時也發現incomingNumber在接聽和掛斷時獲取為blank。

  因為這裡監聽的是通話的狀態變化,所以這個receiver會被調用3次。

  監聽通話狀態需要加上權限:

  1. <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
復制代碼   ===========

  小結:

  1. 對於sendBroadCast的intent對象,需要設置其action name;

  2. 推薦使用顯式指明receiver,在配置文件AndroidManifest.xml指明;

  3. 一個receiver可以接收多個action;

  4. 每次接收廣播都會重新生成一個接收廣播的對象,再次調用onReceive;

  5. 在BroadCast 中盡量不要處理太多邏輯問題,建議復雜的邏輯交給Activity 或者 Service 去處理。



--------------------------------------------
四、Content Provider詳解

  ContentProvider(內容提供者)是Android中的四大組件之一。主要用於對外共享數據,也就是通過ContentProvider把應用中的數據共享給其他應用訪問,其他應用可以通過ContentProvider對指定應用中的數據進行操作。ContentProvider分為系統的和自定義的,系統的也就是例如聯系人,圖片等數據。

  android中對數據操作包含有:

  file, sqlite3, Preferences, ContectResolver與ContentProvider前三種數據操作方式都只是針對本應用內數據,程序不能通過這三種方法去操作別的應用內的數據。

  android中提供ContectResolver與ContentProvider來操作別的應用程序的數據。

  使用方式:

  一個應用實現ContentProvider來提供內容給別的應用來操作,

  一個應用通過ContentResolver來操作別的應用數據,當然在自己的應用中也可以。

  以下這段是Google Doc中對ContentProvider的大致概述:

  內容提供者將一些特定的應用程序數據供給其它應用程序使用。內容提供者繼承於ContentProvider 基類,為其它應用程序取用和存儲它管理的數據實現了一套標准方法。然而,應用程序並不直接調用這些方法,而是使用一個 ContentResolver 對象,調用它的方法作為替代。ContentResolver可以與任意內容提供者進行會話,與其合作來對所有相關交互通訊進行管理。

  1.ContentProvider

  Android提供了一些主要數據類型的ContentProvider,比如音頻、視頻、圖片和私人通訊錄等。可在android.provider包下面找到一些Android提供的ContentProvider。通過獲得這些ContentProvider可以查詢它們包含的數據,當然前提是已獲得適當的讀取權限。

  主要方法:

  public boolean onCreate() 在創建ContentProvider時調用
  public Cursor query(Uri, String[], String, String[], String) 用於查詢指定Uri的ContentProvider,返回一個Cursor

  public Uri insert(Uri, ContentValues) 用於添加數據到指定Uri的ContentProvider中

  public int update(Uri, ContentValues, String, String[]) 用於更新指定Uri的ContentProvider中的數據

  public int delete(Uri, String, String[]) 用於從指定Uri的ContentProvider中刪除數據

  public String getType(Uri) 用於返回指定的Uri中的數據的MIME類型

  *如果操作的數據屬於集合類型,那麼MIME類型字符串應該以vnd.android.cursor.dir/開頭。

  例如:要得到所有person記錄的Uri為content://contacts/person,那麼返回的MIME類型字符串為"vnd.android.cursor.dir/person"。

  *如果要操作的數據屬於非集合類型數據,那麼MIME類型字符串應該以vnd.android.cursor.item/開頭。

  例如:要得到id為10的person記錄的Uri為content://contacts/person/10,那麼返回的MIME類型字符串應為"vnd.android.cursor.item/person"。

  2.ContentResolver

  當外部應用需要對ContentProvider中的數據進行添加、刪除、修改和查詢操作時,可以使用ContentResolver類來完成,要獲取ContentResolver對象,可以使用Context提供的getContentResolver()方法。

  ContentResolver cr = getContentResolver();

  ContentResolver提供的方法和ContentProvider提供的方法對應的有以下幾個方法。

  public Uri insert(Uri uri, ContentValues values) 用於添加數據到指定Uri的ContentProvider中。

  public int delete(Uri uri, String selection, String[] selectionArgs) 用於從指定Uri的ContentProvider中刪除數據。

  public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 用於更新指定Uri的ContentProvider中的數據。

  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 用於查詢指定Uri的ContentProvider。



  3.Uri

  Uri指定了將要操作的ContentProvider,其實可以把一個Uri看作是一個網址,我們把Uri分為三部分。

  第一部分是"content://"。可以看作是網址中的"http://"。

  第二部分是主機名或authority,用於唯一標識這個ContentProvider,外部應用需要根據這個標識來找到它。可以看作是網址中的主機名,比如"blog.csdn.net"。

  第三部分是路徑名,用來表示將要操作的數據。可以看作網址中細分的內容路徑。

1.jpg 
---------------------------------
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved