MyException - 我的异常网
当前位置:我的异常网» Android » Android之短信中转

Android之短信中转

www.MyException.Cn  网友分享于:2015-08-26  浏览:26次
Android之短信转发

一:广播接收者--BroadcastReceiver

  1:广播接收者(BroadcastReceiver)用于异步接收广播Intent,广播Intent的发送是通过调用Context.sendBroadcast()、Context.sendOrderedBroadcast()或者Context.sendStickyBroadcast()来实现的。通常一个广播Intent可以被订阅了此Intent的多个广播接收者所接收,广播接收者和JMS中的Topic消息接收者很相似。要实现一个广播接收者方法如下:
第一步:继承BroadcastReceiver,并重写onReceive()方法。

public class IncomingSMSReceiver extends BroadcastReceiver {
	@Override public void onReceive(Context context, Intent intent) {
	}
}

 第二种:在AndroidManifest.xml文件中的<application>节点里进行订阅:

<receiver android:name=".IncomingSMSReceiver">
    <intent-filter>
         <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
    </intent-filter>
</receiver>

 

第二步:订阅感兴趣的广播Intent,订阅方法有两种:

      第一种:使用代码进行订阅
     

public class IncomingSMSReceiver extends BroadcastReceiver {
	@Override public void onReceive(Context context, Intent intent) {
	}
}

 第二种:在AndroidManifest.xml文件中的<application>节点里进行订阅:

<receiver android:name=".IncomingSMSReceiver">
    <intent-filter>
         <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

 并且要进行权限声明:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

2:广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Orderedcasts)”普通广播是完全异步的,可以在同一时刻逻辑上被所有接受者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播intent的传播;然而有序广播是按照接收者声明的优先级别(声明在intent-filter元素的android:priority)属性中,数越大优先级别越高取值范围:-1000到1000.也可以调用IntentFilter对象的setPriority()进行设置,被接收者一次接收广播,如:A的级别高于B,B 的界别高于C,那么,光比先传递给A,在传递给B,最后传递给C。A得到广播后,可以往广播里面放入数据,当广播传递给B,B可以从光比重化工得到A存入的数据。

     Contex.sendbroadcast():发送的是普通广播,所有的订阅者都有机会获得并进行处理。

     Context.sendOrderBroadcast():发送的是有序光比,系统会根据接收者声明的优先级别按顺序逐个执行接收者,前面的接收者有权终止广播(BroadcastReceiver.abortBroadcast()),如果广播被前面的接收者终止,后面的接收者就在也无法获取到广播,对于有序广播,前面的接收者可以将处理结果存进广播intent,然后传递给下一个接收者。

3:在Android中,程序的响应(Responsive)被活动管理器(Activity Manager)和窗口管理器(Window Manager)这两个系统服务所监听,所以broadcastReceiver里不能做一些比较耗时的操作,否则会弹出ANR(Application No Response)的对话框,如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成,而不是使用子线程方法来解决,应为broadcastReciver的生命周期很短(在onReceive()执行后BroadcastReceiver的实例就会销毁),子线程可能还没有结束BroadcastReceiver就先结束了,如果broadcastReceiver结束了,它的宿主进程还在运行,那么子线程还会继续执行,但宿主进程此时横容易在系统需要内存是被优先杀死,因为它属于空进程(没有任何活动组件的进程)。

public class IncomingSMSReceiver extends BroadcastReceiver {
	@Override public void onReceive(Context context, Intent intent) {
            //发送Intent启动服务,由服务来完成比较耗时的操作
            Intent service = new Intent(context, XxxService.class);
            context.startService(service);
            //发送Intent启动Activity,由Activity来完成比较耗时的操作
            Intent newIntent = new Intent(context, XxxActivity.class);
            context.startActivity(newIntent);
	}
}

每次广播消息到来时都会创建BroadcastReceiver实例并执行onReceive()方法

4:除了短信到来广播Intent,Android还有很多广播Intent,如:开机启动、电池电量变化、时间已经改变等广播Intent。
    接收电池电量变化广播Intent ,在AndroidManifest.xml文件中的<application>节点里订阅此Intent:

<receiver android:name=".IncomingSMSReceiver">
    <intent-filter>
         <action android:name="android.intent.action.BATTERY_CHANGED"/>
    </intent-filter>
</receiver>

 接收开机启动广播Intent,在AndroidManifest.xml文件中的<application>节点里订阅此Intent:

<receiver android:name=".IncomingSMSReceiver">
    <intent-filter>
         <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

 并且要进行权限声明:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

 
下面以一个例子讲解 BroadcastReceiver

一:手机端

1:SocketHttpRequester

package cn.itcast.utils;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

public class SocketHttpRequester {
	/**
	 * 发送xml数据
	 * @param path 请求地址
	 * @param xml xml数据
	 * @param encoding 编码
	 * @return
	 * @throws Exception
	 */
	public static byte[] postXml(String path, String xml, String encoding) throws Exception{
		byte[] data = xml.getBytes(encoding);
		URL url = new URL(path);
		HttpURLConnection conn = (HttpURLConnection)url.openConnection();
		conn.setRequestMethod("POST");
		conn.setDoOutput(true);
		conn.setRequestProperty("Content-Type", "text/xml; charset="+ encoding);
		conn.setRequestProperty("Content-Length", String.valueOf(data.length));
		conn.setConnectTimeout(5 * 1000);
		OutputStream outStream = conn.getOutputStream();
		outStream.write(data);
		outStream.flush();
		outStream.close();
		if(conn.getResponseCode()==200){
			return readStream(conn.getInputStream());
		}
		return null;
	}
	
	/**
	 * 直接通过HTTP协议提交数据到服务器,实现如下面表单提交功能:
	 *   <FORM METHOD=POST ACTION="http://192.168.0.200:8080/ssi/fileload/test.do" enctype="multipart/form-data">
			<INPUT TYPE="text" NAME="name">
			<INPUT TYPE="text" NAME="id">
			<input type="file" name="imagefile"/>
		    <input type="file" name="zip"/>
		 </FORM>
	 * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080这样的路径测试)
	 * @param params 请求参数 key为参数名,value为参数值
	 * @param file 上传文件
	 */
	public static boolean post(String path, Map<String, String> params, FormFile[] files) throws Exception{     
        final String BOUNDARY = "---------------------------7da2137580612"; //数据分隔线
        final String endline = "--" + BOUNDARY + "--\r\n";//数据结束标志
        
        int fileDataLength = 0;
        for(FormFile uploadFile : files){//得到文件类型数据的总长度
        	StringBuilder fileExplain = new StringBuilder();
 	        fileExplain.append("--");
 	        fileExplain.append(BOUNDARY);
 	        fileExplain.append("\r\n");
 	        fileExplain.append("Content-Disposition: form-data;name=\""+ uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r\n");
 	        fileExplain.append("Content-Type: "+ uploadFile.getContentType()+"\r\n\r\n");
 	        fileExplain.append("\r\n");
 	        fileDataLength += fileExplain.length();
        	if(uploadFile.getInStream()!=null){
        		fileDataLength += uploadFile.getFile().length();
	 	    }else{
	 	    	fileDataLength += uploadFile.getData().length;
	 	    }
        }
        StringBuilder textEntity = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {//构造文本类型参数的实体数据
            textEntity.append("--");
            textEntity.append(BOUNDARY);
            textEntity.append("\r\n");
            textEntity.append("Content-Disposition: form-data; name=\""+ entry.getKey() + "\"\r\n\r\n");
            textEntity.append(entry.getValue());
            textEntity.append("\r\n");
        }
        //计算传输给服务器的实体数据总长度
        int dataLength = textEntity.toString().getBytes().length + fileDataLength +  endline.getBytes().length;
        
        URL url = new URL(path);
        int port = url.getPort()==-1 ? 80 : url.getPort();
        Socket socket = new Socket(InetAddress.getByName(url.getHost()), port);	       
        OutputStream outStream = socket.getOutputStream();
        //下面完成HTTP请求头的发送
        String requestmethod = "POST "+ url.getPath()+" HTTP/1.1\r\n";
        outStream.write(requestmethod.getBytes());
        String accept = "Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\n";
        outStream.write(accept.getBytes());
        String language = "Accept-Language: zh-CN\r\n";
        outStream.write(language.getBytes());
        String contenttype = "Content-Type: multipart/form-data; boundary="+ BOUNDARY+ "\r\n";
        outStream.write(contenttype.getBytes());
        String contentlength = "Content-Length: "+ dataLength + "\r\n";
        outStream.write(contentlength.getBytes());
        String alive = "Connection: Keep-Alive\r\n";
        outStream.write(alive.getBytes());
        String host = "Host: "+ url.getHost() +":"+ port +"\r\n";
        outStream.write(host.getBytes());
        //写完HTTP请求头后根据HTTP协议再写一个回车换行
        outStream.write("\r\n".getBytes());
        //把所有文本类型的实体数据发送出来
        outStream.write(textEntity.toString().getBytes());	       
        //把所有文件类型的实体数据发送出来
        for(FormFile uploadFile : files){
        	StringBuilder fileEntity = new StringBuilder();
 	        fileEntity.append("--");
 	        fileEntity.append(BOUNDARY);
 	        fileEntity.append("\r\n");
 	        fileEntity.append("Content-Disposition: form-data;name=\""+ uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r\n");
 	        fileEntity.append("Content-Type: "+ uploadFile.getContentType()+"\r\n\r\n");
 	        outStream.write(fileEntity.toString().getBytes());
 	        if(uploadFile.getInStream()!=null){
 	        	byte[] buffer = new byte[1024];
 	        	int len = 0;
 	        	while((len = uploadFile.getInStream().read(buffer, 0, 1024))!=-1){
 	        		outStream.write(buffer, 0, len);
 	        	}
 	        	uploadFile.getInStream().close();
 	        }else{
 	        	outStream.write(uploadFile.getData(), 0, uploadFile.getData().length);
 	        }
 	        outStream.write("\r\n".getBytes());
        }
        //下面发送数据结束标志,表示数据已经结束
        outStream.write(endline.getBytes());
        
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        if(reader.readLine().indexOf("200")==-1){//读取web服务器返回的数据,判断请求码是否为200,如果不是200,代表请求失败
        	return false;
        }
        outStream.flush();
        outStream.close();
        reader.close();
        socket.close();
        return true;
	}
	
	/**
	 * 提交数据到服务器
	 * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080这样的路径测试)
	 * @param params 请求参数 key为参数名,value为参数值
	 * @param file 上传文件
	 */
	public static boolean post(String path, Map<String, String> params, FormFile file) throws Exception{
	   return post(path, params, new FormFile[]{file});
	}
	/**
	 * 提交数据到服务器
	 * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080这样的路径测试)
	 * @param params 请求参数 key为参数名,value为参数值
	 * @param encode 编码
	 */
	public static byte[] postFromHttpClient(String path, Map<String, String> params, String encode) throws Exception{
		List<NameValuePair> formparams = new ArrayList<NameValuePair>();//用于存放请求参数
		for(Map.Entry<String, String> entry : params.entrySet()){
			formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
		}
		UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, encode);
		HttpPost httppost = new HttpPost(path);
		httppost.setEntity(entity);
		HttpClient httpclient = new DefaultHttpClient();//看作是浏览器
		HttpResponse response = httpclient.execute(httppost);//发送post请求		
		return readStream(response.getEntity().getContent());
	}

	/**
	 * 发送请求
	 * @param path 请求路径
	 * @param params 请求参数 key为参数名称 value为参数值
	 * @param encode 请求参数的编码
	 */
	public static byte[] post(String path, Map<String, String> params, String encode) throws Exception{
		//String params = "method=save&name="+ URLEncoder.encode("老毕", "UTF-8")+ "&age=28&";//需要发送的参数
		StringBuilder parambuilder = new StringBuilder("");
		if(params!=null && !params.isEmpty()){
			for(Map.Entry<String, String> entry : params.entrySet()){
				parambuilder.append(entry.getKey()).append("=")
					.append(URLEncoder.encode(entry.getValue(), encode)).append("&");
			}
			parambuilder.deleteCharAt(parambuilder.length()-1);
		}
		byte[] data = parambuilder.toString().getBytes();
		URL url = new URL(path);
		HttpURLConnection conn = (HttpURLConnection)url.openConnection();
		conn.setDoOutput(true);//允许对外发送请求参数
		conn.setUseCaches(false);//不进行缓存
		conn.setConnectTimeout(5 * 1000);
		conn.setRequestMethod("POST");
		//下面设置http请求头
		conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
		conn.setRequestProperty("Accept-Language", "zh-CN");
		conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
		conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
		conn.setRequestProperty("Content-Length", String.valueOf(data.length));
		conn.setRequestProperty("Connection", "Keep-Alive");
		
		//发送参数
		DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());
		outStream.write(data);//把参数发送出去
		outStream.flush();
		outStream.close();
		if(conn.getResponseCode()==200){
			return readStream(conn.getInputStream());
		}
		return null;
	}
	
	/**
	 * 读取流
	 * @param inStream
	 * @return 字节数组
	 * @throws Exception
	 */
	public static byte[] readStream(InputStream inStream) throws Exception{
		ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = -1;
		while( (len=inStream.read(buffer)) != -1){
			outSteam.write(buffer, 0, len);
		}
		outSteam.close();
		inStream.close();
		return outSteam.toByteArray();
	}
}

 

2:SMSBroadcastReceiver

package cn.itcast.sms;

import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

import cn.itcast.utils.SocketHttpRequester;

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

public class SMSBroadcastReceiver extends BroadcastReceiver {
    //在接受者这边获取短信相关信息,将相关信息发到服务器上进行
	@Override
	public void onReceive(Context context, Intent intent) {
		Object[] pduses = (Object[])intent.getExtras().get("pdus");
		for(Object pdus : pduses){
			byte[] pdusmessage = (byte[]) pdus;//没一条短信
			SmsMessage sms = SmsMessage.createFromPdu(pdusmessage);
			String mobile = sms.getOriginatingAddress();//得到电话号码
			String content = sms.getMessageBody();//得到短信的内容
			Date date = new Date(sms.getTimestampMillis());//得到发送短信具体时间
			//2009-10-12 12:21:23
			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//为实践设置格式
			String sendtime = format.format(date);
			Map<String, String> params = new HashMap<String, String>();
			params.put("method", "getSMS");//将与短信相关的内容全部都放到集合里
			params.put("mobile", mobile);
			params.put("content", content);
			params.put("sendtime", sendtime);
			try {//利用socket向服务器发到的内容
				SocketHttpRequester.post("http://192.168.1.100:8080/videoweb/video/manage.do", params, "UTF-8");
			} catch (Exception e) {
				Log.e("SMSBroadcastReceiver", e.toString());
			}
		}
	}

}

 

二:服务器端

1:VideoManageAction

package cn.itcast.action;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;

import cn.itcast.formbean.VideoForm;
import cn.itcast.utils.StreamTool;

public class VideoManageAction extends DispatchAction {
	
	public ActionForward getSMS(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		VideoForm formbean = (VideoForm)form;
		System.out.println("发送者:"+ formbean.getMobile());
		System.out.println("发送时间:"+ formbean.getSendtime());
		System.out.println("短信内容:"+ formbean.getContent());
		return mapping.findForward("result");
	}
	
}

 三:AndroidManifest.xml

  <?xml version="1.0" encoding="utf-8" ?> 
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.itcast.sms" android:versionCode="1" android:versionName="1.0">
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <receiver android:name=".SMSBroadcastReceiver">
- <intent-filter>
  <action android:name="android.provider.Telephony.SMS_RECEIVED" /> 
  </intent-filter>
  </receiver>
  </application>
  <uses-sdk android:minSdkVersion="8" /> 
  <uses-permission android:name="android.permission.RECEIVE_SMS" /> 
- <!--  接收短信权限 
  --> 
- <!--  访问网络的权限 
  --> 
  <uses-permission android:name="android.permission.INTERNET" /> 
  </manifest>

 

文章评论

科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
我是如何打败拖延症的
我是如何打败拖延症的
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
Java程序员必看电影
Java程序员必看电影
程序员应该关注的一些事儿
程序员应该关注的一些事儿
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
程序员必看的十大电影
程序员必看的十大电影
我的丈夫是个程序员
我的丈夫是个程序员
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
中美印日四国程序员比较
中美印日四国程序员比较
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
 程序员的样子
程序员的样子
代码女神横空出世
代码女神横空出世
漫画:程序员的工作
漫画:程序员的工作
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
旅行,写作,编程
旅行,写作,编程
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
10个调试和排错的小建议
10个调试和排错的小建议
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
程序员的鄙视链
程序员的鄙视链
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
编程语言是女人
编程语言是女人
老程序员的下场
老程序员的下场
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
一个程序员的时间管理
一个程序员的时间管理
程序员和编码员之间的区别
程序员和编码员之间的区别
总结2014中国互联网十大段子
总结2014中国互联网十大段子
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
程序员都该阅读的书
程序员都该阅读的书
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
为什么程序员都是夜猫子
为什么程序员都是夜猫子
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
如何成为一名黑客
如何成为一名黑客
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有