Android手机下监听短信的两种方式

Android手机上监听短信的两种方式

转载于:http://blog.csdn.net/JavaTiger427/archive/2010/10/11/5932751.aspx

 

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>  
                <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>  

 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 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();  
           }  
       }  
    }  
}