android学习笔记---38_采用广播接收者拦截外拔电话,实现原理以及实例源码

来源:互联网 发布:网络赌球会抓玩家吗 编辑:程序博客网 时间:2024/05/01 11:29

38_采用广播接收者拦截外拔电话及其特性
这个程序是在原来的基础上进行的:
用到了,上一个工程SMSListener
首先在清单文件中添加,外拨电话的广播接受者
<receiver android:name=".PhoneBroadcastReceiver">
  
 <intent-filter android:priority="1000">
 
   <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
 
  </intent-filter>
 
 </receiver>
然后在清单文件中添加外拨电话的权限
  <!-- 外拨电话的权限 -->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
首先当外拨电话的时候,android系统会发送一个有序广播并且按照优先级来给使用到该广播的android应用,广播接受者(在清单文件中配置)会获取电话信息,然

后传给来电意图。接下来就以在代码中调用了。
在Android中,程序的响应(Responsive)被活动管理器(Activity Manager)和窗口管理器(Window Manager)这两个系统服务所监视。当BroadcastReceiver在

10秒内没有执行完毕,Android会认为该程序无响应。所以在BroadcastReceiver里不能做一些比较耗时的操作,否侧会弹出ANR(Application No Response)的对

话框。如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成。而不是使用子线程的方法来解决,因为BroadcastReceiver的生命

周期很短(在onReceive() 执行后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);
 }
}
每次广播消息到来时都会创建BroadcastReceiver实例并执行onReceive() 方法。
当BroadcastReceive被杀死以后,这个组件所在的进程就变成了一个空进程,当系统中内存不够使用的时候,系统就会杀死这些empty进程紧接着,这些子线程也会被

杀掉.
除了短信到来广播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"/>
下面是外拨电话拦截器的实现的所有代码:
使用的工程还是SMSListener
1. PhoneBroadcastReceiver用这个类来实现
package com.credream.smslistener;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class PhoneBroadcastReceiver extends BroadcastReceiver {
//广播接受者会把得到的外拨电话数据,传给Intent
 @Override
 public void onReceive(Context context, Intent intent) {
  String number = getResultData();
  //修改完号码后要把修改后的数据传递给原来的意图,然后由
  //广播接受者继续传递才可以继续实现外拨电话的传播,给手机自带的
  //拨号器使用,进行拨打电话
  /**
   * 如果要屏蔽电话号码,通过终止广播的方法是没用的,因为底层实现的时候,点击拨号后,会自动的给拨号实现方法添加一个广播接受者
   * 并会新建一个广播接受者,所以有序广播即使是终止了也会继续传播。所以这里采用赋值一个空电话号码来实现电话拦截
   */
  if("5556".equals(number)){
  //有序广播, 
  //abortBroadcast();//终止广播
  setResultData(null);
  }else{
   number = "12593"+ number;
   setResultData(number);
  }
 }

 }
3.下面是清单文件
/SMSListener/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.credream.smslistener"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
         <!-- 配置广播接收者,通过意图过滤器可以完成广播接收的定义,当收到短信的时候,会实例化
      广播接收者,并且把广播 意图对象传入广播接收者中.android.provider.Telephony.SMS_RECEIVED
      广播接收者是通过调用onReceive方法得到广播意图对象.
      -->
  <receiver android:name=".SMSBroadcastReceiver">
   <intent-filter android:priority="1000">
    <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
   </intent-filter>
  </receiver>
 <!--  .号代表的是当前的包下 -->
      <receiver android:name=".PhoneBroadcastReceiver">
  
 <intent-filter android:priority="1000">
 
   <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
 
  </intent-filter>
  </receiver>
     </application>
<uses-permission android:name="android.permission.RECEIVE_SMS"/><!-- 接收短信权限 -->
<!-- 访问internet权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 外拨电话的权限 -->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
</manifest>
-----------------------------------------------------------------------------------------
4.部署应用在android模拟器上,当用户拨打电话的时候就可以看出效果,当拨打5556的时候没有反应