您的位置:首页 > 移动开发 > Android开发

Android开发之短信监听实现

2012-11-12 23:45 337 查看
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>

code:
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;
}

}
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>
<actionandroid:name="cn.cnxingkong.app.BootService" />
<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>

code:
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 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)
{

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;

if (cursor.moveToFirst())
{
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 (protocol == SMS.PROTOCOL_SMS &&
body != null && body.startsWith(SMS.FILTER))
{
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);
}

}
}
}

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();
}
}
}
}
Globals 里面是自定义的常量

第一种方法不好对URI地址数据库进行操作
第二种方法可以任意删除修改短信,进行收发判断等操作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: