在先前的文章中,接收簡訊的監聽器會一直活在後台,哪怕程式被關閉,監聽器會一直存在並在收到訊息時啟用主程式。在一般的設計中,都不會這麼做,因為這是浪費資源且得不到良好使用者體驗的。因此需要在自己的程式並閉後,將監聽器取消。前文連結(點擊進入) 一、建立一個後台服務,該服務用於接收訊息並將訊息廣播給BroadcastReceiver。由於服務可以被終止,終止時不再轉寄訊息,背景BroadcastReceiver也因此不再生效,會自動被GC回收。程式的目標也達到了 package com.demo; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.os.IBinder; import android.telephony.gsm.SmsMessage; public class ListenService extends Service { public static final String SvrId = "RARNU.SERVICE.DEMO"; public static final String strACT = "android.provider.Telephony.SMS_RECEIVED"; private SMSMsgReceiver recv; @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); } @Override public void onCreate() { IntentFilter filter = new IntentFilter(strACT); recv = new SMSMsgReceiver(); registerReceiver(recv, filter); super.onCreate(); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { unregisterReceiver(recv); super.onDestroy(); } public class SMSMsgReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(strACT)) { StringBuilder sb = new StringBuilder(); Bundle bundle = intent.getExtras(); if (bundle != null) { Object[] pdus = (Object[]) bundle.get("pdus"); SmsMessage[] msg = new SmsMessage[pdus.length]; for (int i = 0; i < pdus.length; i++) { msg[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); } for (SmsMessage currMsg : msg) { sb.append("From:"); sb.append(currMsg.getDisplayOriginatingAddress()); sb.append("\nMessage:"); sb.append(currMsg.getDisplayMessageBody()); } } Intent i = new Intent(SvrId); i.putExtra("PARAM", sb.toString()); sendBroadcast(i); } } } } 可以看到,前文中接收簡訊的代碼被原封不動的複製到服務的代碼內,唯一不同的就是服務中多了sendBroadcast() 二、修改BroadcastReceiver package com.demo; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.widget.Toast; public class MessageReceiver extends BroadcastReceiver { public static final String SvrId = "RARNU.SERVICE.DEMO"; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().toString().equals(SvrId)) { Bundle bund = intent.getExtras(); String strParam = ""; if (bund != null) { strParam = bund.getString("PARAM"); } Intent i = new Intent(context, MsgListen.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Toast.makeText(context, strParam, Toast.LENGTH_SHORT).show(); context.startActivity(i); } } } 收簡訊的代碼被移到服務中了,那麼BroadcastReceive自然也不再需要那段代碼,直接從Extras中取得服務傳來的字串即可。 三、啟動和終止 package com.demo; import android.app.Activity; import android.content.Intent; import android.os.Bundle; public class MsgListen extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onResume() { Intent i = new Intent(MsgListen.this, ListenService.class ); i.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK ); startService(i); super.onResume(); } @Override protected void onPause() { Intent i = new Intent(MsgListen.this, ListenService.class); stopService(i); super.onPause(); } } 在程式的onResume()事件中啟動服務,在onPause()事件中停止服務 然後就可以嘗試測試一下程式了,看看是不是程式關閉後,收到簡訊不會再彈提示了呢? |