Android 监听短信(同时监听广播和数据库)


暗扣方式之一:短信订购,即监听--------拦截------------处理短信。

暗扣方式之二:模拟人为操作(又叫模拟流量),通过后台程序代码模拟人的点击行为,暗自给用户订购业务,由运营商收取你的费用,当然这其中也需要涉及监听/拦截/处理短信。使用这种方式的原理无非是Http处理网页,还涉及接入点切换问题,这里就不详细讲解。

暗扣,强烈谴责这种侵害用户利益的行为。。。

回归正题:有的时候,我们的手机程序需要监听手机短信,当满足条件A时,不处理;当满足条件B时,将其设置为已读;当满足条件C时,将短信删除。

注:Android 4.3以及以后可能由用户来控制程序的权限,如果用户关闭这个程序的权限,意味着你无法监听短信/操作短信内容

目前也有如小米系统在安装时,让用户来控制权限;360来监听优先拦截短信等等(关于谁先安装谁有优先权,动态注册比静态注册优先级别高等问题,在这些情况这里就不讲了)。。。

一,拦截广播

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;

/**
 * 短信广播
 * @author Admin
 *
 */
public class SmsReceiver extends BroadcastReceiver {

    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))
  {
    Bundle bundle = intent.getExtras();
    if (bundle != null)
    {
    Object[] objArray = (Object[]) bundle.get("pdus");
    SmsMessage[] messages = new SmsMessage[objArray.length];
    for (int i = 0; i < objArray.length; i++)
    {
      messages[i] = SmsMessage.createFromPdu((byte[]) objArray[i]);
    }
   
    String phoneNum="";//电话号码
    StringBuilder sb = new StringBuilder();//短信内容   
   
    for (SmsMessage currentMessage : messages) 
    {
      phoneNum=currentMessage.getDisplayOriginatingAddress();
      sb.append(currentMessage.getDisplayMessageBody());     
    }   
   
    //根据你策略的手机端口号/拦截关键字判断进行是否中断广播(this.abortBroadcast();),
    //TODO 
    } 
  }
 }
}

二、开启一个服务开监听数据库

import android.app.Service;
import android.content.ContentResolver;
import android.content.Intent;
import android.net.Uri;
import android.os.IBinder;
import android.os.Process;

/**
 * @author Administrator
 *
 */
public class SmsService extends Service {

 private SmsObserver mObserver;
 
 @Override
 public IBinder onBind(Intent intent) {
  return null;
 }

 @Override
 public void onCreate() {
  //在这里启动
  ContentResolver resolver = getContentResolver(); 
  mObserver = new SmsObserver(resolver, new SmsHandler(this));
  resolver.registerContentObserver(Uri.parse("content://sms"), true, mObserver);
 }

 @Override
 public void onDestroy() {
  super.onDestroy();
  this.getContentResolver().unregisterContentObserver(mObserver);
  Process.killProcess(Process.myPid());
 }
}

三、数据库观察者:

import android.content.ContentResolver;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Message;


/**
 * @author Administrator
 *
 */
public class SmsObserver extends ContentObserver{

 private ContentResolver mResolver;
 public SmsHandler smsHandler;
 
 public SmsObserver(ContentResolver mResolver,SmsHandler handler) {
  super(handler);
  this.mResolver=mResolver;
  this.smsHandler=handler;
 }
 
 @Override
 public void onChange(boolean selfChange) {
  Cursor mCursor=mResolver.query(Uri.parse("content://sms/inbox"), new String[] { "_id", "address", "read", "body", "thread_id" }, "read=?", new String[] { "0" }, "date desc");
 
  if(mCursor==null)
  {
   return;
  }
  else
  {
   while (mCursor.moveToNext())
   {
    SmsInfo _smsInfo=new SmsInfo();
   
    int _inIndex=mCursor.getColumnIndex("_id");
    if(_inIndex!=-1)
    {
     _smsInfo._id=mCursor.getString(_inIndex);
    }
   
    int thread_idIndex=mCursor.getColumnIndex("thread_id");
    if(thread_idIndex!=-1)
    {
     _smsInfo.thread_id=mCursor.getString(thread_idIndex);
    }
   
      int addressIndex=mCursor.getColumnIndex("address");
    if(addressIndex!=-1)
    {
     _smsInfo.smsAddress=mCursor.getString(addressIndex);
    }
   
      int bodyIndex=mCursor.getColumnIndex("body");
    if(bodyIndex!=-1)
    {
     _smsInfo.smsBody=mCursor.getString(bodyIndex);
    } 
   
    int readIndex=mCursor.getColumnIndex("read");
    if(readIndex!=-1)
    {
     _smsInfo.read=mCursor.getString(readIndex);
    }     

    //根据你的拦截策略,判断是否不对短信进行操作;将短信设置为已读;将短信删除
    //TODO
    Message msg=smsHandler.obtainMessage();
    _smsInfo.action=2;//0不对短信进行操作;1将短信设置为已读;2将短信删除
    msg.obj=_smsInfo;
    smsHandler.sendMessage(msg);
   }
  }
 
  if(mCursor!=null)
  {
   mCursor.close();
   mCursor=null;
  }
 }
}

四、短信处理类

import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;

/**
 * @author 短信的处理
 *
 */
public  class SmsHandler extends Handler
{
 private Context  mcontext;
 
 public SmsHandler(Context  context)
 {
  this.mcontext=context;
 }
 
 @Override
 public void handleMessage(Message msg)
 {
  SmsInfo smsInfo=(SmsInfo)msg.obj;
 
  if(smsInfo.action==1)
  {
   ContentValues values = new ContentValues();
      values.put("read", "1");
      mcontext.getContentResolver().update(Uri.parse("content://sms/inbox"), values, "thread_id=?", new String[]{smsInfo.thread_id});
  }
  else if(smsInfo.action==2)
  {
   Uri mUri=Uri.parse("content://sms/");
   mcontext.getContentResolver().delete(mUri, "_id=?", new String[]{smsInfo._id});
  }
 } 
}

五、SmsInfo 数据结构

/**
 * 主要用于短信拦截
 * @author Administrator
 *
 */
public class SmsInfo {
 public String _id="";
 public String thread_id = "";
 public String smsAddress = "";
 public String smsBody = "";
 public String read="";
 public int action=0;//1代表设置为已读,2表示删除短信
}

短信拦截大概就是如此了。

相关内容

    暂无相关文章