Android手机上监听短信的两种方式【转】
Android手机上监听短信有两种方式:
1、 接受系统的短信广播,操作短信内容。
优点:操作方便,适合简单的短信应用。
缺点:来信会在状态栏显示通知信息。
AndroidManifest.xml:
<uses-permission android:name="android.permission.SEND_SMS"></uses-permission>
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
<!-- Receiver -->
<receiver android:name=".sms.SMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
<!-- Receiver -->
<receiver android:name=".sms.SMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
代码:
package org.anymobile.demo.sms;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.gsm.SmsMessage;
import android.util.Log;
public class SMSReceiver extends BroadcastReceiver
{
public static final String TAG = "ImiChatSMSReceiver";
//android.provider.Telephony.Sms.Intents
public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
@Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(SMS_RECEIVED_ACTION))
{
SmsMessage[] messages = getMessagesFromIntent(intent);
for (SmsMessage message : messages)
{
Log.i(TAG, message.getOriginatingAddress() + " : " +
message.getDisplayOriginatingAddress() + " : " +
message.getDisplayMessageBody() + " : " +
message.getTimestampMillis());
}
}
}
public final SmsMessage[] getMessagesFromIntent(Intent intent)
{
Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
byte[][] pduObjs = new byte[messages.length][];
for (int i = 0; i < messages.length; i++)
{
pduObjs[i] = (byte[]) messages[i];
}
byte[][] pdus = new byte[pduObjs.length][];
int pduCount = pdus.length;
SmsMessage[] msgs = new SmsMessage[pduCount];
for (int i = 0; i < pduCount; i++)
{
pdus[i] = pduObjs[i];
msgs[i] = SmsMessage.createFromPdu(pdus[i]);
}
return msgs;
}
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.gsm.SmsMessage;
import android.util.Log;
public class SMSReceiver extends BroadcastReceiver
{
public static final String TAG = "ImiChatSMSReceiver";
//android.provider.Telephony.Sms.Intents
public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
@Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(SMS_RECEIVED_ACTION))
{
SmsMessage[] messages = getMessagesFromIntent(intent);
for (SmsMessage message : messages)
{
Log.i(TAG, message.getOriginatingAddress() + " : " +
message.getDisplayOriginatingAddress() + " : " +
message.getDisplayMessageBody() + " : " +
message.getTimestampMillis());
}
}
}
public final SmsMessage[] getMessagesFromIntent(Intent intent)
{
Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
byte[][] pduObjs = new byte[messages.length][];
for (int i = 0; i < messages.length; i++)
{
pduObjs[i] = (byte[]) messages[i];
}
byte[][] pdus = new byte[pduObjs.length][];
int pduCount = pdus.length;
SmsMessage[] msgs = new SmsMessage[pduCount];
for (int i = 0; i < pduCount; i++)
{
pdus[i] = pduObjs[i];
msgs[i] = SmsMessage.createFromPdu(pdus[i]);
}
return msgs;
}
}
2、 应用观察者模式,监听短信数据库,操作短信内容。
优点:可以拦截来信在状态栏的显示通知,适合作短信拦截。
缺点:可以发展成MU,在后台悄悄的收/发短信。
实例如下:
SystemEventReceiver:收到开机启动OK的广播后,启动BootService服务;收到应用发送短信的INTENT后,调用系统接口发送短信
BootService:开启服务后,打开短信监听器
SMSObserver:数据观察者,监听短信数据库
SMSHandler:短信处理器
AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_SMS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_SMS"></uses-permission>
<!-- Service -->
<service android:name=".BootService"
android:label="@string/app_name">
<intent-filter>
<action android:name="org.anymobile.test.service.IMICHAT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
<!-- Receiver -->
<receiver android:name=".SystemEventReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.WRITE_SMS"></uses-permission>
<!-- Service -->
<service android:name=".BootService"
android:label="@string/app_name">
<intent-filter>
<action android:name="org.anymobile.test.service.IMICHAT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
<!-- Receiver -->
<receiver android:name=".SystemEventReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
package org.anymobile.demo.sms;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class SMSHandler extends Handler
{
public static final String TAG = "SMSHandler";
private Context mContext;
public SMSHandler(Context context)
{
super();
this.mContext = context;
}
public void handleMessage(Message message)
{
Log.i(TAG, "handleMessage: " + message);
MessageItem item = (MessageItem) message.obj;
//delete the sms
Uri uri = ContentUris.withAppendedId(SMS.CONTENT_URI, item.getId());
mContext.getContentResolver().delete(uri, null, null);
Log.i(TAG, "delete sms item: " + item);
}
}
package org.anymobile.demo.sms;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class SMSObserver extends ContentObserver
{
public static final String TAG = "SMSObserver";
private static final String[] PROJECTION = new String[]
{
SMS._ID,//0
SMS.TYPE,//1
SMS.ADDRESS,//2
SMS.BODY,//3
SMS.DATE,//4
SMS.THREAD_ID,//5
SMS.READ,//6
SMS.PROTOCOL//7
};
private static final String SELECTION =
SMS._ID + " > %s" +
// " and " + SMS.PROTOCOL + " = null" +
// " or " + SMS.PROTOCOL + " = " + SMS.PROTOCOL_SMS + ")" +
" and (" + SMS.TYPE + " = " + SMS.MESSAGE_TYPE_INBOX +
" or " + SMS.TYPE + " = " + SMS.MESSAGE_TYPE_SENT + ")";
private static final int COLUMN_INDEX_ID = 0;
private static final int COLUMN_INDEX_TYPE = 1;
private static final int COLUMN_INDEX_PHONE = 2;
private static final int COLUMN_INDEX_BODY = 3;
private static final int COLUMN_INDEX_PROTOCOL = 7;
private static final int MAX_NUMS = 10;
private static int MAX_ID = 0;
private ContentResolver mResolver;
private Handler mHandler;
public SMSObserver(ContentResolver contentResolver, Handler handler)
{
super(handler);
this.mResolver = contentResolver;
this.mHandler = handler;
}
@Override
public void onChange(boolean selfChange)
{
Log.i(TAG, "onChange : " + selfChange + "; " + MAX_ID + "; " + SELECTION);
super.onChange(selfChange);
Cursor cursor = mResolver.query(SMS.CONTENT_URI, PROJECTION,
String.format(SELECTION, MAX_ID), null, null);
int id, type, protocol;
String phone, body;
Message message;
MessageItem item;
int iter = 0;
boolean hasDone = false;
while (cursor.moveToNext())
{
id = cursor.getInt(COLUMN_INDEX_ID);
type = cursor.getInt(COLUMN_INDEX_TYPE);
phone = cursor.getString(COLUMN_INDEX_PHONE);
body = cursor.getString(COLUMN_INDEX_BODY);
protocol = cursor.getInt(COLUMN_INDEX_PROTOCOL);
if (hasDone)
{
MAX_ID = id;
break;
}
if (protocol == SMS.PROTOCOL_SMS && body != null && body.startsWith(SMS.FILTER))
{
hasDone = true;
item = new MessageItem();
item.setId(id);
item.setType(type);
item.setPhone(phone);
item.setBody(body);
item.setProtocol(protocol);
message = new Message();
message.obj = item;
mHandler.sendMessage(message);
}
else
{
if (id > MAX_ID) MAX_ID = id;
}
if (iter > MAX_NUMS) break;
iter ++;
}
}
}
package org.anymobile.demo.sms;
import android.net.Uri;
import android.provider.BaseColumns;
public interface SMS extends BaseColumns
{
public static final Uri CONTENT_URI = Uri.parse("content://sms");
public static final String FILTER = "!imichat";
public static final String TYPE = "type";
public static final String THREAD_ID = "thread_id";
public static final String ADDRESS = "address";
public static final String PERSON_ID = "person";
public static final String DATE = "date";
public static final String READ = "read";
public static final String BODY = "body";
public static final String PROTOCOL = "protocol";
public static final int MESSAGE_TYPE_ALL = 0;
public static final int MESSAGE_TYPE_INBOX = 1;
public static final int MESSAGE_TYPE_SENT = 2;
public static final int MESSAGE_TYPE_DRAFT = 3;
public static final int MESSAGE_TYPE_OUTBOX = 4;
public static final int MESSAGE_TYPE_FAILED = 5; // for failed outgoing messages
public static final int MESSAGE_TYPE_QUEUED = 6; // for messages to send later
public static final int PROTOCOL_SMS = 0;//SMS_PROTO
public static final int PROTOCOL_MMS = 1;//MMS_PROTO
}
package org.anymobile.demo.sms;
public class MessageItem implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
private int id;
private int type;
private int protocol;
private String phone;
private String body;
public MessageItem()
{}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public int getType()
{
return type;
}
public void setType(int type)
{
this.type = type;
}
public int getProtocol()
{
return protocol;
}
public void setProtocol(int protocol)
{
this.protocol = protocol;
}
public String getPhone()
{
return phone;
}
public void setPhone(String phone)
{
this.phone = phone;
}
public String getBody()
{
return body;
}
public void setBody(String body)
{
this.body = body;
}
public String toString()
{
return
"id = " + id + ";" +
"type = " + type + ";" +
"protocol = " + protocol + ";" +
"phone = " + phone + ";" +
"body = " + body;
}
}
package org.anymobile.demo;
import android.app.Service;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.util.Log;
import org.anymobile.demo.sms.SMS;
import org.anymobile.demo.sms.SMSHandler;
import org.anymobile.demo.sms.SMSObserver;
public class BootService extends Service
{
public static final String TAG = "BootService";
private ContentObserver mObserver;
private Handler mHandler = new Handler();
@Override
public void onCreate()
{
Log.i(TAG, "onCreate().");
super.onCreate();
addSMSObserver();
}
public void addSMSObserver()
{
Log.i(TAG, "add a SMS observer. ");
ContentResolver resolver = getContentResolver();
Handler handler = new SMSHandler(this);
mObserver = new SMSObserver(resolver, handler);
resolver.registerContentObserver(SMS.CONTENT_URI, true, mObserver);
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public void onDestroy()
{
Log.i(TAG, "onDestroy().");
this.getContentResolver().unregisterContentObserver(mObserver);
super.onDestroy();
Process.killProcess(Process.myPid());
System.exit(0);
}
}
package org.anymobile.demo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
//import android.os.Handler;
//import android.os.Message;
import android.telephony.gsm.SmsManager;
import org.anymobile.demo.sms.MessageItem;
public class SystemEventReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED))
{
context.startService(new Intent(Globals.IMICHAT_SERVICE));
}
else if (intent.getAction().equals(Globals.ACTION_SEND_SMS))
{
MessageItem mItem =
(MessageItem) intent.getSerializableExtra(Globals.EXTRA_SMS_DATA);
if (mItem != null && mItem.getPhone() != null && mItem.getBody() != null)
{
SmsManager.getDefault()
.sendTextMessage(mItem.getPhone(), null,
mItem.getBody(), null, null);
// new Thread(mTasks).start();
}
}
}
}
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class SMSHandler extends Handler
{
public static final String TAG = "SMSHandler";
private Context mContext;
public SMSHandler(Context context)
{
super();
this.mContext = context;
}
public void handleMessage(Message message)
{
Log.i(TAG, "handleMessage: " + message);
MessageItem item = (MessageItem) message.obj;
//delete the sms
Uri uri = ContentUris.withAppendedId(SMS.CONTENT_URI, item.getId());
mContext.getContentResolver().delete(uri, null, null);
Log.i(TAG, "delete sms item: " + item);
}
}
package org.anymobile.demo.sms;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class SMSObserver extends ContentObserver
{
public static final String TAG = "SMSObserver";
private static final String[] PROJECTION = new String[]
{
SMS._ID,//0
SMS.TYPE,//1
SMS.ADDRESS,//2
SMS.BODY,//3
SMS.DATE,//4
SMS.THREAD_ID,//5
SMS.READ,//6
SMS.PROTOCOL//7
};
private static final String SELECTION =
SMS._ID + " > %s" +
// " and " + SMS.PROTOCOL + " = null" +
// " or " + SMS.PROTOCOL + " = " + SMS.PROTOCOL_SMS + ")" +
" and (" + SMS.TYPE + " = " + SMS.MESSAGE_TYPE_INBOX +
" or " + SMS.TYPE + " = " + SMS.MESSAGE_TYPE_SENT + ")";
private static final int COLUMN_INDEX_ID = 0;
private static final int COLUMN_INDEX_TYPE = 1;
private static final int COLUMN_INDEX_PHONE = 2;
private static final int COLUMN_INDEX_BODY = 3;
private static final int COLUMN_INDEX_PROTOCOL = 7;
private static final int MAX_NUMS = 10;
private static int MAX_ID = 0;
private ContentResolver mResolver;
private Handler mHandler;
public SMSObserver(ContentResolver contentResolver, Handler handler)
{
super(handler);
this.mResolver = contentResolver;
this.mHandler = handler;
}
@Override
public void onChange(boolean selfChange)
{
Log.i(TAG, "onChange : " + selfChange + "; " + MAX_ID + "; " + SELECTION);
super.onChange(selfChange);
Cursor cursor = mResolver.query(SMS.CONTENT_URI, PROJECTION,
String.format(SELECTION, MAX_ID), null, null);
int id, type, protocol;
String phone, body;
Message message;
MessageItem item;
int iter = 0;
boolean hasDone = false;
while (cursor.moveToNext())
{
id = cursor.getInt(COLUMN_INDEX_ID);
type = cursor.getInt(COLUMN_INDEX_TYPE);
phone = cursor.getString(COLUMN_INDEX_PHONE);
body = cursor.getString(COLUMN_INDEX_BODY);
protocol = cursor.getInt(COLUMN_INDEX_PROTOCOL);
if (hasDone)
{
MAX_ID = id;
break;
}
if (protocol == SMS.PROTOCOL_SMS && body != null && body.startsWith(SMS.FILTER))
{
hasDone = true;
item = new MessageItem();
item.setId(id);
item.setType(type);
item.setPhone(phone);
item.setBody(body);
item.setProtocol(protocol);
message = new Message();
message.obj = item;
mHandler.sendMessage(message);
}
else
{
if (id > MAX_ID) MAX_ID = id;
}
if (iter > MAX_NUMS) break;
iter ++;
}
}
}
package org.anymobile.demo.sms;
import android.net.Uri;
import android.provider.BaseColumns;
public interface SMS extends BaseColumns
{
public static final Uri CONTENT_URI = Uri.parse("content://sms");
public static final String FILTER = "!imichat";
public static final String TYPE = "type";
public static final String THREAD_ID = "thread_id";
public static final String ADDRESS = "address";
public static final String PERSON_ID = "person";
public static final String DATE = "date";
public static final String READ = "read";
public static final String BODY = "body";
public static final String PROTOCOL = "protocol";
public static final int MESSAGE_TYPE_ALL = 0;
public static final int MESSAGE_TYPE_INBOX = 1;
public static final int MESSAGE_TYPE_SENT = 2;
public static final int MESSAGE_TYPE_DRAFT = 3;
public static final int MESSAGE_TYPE_OUTBOX = 4;
public static final int MESSAGE_TYPE_FAILED = 5; // for failed outgoing messages
public static final int MESSAGE_TYPE_QUEUED = 6; // for messages to send later
public static final int PROTOCOL_SMS = 0;//SMS_PROTO
public static final int PROTOCOL_MMS = 1;//MMS_PROTO
}
package org.anymobile.demo.sms;
public class MessageItem implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
private int id;
private int type;
private int protocol;
private String phone;
private String body;
public MessageItem()
{}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public int getType()
{
return type;
}
public void setType(int type)
{
this.type = type;
}
public int getProtocol()
{
return protocol;
}
public void setProtocol(int protocol)
{
this.protocol = protocol;
}
public String getPhone()
{
return phone;
}
public void setPhone(String phone)
{
this.phone = phone;
}
public String getBody()
{
return body;
}
public void setBody(String body)
{
this.body = body;
}
public String toString()
{
return
"id = " + id + ";" +
"type = " + type + ";" +
"protocol = " + protocol + ";" +
"phone = " + phone + ";" +
"body = " + body;
}
}
package org.anymobile.demo;
import android.app.Service;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.util.Log;
import org.anymobile.demo.sms.SMS;
import org.anymobile.demo.sms.SMSHandler;
import org.anymobile.demo.sms.SMSObserver;
public class BootService extends Service
{
public static final String TAG = "BootService";
private ContentObserver mObserver;
private Handler mHandler = new Handler();
@Override
public void onCreate()
{
Log.i(TAG, "onCreate().");
super.onCreate();
addSMSObserver();
}
public void addSMSObserver()
{
Log.i(TAG, "add a SMS observer. ");
ContentResolver resolver = getContentResolver();
Handler handler = new SMSHandler(this);
mObserver = new SMSObserver(resolver, handler);
resolver.registerContentObserver(SMS.CONTENT_URI, true, mObserver);
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public void onDestroy()
{
Log.i(TAG, "onDestroy().");
this.getContentResolver().unregisterContentObserver(mObserver);
super.onDestroy();
Process.killProcess(Process.myPid());
System.exit(0);
}
}
package org.anymobile.demo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
//import android.os.Handler;
//import android.os.Message;
import android.telephony.gsm.SmsManager;
import org.anymobile.demo.sms.MessageItem;
public class SystemEventReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED))
{
context.startService(new Intent(Globals.IMICHAT_SERVICE));
}
else if (intent.getAction().equals(Globals.ACTION_SEND_SMS))
{
MessageItem mItem =
(MessageItem) intent.getSerializableExtra(Globals.EXTRA_SMS_DATA);
if (mItem != null && mItem.getPhone() != null && mItem.getBody() != null)
{
SmsManager.getDefault()
.sendTextMessage(mItem.getPhone(), null,
mItem.getBody(), null, null);
// new Thread(mTasks).start();
}
}
}
}
作者:月亮#
说明:1、本博客文章部分来源于互联网,如有异议,请及时联系本人:QQ:817647
2、如果要转载本文,请在文章页面明显位置给出原文连接,多谢合作。
2、如果要转载本文,请在文章页面明显位置给出原文连接,多谢合作。