Android 短信广播接收相关问题
本人是Android新手,最近做了一个关于监听手机短信功能的应用,我在网上看资料了解到广播分为有序广播和无序广播,有序广播;无序广播又称普通广播,其中的利弊我也一时没搞清楚,我用的是有序广播实现的,具体思路如下
1、定义一个接收短信的广播
2、当系统接收到短信时,拦截短信,获取短信内容
3、将指定的短信内容转发到服务器
下面是我的实现方法
1、添加一个短消息接收类
1 import java.util.ArrayList; 2 import java.util.HashMap; 3 import java.util.List; 4 import java.util.Map; 5 import org.apache.http.HttpResponse; 6 import org.apache.http.NameValuePair; 7 import org.apache.http.client.entity.UrlEncodedFormEntity; 8 import org.apache.http.client.methods.HttpPost; 9 import org.apache.http.impl.client.DefaultHttpClient; 10 import org.apache.http.message.BasicNameValuePair; 11 import android.content.BroadcastReceiver; 12 import android.content.Context; 13 import android.content.Intent; 14 import android.telephony.SmsMessage; 15 import android.telephony.TelephonyManager; 16 import android.util.Log; 17 import android.widget.Toast; 18 19 public class MessageBroadcastReceiver extends BroadcastReceiver { 20 private static final String ACTION = "android.provider.Telephony.SMS_RECEIVED"; 21 String uri="http://127.0.0.1:8080/Home/SmsHandler"; 22 23 @Override 24 public void onReceive(Context context, Intent intent) { 25 //监听短信广播 26 if (intent != null && intent.getAction() != null 27 && ACTION.compareToIgnoreCase(intent.getAction()) == 0) { 28 Object[] pduArray = (Object[]) intent.getExtras().get("pdus"); 29 SmsMessage[] messages = new SmsMessage[pduArray.length]; 30 //SmsManager sms=SmsManager.getDefault(); 31 String localTelPhoneNumber=getPhoneNumber(context); 32 33 for (int i = 0; i < pduArray.length; i++) { 34 messages[i] = SmsMessage.createFromPdu((byte[]) pduArray[i]); 35 if(messages[i].getDisplayMessageBody().contains("测试数据")) //制定短信转发过滤条件 36 { 37 String filterSms=messages[i].getDisplayMessageBody(); 38 Map<String, String> params=new HashMap<String, String>(); 39 params.put("phoneNumber", localTelPhoneNumber); 40 params.put("smsContent", filterSms); 41 try { 42 sendHttpClientPOSTRequest(uri,params,"UTF-8"); 43 Toast.makeText(context, 44 "短信验证码已转发!", 45 Toast.LENGTH_LONG).show(); 46 // show first message 47 } catch (Exception e) { 48 Toast.makeText(context, 49 e.toString(), 50 Toast.LENGTH_LONG).show(); 51 e.printStackTrace(); 52 } 53 } 54 } 55 Log.d("ConvertToMsg", "SMS Message Received."); 56 } 57 } 58 59 /** 60 * 通过HttpClient发送Post请求 61 * @param path 请求路径 62 * @param params 请求参数 63 * @param ecoding 请求编码 64 * @return 请求是否成功 65 */ 66 private boolean sendHttpClientPOSTRequest(String path, 67 Map<String, String> params, String ecoding) throws Exception { 68 69 List<NameValuePair> pair=new ArrayList<NameValuePair>();//存放请求参数 70 71 if(params!=null && !params.isEmpty()){ 72 for (Map.Entry<String, String> entry : params.entrySet()) { 73 pair.add(new BasicNameValuePair(entry.getKey(),entry.getValue())); 74 } 75 } 76 77 UrlEncodedFormEntity enFormEntity=new UrlEncodedFormEntity(pair,ecoding); 78 HttpPost httpPost=new HttpPost(path); 79 httpPost.setEntity(enFormEntity); 80 DefaultHttpClient client=new DefaultHttpClient(); 81 HttpResponse response=client.execute(httpPost); 82 if(response.getStatusLine().getStatusCode()==200){ 83 return true; 84 } 85 86 return false; 87 } 88 89 /* getPhoneNumber方法返回当前手机的电话号码, 90 * 同时必须在androidmanifest.xml中 91 * 加入 android.permission.READ_PHONE_STATE 这个权限 92 */ 93 private String getPhoneNumber(Context context){ 94 TelephonyManager mTelephonyMgr; 95 mTelephonyMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 96 return mTelephonyMgr.getLine1Number(); 97 } 98 }
1 import com.example.testdemo.MessageBroadcastReceiver; 2 import com.example.testdemo.R; 3 import android.os.Bundle; 4 import android.app.Activity; 5 import android.content.ActivityNotFoundException; 6 import android.content.BroadcastReceiver; 7 import android.content.ComponentName; 8 import android.content.Context; 9 import android.content.Intent; 10 import android.content.IntentFilter; 11 import android.content.pm.ActivityInfo; 12 import android.content.pm.PackageManager; 13 import android.content.pm.ResolveInfo; 14 import android.telephony.TelephonyManager; 15 import android.view.KeyEvent; 16 import android.view.Menu; 17 import android.widget.Toast; 18 public class MainActivity extends Activity { 19 @Override 20 protected void onCreate(Bundle savedInstanceState) { 21 super.onCreate(savedInstanceState); 22 setContentView(R.layout.activity_main); 23 24 String phoneNumber = getPhoneNumber(this); 25 26 if(phoneNumber == ""){ 27 Toast.makeText(this, 28 "程序错误!", 29 Toast.LENGTH_LONG).show(); 30 return; 31 }else{ 32 Toast.makeText(this, 33 phoneNumber, 34 Toast.LENGTH_LONG).show(); 35 } 36 37 //注册短信广播 38 final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED"; 39 IntentFilter filter = new IntentFilter(SMS_RECEIVED); 40 BroadcastReceiver receiver = new MessageBroadcastReceiver(); 41 registerReceiver(receiver, filter); 42 } 43 44 @Override 45 public boolean onCreateOptionsMenu(Menu menu) { 46 // Inflate the menu; this adds items to the action bar if it is present. 47 getMenuInflater().inflate(R.menu.main, menu); 48 return true; 49 } 50 51 @Override 52 protected void onDestroy() { 53 super.onDestroy(); 54 } 55 56 /*重写Home键盘事件,使程序后台运行*/ 57 @Override 58 public boolean onKeyDown(int keyCode, KeyEvent event) { 59 PackageManager pm = getPackageManager(); 60 ResolveInfo homeInfo = 61 pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME), 0); 62 if (keyCode == KeyEvent.KEYCODE_BACK) { 63 ActivityInfo ai = homeInfo.activityInfo; 64 Intent startIntent = new Intent(Intent.ACTION_MAIN); 65 startIntent.addCategory(Intent.CATEGORY_LAUNCHER); 66 startIntent.setComponent(new ComponentName(ai.packageName, ai.name)); 67 startActivitySafely(startIntent); 68 return true; 69 } else 70 return super.onKeyDown(keyCode, event); 71 } 72 73 private void startActivitySafely(Intent intent) { 74 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 75 try { 76 startActivity(intent); 77 } catch (ActivityNotFoundException e) { 78 Toast.makeText(this, "null", 79 Toast.LENGTH_SHORT).show(); 80 } catch (SecurityException e) { 81 Toast.makeText(this, "null", 82 Toast.LENGTH_SHORT).show(); 83 } 84 } 85 86 /** 87 * 1. getPhoneNumber方法返回当前手机的电话号码, 88 * 同时必须在androidmanifest.xml中 89 * 加入 android.permission.READ_PHONE_STATE 这个权限 90 */ 91 private String getPhoneNumber(Context context){ 92 TelephonyManager mTelephonyMgr; 93 mTelephonyMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 94 return mTelephonyMgr.getLine1Number().trim(); 95 } 96 }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.testdemo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="5" android:targetSdkVersion="5" /> <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission> <uses-permission android:name="android.permission.READ_SMS"></uses-permission> <!-- <uses-permission android:protectionLevel="normal" android:name="android.permission.SEND_SMS"></uses-permission> --> <!-- Http权限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 开机启动完成权限 --> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.testdemo.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 注册广播接收器,用于接收开机启动完成的广播 --> <receiver android:name=".BootStartBroadcastReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> </application> </manifest>
好了,配置好之后就可以编译你的项目了,在手机上安装测试可以正常运行,但是有一些问题,就是在某些手机上短信广播接收不到,例如小米和以前的某些牌子的老款智能手机,我在网上查了查,有认说是广播优先级问题,同是短信应用软件,先安装的优先级高,还有一种情况,是软件本身的优先级高,但是都没有提出具体的解决方案,还有一个原因就是系统本身的安全机制,由于某些设置导致短信应用软件不能正常使用,例如小米手机,在短信设置里面好像有一项和短信接收有关的设置,调整之后就可以接收了,但其他手机还没有解决,如果有哪个大牛有好的解决方案,给小弟指点迷津,感激不尽。