設計一發送簡訊的程式 , 並可得知發送之後的送達結果 , 這題使用BroadcastReceiver 等待程式發送簡訊的動作 , 而關於BroadcastReceiver的使用有兩種方法 , 一種是靜態的在AndroidManifest.xml中在<receiver> tag中註冊 , 另一種是動態的在程式中使用 registerReceiver() method 註冊和使用unregisterReceiver()註銷 , 另外既然要讓 BroadcastReceiver 可以判斷發送簡訊的動作 , 就要在 IntentFilter 中增加發送簡訊的action , 但是 Android SDK 沒有提供相關的action , 所以我們必須使用我們自己的 custom action string , 而這題我們使用動態註冊及註銷的方式搭配自訂的 action 來達成題目要求。
package COM.TQC.GDD03; import android.app.Activity; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.telephony.SmsManager; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class GDD03 extends Activity { private Button mButton1; private EditText mEditText1, mEditText2; PendingIntent sentIntent; SmsManager smsManager; mServiceReceiver mServiceReceiver; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); /* Phone No. */ mEditText1 = (EditText) findViewById(R.id.myEditText1); /* SMS BODY */ mEditText2 = (EditText) findViewById(R.id.myEditText2); mButton1 = (Button) findViewById(R.id.myButton1); mEditText1.setText("5556"); mEditText2.setText("DAVID_SEND"); mServiceReceiver = new mServiceReceiver(); //宣告一個自訂的BroadcastReceiver , 稍後我們會在onResume() 動態註冊它 smsManager = SmsManager.getDefault(); //SmsManager 類別可以協助我們送出簡訊 , 我們可以透過 這個static method getDefault()來取得 SmsManager預設的instance Intent smsIntent = new Intent("COM.TQC.GDD03.Send_Message"); //替這個Intent 設定我們自訂的action : COM.TQC.GDD03.Send_Message //通常在action前我們會附加上 application package name smsIntent.putExtra("Data", "Hello!"); //順便附加個字串 sentIntent = PendingIntent.getBroadcast(GDD03.this, 0, smsIntent, PendingIntent.FLAG_CANCEL_CURRENT); //public static PendingIntent getBroadcast (Context context, int requestCode, Intent intent, int flags) //使用這個static method 我們會接收到一個具有像Context.sendBroadcast()行為的PendingIntent instance. //我們使用 FLAG_CANCEL_CURRENT , 用意是在產生一個新的 PendingIntent之前 , 會把舊的先cancel掉 mButton1.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub smsManager.sendTextMessage(mEditText1.getText().toString(), null, mEditText2.getText().toString(), sentIntent, null); //送出簡訊 , 並附加一個 PendingIntent sentIntent , 用意是等它回報傳送結果(result code) //並且可以從sentIntent中取得相關資訊 , 例如一些額外的錯誤提示 , 或是我們預先加入的資訊如之前的"Data" } }); } public class mServiceReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Log.d("Test","Data:"+intent.getStringExtra("Data")); //顯示之前擺入sentIntent的附加資訊 if(intent.getAction().equals("COM.TQC.GDD03.Send_Message")) { switch(getResultCode()) //取得回傳的result code { case Activity.RESULT_OK: showToast("SMS sent"); break; case SmsManager.RESULT_ERROR_RADIO_OFF: showToast("RADIO OFF"); break; case SmsManager.RESULT_ERROR_GENERIC_FAILURE: //如果是這個"一般錯誤"的case , 那麼 sentIntent 也許會附帶一組 "errorCode" 來記錄錯誤資訊 break; case SmsManager.RESULT_ERROR_NULL_PDU: //Failed because no pdu provided break; case SmsManager.RESULT_ERROR_NO_SERVICE: //Failed because service is currently unavailable break; default: showToast("NO SERVICE"); break; } } } } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); IntentFilter IFilter = new IntentFilter(); IFilter.addAction("COM.TQC.GDD03.Send_Message"); //宣告一個IntentFilter並使用我們之前自訂的action registerReceiver(mServiceReceiver,IFilter); //動態註冊BroadcastReceiver } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); unregisterReceiver(mServiceReceiver); //動態註銷BroadcastReceiver } public void showToast(String message) { Toast.makeText(this, message, Toast.LENGTH_LONG).show(); } }
在這裡有幾個重點要說明一下 , 我們選擇在 onResume() method去動態註冊custom BroadcastReceiver : mServiceReceiver , 然後選擇在onPause()的時候去註銷它 , 那是因為當程式進入pause狀態時 , 是沒辦法接收到 intent的。
另外根據PendingIntent的操作行為 , 我們選用不同的method 取得它的instance , 而它有三個不同的 static method可以協助我們取得instance , 分別是
getActivity(Context, int, Intent, int)
, getBroadcast(Context, int, Intent, int)
,getService(Context, int, Intent, int)
在這題我們要讓mServiceReceiver 可以接收到傳送簡訊的action , 所以使用getBroadcast() , 而 PendingIntent 就會附加在 SmsManager.sendTextMessage() 當傳送簡訊時被sent出去。SmsManager 類別中的
public void sendTextMessage (String destinationAddress, String scAddress, String text, PendingIntent sentIntent,PendingIntent deliveryIntent) 可以協助我們送出簡訊 , 特別是如果參數 PendingIntent sentIntent 不是null的話 , 當傳送簡訊後可以透過 getResultCode() 取得回報的 result code , 我們再根據這個 result code去判斷簡訊發送的情形是否成功 , 或是有哪些錯誤訊息。
接下來是AndroiManifest.xml , 請記得由於我們有發送簡訊這個動作 , 所以記得宣告 use-permission : android.permission.SEND_SMS
最後是main.xml
由於題目要求能判斷無線網路關閉的狀態 , 所以去設定無線裝置及網路的地方啟動飛航模式。
成功的判斷出因為沒有網路所以沒辦法成功發送簡訊的狀態
開啟另一個5556模擬器 , 可以看到畫面上有出現接收到簡訊的提示。
P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....
沒有留言:
張貼留言