本周末,需要做一个收到短信提醒的功能,因为好多人都换号了,但是原来的号还想用,接受到短信,不能及时处理,因此需要一个这样的应用,收到短信后可以提醒用户,或者转发过来,或者打电话通知。
Android上,可以通过两种方法实现,第一种是系统收到短信,会发送一个广播android.provider.Telephony.SMS_RECEIVED,可以实现一个BroadcastReceiver,来订阅收听这个广播。代码如下:
public class SMSReceiver extends BroadcastReceiver {
protected static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION)) {
Log.e("liufeng","action...");
SmsManager sms = SmsManager.getDefault();
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
Log.e("liufeng","pdus:"+pdus.toString());
SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
for (SmsMessage message : messages) {
String msg = message.getMessageBody();
String to = message.getOriginatingAddress();
//sms.sendTextMessage(to, null, msg, null, null);
}
}
}
}
}
另外需要在Manefest中声明这个receiver。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.sms"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8" />
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<receiver android:name="com.android.sms.SMSReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
</manifest>
但是很奇怪的是,我在模拟器还是真机上怎么都收不到短信消息,就是onReceive函数不执行。
只能用下面第二种方法。
通过ContentObserver监听数据库的变化。
public class SMSObserver extends ContentObserver {
private Cursor mCursor = null;
public SMSObserver(Context context, Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
//query inbox
Uri inSMSUri = Uri.parse("content://sms/inbox");
mCursor = mContext.getContentResolver().query(inSMSUri, null, null, null, "date desc");
if (mCursor != null) {
StringBuilder sb = new StringBuilder();
//循环遍历 while(mCursor.moveToNext()) {
int isread = mCursor.getInt(mCursor.getColumnIndex("read"));
int id = mCursor.getInt(mCursor.getColumnIndex("_id"));
if (isread == 0) {
//String strAddress = Integer.toString(mCursor.getInt(mCursor.getColumnIndex("address")));
String body = mCursor.getString(mCursor.getColumnIndex("body"));
// 把这条记录写成1
ContentValues values = new ContentValues();
values.put("read", 1);
mContext.getContentResolver().update(Uri.parse("content://sms/inbox"),
values,
"_id=?",
new String[]{"" + id});
//send sms
//sendSmsToTarget("18618197759", body);
sendOneCall("18618197759");
}
}
mCursor.close();
}
}
private void sendOneCall(String strNumber) {
Intent intent = new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+strNumber));
mContext.startActivity(intent);
}
private void sendSmsToTarget(String address, String body) {
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(address, null, body, null, null);
}
}
在需要用这个Observer的地方注册就可以了。
public class SmsManagerActivity extends Activity {
private SMSObserver smsOb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sms_manager);
smsOb = new SMSObserver(this, mHandler);
registerObserver();
}
private void registerObserver() {
Uri smsUri = Uri.parse("content://sms/");
getContentResolver().registerContentObserver(smsUri, true,smsOb);
}
}
最后也要在Menifest中声明一些权限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.liufeng.smsmanager"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.liufeng.smsmanager.SmsManagerActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
这种方法,可以监听到数据库的变化,功能没有问题。
很奇怪的是第一种方法不行,没有找到原因,有时间再研究一下。