【转】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>

 

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

           }

       }

    }

}

 

 OVER!

 

原文

作者:徐建祥(netpirate@gmail.com)
日期:2010/08/10
网址:http://www.anymobile.org

 

posted on 2011-06-05 22:43  yingql  阅读(1524)  评论(0编辑  收藏  举报

导航