Presentation is loading. Please wait.

Presentation is loading. Please wait.

第12章 廣播接收器、服務與訊息提醒 12-1 系統服務的基礎 12-2 狀態列與訊息提醒 12-3 廣播接收器 12-4 建立本地服務

Similar presentations


Presentation on theme: "第12章 廣播接收器、服務與訊息提醒 12-1 系統服務的基礎 12-2 狀態列與訊息提醒 12-3 廣播接收器 12-4 建立本地服務"— Presentation transcript:

1 第12章 廣播接收器、服務與訊息提醒 12-1 系統服務的基礎 12-2 狀態列與訊息提醒 12-3 廣播接收器 12-4 建立本地服務
12-5 再談資料分享

2 12-1 系統服務的基礎 – 說明 服務是一個在背景執行的行程,可以執行和活動一樣的工作,只是沒有使用介面,所以不會與使用者互動。例如:播放背景音樂時,之所以不會打斷我們發簡訊或收發電子郵件,因為它是一個在背景執行的服務,才能讓音樂播放不會中斷。

3 12-1 系統服務的基礎 – 服務的類型 Android的服務(Services)依據使用範圍的不同,可以分為兩種類型,如下所示:
12-1 系統服務的基礎 – 服務的類型 Android的服務(Services)依據使用範圍的不同,可以分為兩種類型,如下所示: 本地服務(Local Service):使用在Android應用程式的內部,主要是實作一些應用程式的耗時任務,例如:下載檔案、播放背景音樂和查询升级資訊等,因為服務是在背景執行,所以不會影響使用者操作應用程式,可以提昇使用者經驗,不會被一些耗時任務中斷。 遠端服務(Remote Services):使用在Android作業系統中不同應用程式之間的服務,簡單的說,這種服務可以被應用程式重複使用,例如:天氣預報服務、定位服務和感應器服務等,應用程式並不需要自行建立這些服務,而只是使用這些遠端服務。

4 12-1 系統服務的基礎 – 系統服務(System Services)
如同許多現代電腦的作業系統,Android作業系統本身就內建許多系統服務,這些服務在開機後有些就會自動啟動,而且持續執行中,因為它隨時需要提供使用者所需的服務,支援作業系統的正常運作。 Android內建相當多的系統服務,一些常用的系統服務有:定位服務、感應器服務、WIFI服務、藍牙服務、電信服務和警報服務等。

5 12-1 系統服務的基礎 – 如何使用系統服務 我們可以直接使用Manager類別來使用這些系統服務,在Activity類別是呼叫繼承自Context類別的getSystemService()方法,可以取得系統服務的Manager物件,然後透過Manager物件來存取系統服務。 一般來說,大部分系統服務是使用訂閱/取消訂閱機制來提供Android應用程式所需的服務,換句話說,我們需要註冊Android應用程式為系統服務的通知對象,在Java語言是建立傾聽者物件來實作服務事件的回撥方法(Callbacks Methods),當事件發生時,服務就會呼叫這些回撥方法。

6 12-1 系統服務的基礎 – 系統服務與電源管理 請注意!因為有些系統服務需要大量電力的供應,換句話說,它會花費較多行動裝置的電力,例如:GPS定位服務和一些感應器服務,為了節省電力,通常只有在真正需要時才會使用這些服務,以活動生命周期來說,建議在onResume()方法註冊服務的傾聽者物件;onPause()方法取消註冊服務的傾聽者物件。

7 12-2 狀態列與訊息提醒 在狀態列顯示提醒訊息 更多的提醒方式

8 在狀態列顯示提醒訊息 – 說明 狀態列(Status Bar)是行動裝置最上方的一條橫向的長條區域,不同於Windows視窗的狀態列是位在最下方(平板電腦Android 3.x也是位在最下方),Android 4.0版作業系統的狀態列是位在最上方,「通知服務」(Notification Service)是一種系統服務,可以在狀態列顯示可向下捲動的通知,例如:未接來電,如右圖所示:

9 12-2-1 在狀態列顯示提醒訊息 – 步驟一 步驟一:取得通知管理物件
在Android應用程式是使用「通知管理」(Notification Manager)的Manager物件在狀態列顯示提醒訊息和通知,如下所示: NotificationManager notif = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 程式碼呼叫Context物件的getSystemService()方法來取得NotificationManager物件,參數是NOTIFICATON_SERVICE常數。

10 12-2-1 在狀態列顯示提醒訊息 – 步驟二 步驟二:建立通知物件
在取得NotificationManager物件後,我們就可以建立Notification通知物件,如下所示: Notification note=new Notification(R.drawable.icon, "新郵件", System.currentTimeMillis()); Notification物件的內容是顯示在狀態列的訊息提醒,建構子參數有3個,第1個是在狀態列顯示的圖示,第2個是在狀態列顯示的標題文字,第3個是在通知顯示的時間,System.currentTimeMillis()類別方法可以取得現在時間。

11 12-2-1 在狀態列顯示提醒訊息 – 步驟三 步驟三:建立PendingIntent物件
對於通知的項目清單來說,我們可以按一下通知項目(因為可能有很多個)來觸發Intent意圖物件,使用的是PendingIntent物件,此物件的內容就是包裝著Intent物件,可以讓其他應用程式在稍後觸發再來送出其中的Intent物件,如下所示: Intent intent = new Intent(this, NotificationActivity.class); intent.putExtra("NOTIFICATION_ID", NOTIF_ID); PendingIntent pI = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

12 12-2-1 在狀態列顯示提醒訊息 – 步驟四 步驟四:準備通知事件的資訊
現在,我們就可以建立通知事件顯示的資訊,即通知清單中項目所需的資訊,如下所示: note.setLatestEventInfo(this,"新郵件","你有未讀郵件",pI); 程式碼使用setLastestEventInfo()方法來指定通知事件的最新資訊,其參數依序為Context物件、通知的標題文字、通知的詳細內容和PendingIntent物件。

13 12-2-1 在狀態列顯示提醒訊息 – 步驟五 步驟五:通知使用者 最後,我們可以通知使用者來顯示提醒訊息,如下所示:
notif.notify(NOTIF_ID, note); 上述程式碼使用NotificationManager物件的notify()方法來通知使用者,第1個參數是唯一的通知識別碼,第2個參數是Notification物件。

14 12-2-1 在狀態列顯示提醒訊息 – 步驟六 步驟六:取消狀態列的提醒訊息 在通知啟動的活動可以取消狀態列的提醒訊息,如下所示:
NotificationManager notif = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); notif.cancel(getIntent().getExtras(). getInt("NOTIFICATION_ID")); 程式碼是在活動的onCreate()方法取得NotificationManager物件後,呼叫cancel()方法來取消狀態列的提醒訊息,參數是Intent物件傳遞的通知識別碼。

15 更多的提醒方式 - 使用振動提醒使用者 Notification類別支援vibrate屬性來指定振動範本,可以讓我們在訊息提醒外,加上振動效果,如下所示: Notification note=new Notification(R.drawable.icon, "新郵件", System.currentTimeMillis()); note.vibrate= new long[] {100, 250, 100, 500}; vibrate屬性值是一個long陣列,第1個元素是等待時間,第2個元素是振動時間,以此類推,以此例就是:100ms等待,250ms振動,再100ms等待,500ms振動。 行動裝置除了硬體支援外,還需要在AndroidManifest.xml檔案加上使用振動的權限,如下所示: <uses-permission android:name="android.permission.VIBRATE"/>

16 12-2-2 更多的提醒方式 - 使用LED燈提醒使用者
Notification類別也支援LED閃爍的提醒,我們只需指定相關屬性值,就可以在行動裝置關閉螢幕時,閃爍LED燈來提醒使用者,如下所示: note.ledARGB = Color.RED; note.flags |= Notification.FLAG_SHOW_LIGHTS; note.ledOnMS = 200; note.ledOffMS = 300;

17 12-3 廣播接收器 建立廣播接收器 送出與接收自訂廣播 系統服務與廣播接收器

18 建立廣播接收器 – 基礎 Android系統本身就會常常發出廣播,例如:接到來電、收到簡訊、啟動相機裝置、時區改變、系統開機、電池剩餘電量過低或使用者選擇偏好語言時,Android系統都會發出廣播。 我們可以將廣播接收器想像是停車場上的多輛轎車,駕駛手上的遙控器就是廣播發送者,因為頻率不同,一輛轎車只能接收指定遙控器頻率的廣播,等到轎車接到廣播,就解開門鎖,駕駛才能打開車門進入車輛,其他駕駛的遙控器就沒有作用。

19 12-3-1 建立廣播接收器 – 建立廣播接收器接收系統廣播
建立廣播接收器 – 建立廣播接收器接收系統廣播 廣播接收器本身並沒有任何使用介面,它是一個繼承android.content.BroadcastReceiver抽象類別的子類別,等到接收到指定的廣播而觸發時,即在實作的onReceive()抽象方法(因為是抽象方法,繼承的子類別一定要實作此方法)回應廣播來執行所需操作,如下所示: public class Ch12_3_1BroadcastReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { // 處理接收的廣播 }

20 送出與接收自訂廣播 – 說明 Android應用程式也可以送出自訂廣播,從一個活動至另一個活動,或完全不同的Android應用程式,例如:使用廣播讓其他應用程式知道它已經完成檔案下載,在Java程式是使用Intent物件的sendBroadcast()方法來送出自訂廣播。 因為廣播接收器類別本身並沒有程式進入點,在行動裝置安裝廣播接收器後,使用者並不能直接執行,我們需要在活動透過Intent意圖物件發出廣播來啟動。

21 送出與接收自訂廣播 – 說明 基本上,我們可以從活動送出廣播,為了方便說明,本節範例專案是將送出廣播的活動和廣播接收器置於同一個專案,在實務上,通常都是從一個Android應用程式送出廣播,讓另一個廣播接收器的Android應用程式接收廣播,而少在同一個應用程式使用廣播接收器。

22 12-3-2 送出與接收自訂廣播 – 建立活動送出自訂廣播
送出與接收自訂廣播 – 建立活動送出自訂廣播 在活動送出廣播一樣是使用Intent意圖物件,如下所示: public void btn1_Click(View view) { Intent i = new Intent("android.broadcast.TOAST"); sendBroadcast(i); } btn1_Click()方法是事件處理方法,在建立Intent物件後,使用sendBroadcast()方法送出廣播,Intent物件的建構子參數是廣播接收器註冊的動作名稱android.broadcast.TOAST,換句話說,我們發出的是不明確接收者的廣播。

23 12-3-2 送出與接收自訂廣播 – 建立廣播接收器接收自訂廣播
送出與接收自訂廣播 – 建立廣播接收器接收自訂廣播 等到接收到指定廣播而觸發時,廣播接收器可以啟動活動、服務、顯示通知或訊息文字,即在實作的onReceive()抽象方法回應廣播來執行所需操作,如下所示: public void onReceive(Context context, Intent intent) { Toast.makeText(context, "收到Toast廣播!", Toast.LENGTH_SHORT).show(); } ToastBroadcastReceiver類別的onReceive()方法在接到廣播後,使用Toast類別顯示收到廣播的訊息文字。

24 12-3-2 送出與接收自訂廣播 – AndroidManifest.xml
<receiver android:name=".ToastBroadcastReceiver"> <intent-filter> <action android:name="android.broadcast.TOAST"/> </intent-filter> </receiver>

25 系統服務與廣播接收器 – 說明 在實務上,我們可以透過系統服務發出廣播,然後在廣播接收器使用系統服務來回應廣播,例如:建立倒數計時的Android應用程式,它是使用AlertManager鬧鐘管理員在計時到後發出廣播,然後在廣播接收器使用Vibrator系統服務讓行動裝置振動來回應計時已經到了。

26 12-3-3 系統服務與廣播接收器 – 使用鬧鐘管理員排程發出廣播(PedingIntent)
Android作業系統的鬧鐘服務(Alarm Services)可以排程在指定時間點送出廣播,並且自動啟動目標應用程式,簡單的說,就是提供定時服務的功能。 在本節是使用ALARM_SERVICE系統服務的AlarmManager物件在時間到達時送出廣播給指定的廣播接收器,它是使用PendingIntent物件來包裝攜帶Intent物件,如下所示: Intent i = new Intent(this, AlarmBroadcastReceiver.class); PendingIntent pi = PendingIntent.getBroadcast( this, 1234, i, 0);

27 12-3-3 系統服務與廣播接收器 – 使用鬧鐘管理員排程發出廣播(取得系統服務)
系統服務與廣播接收器 – 使用鬧鐘管理員排程發出廣播(取得系統服務) 我們使用getSystemService()方法取得系統服務的AlarmManager物件,如下所示: AlarmManager alarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE); 程式碼呼叫Context物件的getSystemService()方法來取得AlarmManager物件,參數是ALARM_SERVICE常數。 在取得AlarmManager物件後,就可以使用set()方法來指定排程的時間,如下所示: alarmMgr.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+ (seconds * 1000), pi);

28 12-3-3 系統服務與廣播接收器 – 在廣播接收器使用Vibrator系統服務
等到接收到AlarmManage的廣播而觸發時,廣播接收器可以在實作的onReceive()抽象方法回應廣播來執行所需的操作,如下所示: public void onReceive(Context context, Intent intent) { Toast.makeText(context, "倒數計時的時間已經到了!", Toast.LENGTH_LONG).show(); Vibrator vibrator = (Vibrator) context.getSystemService( Context.VIBRATOR_SERVICE); vibrator.vibrate(1500); // 1秒半 }

29 12-4 建立本地服務 服務的生命周期 建立本地服務 建立與活動通訊的本地服務

30 服務的生命周期 – 說明 服務(Services)是在背景執行,所以一些耗時或在背景執行不影響使用者操作的任務,都可以使用本地服務來處理,例如:播放音樂和掃描SD卡上的媒體檔案等。

31 服務的生命周期 – 回撥方法 Android的服務並不能自行啟動,我們需要透過其他元件使用Context.startService()或Context.bindService()方法來啟動服務。服務的生命周期就是Android作業系統依序呼叫的一些回撥方法,如下表所示: 方法 說明 onCreate() 作業系統當服務第1次啟動時呼叫,請注意!我們不可以直接呼叫此方法 onDestroy() 當服務不再需要時,作業系統呼叫此方法來移除服務 onStartCommand() 每一次客戶端明確的啟動服務,就會呼叫一次此方法,舊版名為onStart()方法 onBind() 傳回客戶端可以與服務通訊的通訊通道(Communications Channel) onRebind() 當有新的客戶端連接服務時,就呼叫此方法 onUnbind() 當所有客戶端都斷線時,呼叫此方法

32 12-4-1 服務的生命周期 – 使用startService()方法啟動服務-1
服務的生命周期就是作業系統依序呼叫上表的回撥方法,當應用程式呼叫startService()方法啟動服務後,系統就依序呼叫onCreate()和onStartCommand()方法,此時的服務便處於執行狀態,如下圖所示:

33 12-4-1 服務的生命周期 – 使用startService()方法啟動服務-2
當應用程式呼叫stopService()方法停止服務,就是呼叫onDestroy()方法,如下圖所示:

34 12-4-1 服務的生命周期 – 使用bindService()方法啟動服務
如果服務是呼叫bindService()方法來啟動,作業系統只會呼叫onCreate()方法,而不會呼叫onStartCommand()方法,如右圖所示:

35 建立本地服務 - 說明 除了第12-1節的系統服務外,我們也可以自行建立本地服務,如同活動和廣播接收器一般,我們需要繼承android.app.Service抽象類別來建立本地服務的類別,如下圖所示:

36 12-4-2 建立本地服務 – 程式碼 public class CountService extends Service { …
@Override public void onCreate() { super.onCreate(); } public void onDestroy() { super.onDestroy(); public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; public IBinder onBind(Intent arg0) { return null;

37 建立與活動通訊的本地服務 – 說明 CountService服務是直接修改上一節的同名服務,因為使用bindService()方法啟動服務不會呼叫onStartCommand()方法,所以將計數的執行緒改在onCreate()方法,新增getCount()方法傳回目前計數。

38 12-4-3 建立與活動通訊的本地服務 – 在服務宣告Binder內層類別
因為活動需要和服務建立連接(透過Binder物件建立連接),所以在CountService類別需要宣告Binder內層類別,如下所示: private ServiceBinder sBinder = new ServiceBinder(); .... public class ServiceBinder extends Binder { CountService getService() { return CountService.this; } 實作的onBind()方法就是傳回此ServiceBinder物件sBinder,如下所示: @Override public IBinder onBind(Intent intent) { return sBinder;

39 12-4-3 建立與活動通訊的本地服務 – 在活動建立ServiceConnection介面物件
活動是透過ServiceConnection物件和服務的Binder物件建立連接,如下所示: private CountService s; private ServiceConnection myConnection = new ServiceConnection() { public void onServiceConnected( ComponentName className, IBinder binder) { s = ((CountService.ServiceBinder) binder).getService(); } public void onServiceDisconnected( ComponentName className) { s = null; };

40 12-4-3 建立與活動通訊的本地服務 – 啟動服務和建立活動與服務之間的連接
建立與活動通訊的本地服務 – 啟動服務和建立活動與服務之間的連接 在這一節的CountService服務是使用bindService()方法啟動服務,位在活動覆寫的onCreate()方法,如下所示: bindService(new Intent(this, CountService.class), myConnection, BIND_AUTO_CREATE); Context類別的bindService()方法共有3個參數,第1個是啟動服務的Intent物件,第2個是ServiceConnection介面物件,最後1個是旗標值,BIND_AUTO_CREATE是自動啟動服務和建立連接。

41 12-4-3 建立與活動通訊的本地服務 – 中斷活動與服務之間的連接
建立與活動通訊的本地服務 – 中斷活動與服務之間的連接 在onDestroy()方法可以中斷與服務之間的連接,使用的是unbindService()方法,參數是ServiceConnection介面物件,如下所示: unbindService(myConnection);

42 12-5 再談資料分享 – 說明 在第10章說明的偏好設定檔、檔案和資料庫都可以在Android應用程式中各活動之間分享資料,第11章的內容提供者可以在應用程式之間分享資料,通常是在分享資料庫的資料。 一般來說,應用程式建立內容提供者的機會並不多,反而更多機會是使用Android作業系統內建的內容提供者,例如:聯絡人資料。而且,偏好設定檔和檔案也不只可以在同一個應用程式的活動之間分享資料,如果需要,我們也可以在Android應用程式讀取其他應用程式的偏好設定檔和檔案。

43 12-5 再談資料分享 – 來源應用程式的偏好設定檔
12-5 再談資料分享 – 來源應用程式的偏好設定檔 對於準備存取其他應用程式的來源偏好設定檔和檔案,我們需要使用MODE_WORLD_READLABLE模式來開啟,例如:在Android專案Ch12_5S取得偏好設定檔,如下所示: private SharedPreferences prefs; ….. prefs = getSharedPreferences("MyPREFS", MODE_WORLD_READABLE); getSharedPreferences()方法的第2個參數是MODE_WORLD_READABLE模式,而不是第10章的MODE_PRIVAT。

44 12-5 再談資料分享 – 來源應用程式的檔案 同樣的,開啟檔案也是使用MODE_WORLD_READABLE,而不是MODE_PRIVAT,如下所示: private String fname = "note.txt"; ….. FileOutputStream out = openFileOutput( fname,MODE_WORLD_READABLE);

45 12-5 再談資料分享 – 讀取來源應用程式的偏好設定檔和檔案
12-5 再談資料分享 – 讀取來源應用程式的偏好設定檔和檔案 我們可以建立Android應用程式讀取來源應用程式的偏好設定檔,首先取得來源應用程式的Context物件,如下所示: private Context Ch12_5S = null; try { Ch12_5S = createPackageContext( "android_Examples.ch12.ch12_5S", 0); } catch (Exception ex) { ex.printStackTrace(); finish(); 使用來源應用程式的Context物件取得偏好設定檔,如下所示: SharedPreferences prefs; prefs = Ch12_5S.getSharedPreferences("MyPREFS", MODE_WORLD_READABLE);

46 12-5 再談資料分享 – 讀取來源應用程式的檔案 同理,我們也可以開啟來源應用程式的分享檔案,如下所示:
12-5 再談資料分享 – 讀取來源應用程式的檔案 同理,我們也可以開啟來源應用程式的分享檔案,如下所示: FileInputStream in = Ch12_5S.openFileInput(fname); 程式碼是使用來源應用程式的Context物件來開啟讀取檔案,然後就可以讀取檔案內容,這部分和第10章並沒有什麼不同。

47 End


Download ppt "第12章 廣播接收器、服務與訊息提醒 12-1 系統服務的基礎 12-2 狀態列與訊息提醒 12-3 廣播接收器 12-4 建立本地服務"

Similar presentations


Ads by Google