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>

代码:

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>
                
<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, 
nullnull);
       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), 
nullnull);
        
        
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(), 
nullnull);
//            new Thread(mTasks).start();
           }
       }
    }
}
 

 

posted @ 2011-06-07 09:35  ycmoon  阅读(948)  评论(1编辑  收藏  举报
QQ:817647 MSN:kenny@msn.cn EMail:ycmoon@qq.com