android短信和广播机制

来源:互联网 发布:河源网络广播电视台 编辑:程序博客网 时间:2024/05/18 01:35

广播介绍

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

 

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

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

sendStickyBroadcast() 意思只要是如果发送广播之后才执行registerReceiver(BroadcastReceiver,IntentFilter).这个方法依然可以接受到。换句话说,在ReceiverActivity里是通过代码来注册Recevier而不是在Manifest里面注册的。sendStickyBroadcast发出的最后一个Intent会被保留,当下次Recevier处于活跃的时候,又会接受到它。需要加BROADCAST_STICKY权限,否则会抛SecurityException



安卓手机中的短信适合用广播来监测,需要注册广播。此外还可以用来过滤短信,可根据内容和电话号码来过滤短信

把主要代码传上来存盘,方便以后忘记时上来取


首先:订阅感兴趣的广播 Intent ,订阅方法有两种:

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

Java代码 

IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");  

registerClass receiver = new registerClass();  

registerReceiver(receiver, filter);  

 

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

Html代码 

<receiver android:name=".IncomingSMSReceiver">  

<intent-filter>  

<action android:name="android.provider.Telephony.SMS_RECEIVED"/>  

</intent-filter>  

</receiver> 

我用第二种


package com.lan.www;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
// 这是那个广播类,需继承系统的
public class SmsReciver extends BroadcastReceiver {
    private final String MagicString = "lan";
   

//onReceive的生命周期为10秒,所以里面的操作不能超过10秒

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        if((intent.getAction()!=null)&&(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED"))) //这个action是系统短信专属
        {
            StringBuffer sb = new StringBuffer();
            Bundle bundle = intent.getExtras();  //如果有短信过来,Android系统其实就是用一个Bundle来存短信的
            if(bundle!=null)
            {
            //短信头是一个pdus
                Object[] pdus = (Object[]) bundle.get("pdus");  //一条短信(中文是70个字符左右,英文是140左右,都包括了标点符号),可能不只一条,但每一条都有pdus
                
                SmsMessage[] msgs = new SmsMessage[pdus.length];  //有多少条短信就有多少条短信
                for (int i = 0; i < msgs.length; i++) {
                //短信内容
                    msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                }
                //得到电话号码,一般取第一条短信的电话号码就可以了,要想严谨就应该每条短信都应该进行取电话号码,因为这时可能其他人也在发短信过来,
                String telnumber = msgs[0].getOriginatingAddress();
                for (SmsMessage smsMessage : msgs) {
                    sb.append(smsMessage.getMessageBody());
                }

               if(smgs.length() >0){

                  Date date new Date(smgs[0].getTimestampMillis());
             SimpleDateFormat format new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
               String time format.format(date) //得到发送时间

                 }


                Log.i("lan", "SMS telnumber="+telnumber+" info="+sb.toString());
                //过滤短信
                if(sb.indexOf(MagicString)!=-1)
                {
                //有过滤的短信内容在里面就清除
                    sb = null;
                    //阻止广播播出
                    this.abortBroadcast();
                }
                if(sb!=null&&sb.length()!=0)
                {
                    Intent it = new Intent(context, SMS1Activity.class).putExtra("info", sb.toString()).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(it);//这里传给另一个界面了
                }
            }
            //这个方法有时不好用,不好用就加在这里试试
//            this.abortBroadcast();
        }
    }

}
在AndroidManifest.xml文件中进行配置:

<receiver android:name="SmsReciver">
            <intent-filter android:priority="1000"> //权限越高,才能确保执行,目前最高是int 类型,
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>

            </intent-filter>
        </receiver>


<uses-permission android:name="android.permission.RECEIVE_SMS"/><!-- 接收短信权限 -->
<uses-permission android:name="android.permission.SEND_SMS"/><!-- 发送短信权限 -->


另发送短信

SmsManager sms = SmsManager.getDefault();//得到系统的短信管理
        ArrayList<String> texts = sms.divideMessage(text.toString()); //分成若干条短信
        PendingIntent pi = PendingIntent.getBroadcast( //不一定发生时,用此类
                SendNotify.this,
                0,
                new Intent(),
                0);
        for (String string : texts) {
            for (int i = 0; i < phones.length; i++) {
                sms.sendTextMessage(phones[i], null, string, pi, null);  //发送短信
            }
        }


下面这段自http://www.2cto.com/kf/201206/137542.html

如果想在播出的电话加上特殊提示或者默认加上区号,12593优惠号等,那么就需要监听外拨的电话,并进行处理:


向外拨打电话时系统会发出一个有序广播,虽然该广播最终会被拔号器里的广播接收者所接收并实现电话拔打,但我们可以在广播传递给拔号广播接收者之前先得到该广播,然后清除传递给拔号广播接收者的电话号码,在拔号广播接收者接收到该广播时,由于电话号码为null,因此取消电话拔打。

public class OutgoingCallReceiver extends BroadcastReceiver {
     public void onReceive(Context context, Intent intent) {
           setResultData(null); //清除电话,广播被传给系统的接收者后,因为电话为null,取消电话拔打
     
          // 同样如果你想修改外拔的电话号码,可以这样做
          // String phone = getResultData();//得到外拔电话
          // setResultData(“12593”+ phone);//在电话前面加上12593
     }
}


接收外拔电话广播Intent,在AndroidManifest.xml文件中的<application>节点里订阅此Intent:
<receiver android:name=".OutgoingCallReceiver">
    <intent-filter android:priority="1">
         <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
    </intent-filter>
</receiver>
并且要进行权限声明:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>