設計一發送簡訊的程式 , 並可得知發送之後的送達結果 , 這題使用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皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....





沒有留言:
張貼留言