一、开发环境
      Elispse5.5,JDK1.6,Aadroid 2.1

二、开发中使用到的重点技术点:
      距离感应(SENSOR_SERVICE ),音讯管理(AUDIO_SERVICE ),
      电话状态监听 (TELEPHONY _ SERVICE ),
      java反射启动自动接听,开机自动启动Service ,
      监听来电,在Service 中启动Activity 并传递参数

三、主要开发流程:

1. 在前三步中我们看到有一个公共的辅助类CommonHelper

       package com.org.speaker;             import android.content.Context;import android.content.Intent;           public class CommonHelper {           //保存电话状态public static int phoneState=0;          //保存音讯管理对象public static MyAudioManager mam=null;           //保存去点电话号码public static String outGoingPhoneNumber="";//启动一个新的Activitypublic static void StartCustomerInfoActivity(Context context,String telNo){               //第一个参数 启动新的Acitivity的Context;  第二个参数 启动的Acitivity的类
 Intent intent = new Intent(context,CustomerInfo.class);               //在Service中启动一个Activity并需添加此Flagintent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);               //启动新的Activity时传递的参数
               intent.putExtra("TelNo",telNo);                //启动新的Activity
               context.startActivity(intent);}} 

其实将这个类放到第一步是不合适的,因为这个公共类实在我不断写码过程中完善的,并不是一开始就创建的。

2.首先我们建立我们一个音讯管理的类,用于管理当来电或者去点时扩音器的开关。

   import android.content.Context;  import android.media.AudioManager;import android.widget.Toast;      public class MyAudioManager {private AudioManager audioManager;private int currVolume=0;private Context context;public MyAudioManager(Object object,Context mc){//音频管理对象由外部调用时传入(http://www.my400800.cn )                this.audioManager=(AudioManager)object;                 this.context=mc;                //设置音讯模式为对外输出this.audioManager.setMode(AudioManager.ROUTE_SPEAKER);                  //取得当前的音量
 currVolume=audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);}//打开扬声器public void OpenSpeaker(){                 //设置为true,打开扬声器
 audioManager.setSpeakerphoneOn(true);                 //设置打开扬声器的音量为最大
 audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL ),AudioManager.STREAM_VOICE_CALL);//Toast.makeText(context,"揚聲器已經打開",Toast.LENGTH_SHORT).show();
 }//关闭扬声器public void CloseSpeaker(){                //设置为false,关闭已经打开的扬声器
 audioManager.setSpeakerphoneOn(false);                //恢复为正常音量
 audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,currVolume,AudioManager.STREAM_VOICE_CALL);//Toast.makeText(context,"揚聲器已經關閉",Toast.LENGTH_SHORT).show();
 }}

3.建立一个监听电话状态的类

       package com.org.speaker;       import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import com.android.internal.*;import com.android.internal.telephony.ITelephony;       import android.content.Context;import android.os.RemoteException; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.widget.Toast;    

public class SpeakMananger{private TelephonyManager  teleManager; private Context context;public  SpeakMananger(Object object,Context p_context) {                    //转换从外部传入的Object为TelephonyManager对象this.teleManager=(TelephonyManager)object;this.context=p_context;}//注册电话状态监听器public void RegisterListener(){teleManager.listen(new MyPhoneStateListener(),PhoneStateListener.LISTEN_CALL_STATE);}class MyPhoneStateListener extends PhoneStateListener {@Overridepublic void onCallStateChanged(int state,String incomingNumber){ super.onCallStateChanged(state, incomingNumber);switch(state){//空闲     没有电话打入或者打出 处于挂机空闲状态case TelephonyManager.CALL_STATE_IDLE://Toast.makeText(context,"空閒",Toast.LENGTH_SHORT).show();break;//摘机     有电话打出或者打入  按接听接或者其它操作拨打或接听来电case TelephonyManager.CALL_STATE_OFFHOOK://Toast.makeText(context,"摘機",Toast.LENGTH_SHORT).show();//去電 如果是去電則incomingNumber為null或""                              //【因为此处无法监听去电并且无法去电的电话号码,所以当去电时此处的打入电话号码为null或者""】if(incomingNumber==null || incomingNumber.length()<=0){                                   //打开扬声器
 CommonHelper.mam.OpenSpeaker();                                  //根据公共类中保存的去电电话号码启动一个新的Activity
 CommonHelper.StartCustomerInfoActivity(context,CommonHelper.outGoingPhoneNumber);}//else   //來電    本人是需要在来电振铃的时候就打开扩音器和启动一个新的Acitivity,所以此处被注释掉//CommonHelper.StartCustomerInfoActivity(context,incomingNumber);                               break;//振铃    在此处我需要在振铃的时候自动接听电话并且打开扬声器和新启动一个Activitycase TelephonyManager.CALL_STATE_RINGING://Toast.makeText(context,"振鈴",Toast.LENGTH_SHORT).show();try {/* 以下两种方法都可以使用 都能完成自动接听 但是第一种的异常信息处理的比较完善 *///StartCall();
 answerPhoneAidl();                                      //新启动一个Activity
 CommonHelper.StartCustomerInfoActivity(context,incomingNumber);} catch (Exception e) {Toast.makeText(context,"自动接听发生异常:"+e.getMessage(),Toast.LENGTH_LONG).show();}break;}                       //保存当前电话状态
 CommonHelper.phoneState=state;}}      //此自动接听代码来自官方开源Demo http://code.google.com/p/auto-answer/source/detail?r=17 private void answerPhoneAidl() throws Exception {Class c = Class.forName(teleManager.getClass().getName());Method m = c.getDeclaredMethod("getITelephony",(Class[])null);m.setAccessible(true);ITelephony telephonyService;telephonyService = (ITelephony)m.invoke(teleManager,(Object[])null);// Silence the ringer and answer the call!
 telephonyService.silenceRinger(); telephonyService.answerRingingCall();          }/*** 利用JAVA反射机制调用ITelephony的answerRingingCall()开始通话。*/private void StartCall() {// 初始化iTelephony
 Class<TelephonyManager> c = TelephonyManager.class;Method getITelephonyMethod = null;try {// 获取所有public/private/protected/默认// 方法的函数,如果只需要获取public方法,则可以调用getMethod.
 getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[])null);// 将要执行的方法对象设置是否进行访问检查,也就是说对于public/private/protected/默认// 我们是否能够访问。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false// 则指示反射的对象应该实施 Java 语言访问检查。
 getITelephonyMethod.setAccessible(true);} catch (SecurityException e) {Toast.makeText(context,"安全异常:"+e.getMessage(),Toast.LENGTH_SHORT).show();} catch (NoSuchMethodException e) {Toast.makeText(context,"未找到方法:"+e.getMessage(),Toast.LENGTH_SHORT).show();}                     try {ITelephony iTelephony = (ITelephony) getITelephonyMethod.invoke(teleManager, (Object[])null);                        //停止响铃
 iTelephony.silenceRinger();                         //接听来电
 iTelephony.answerRingingCall();} catch (IllegalArgumentException e) {Toast.makeText(context,"参数异常:"+e.getMessage(),Toast.LENGTH_SHORT).show();} catch (IllegalAccessException e) {Toast.makeText(context,"进入权限异常:"+e.getMessage(),Toast.LENGTH_SHORT).show();} catch (InvocationTargetException e) {Toast.makeText(context,"目标异常:"+e.getMessage(),Toast.LENGTH_SHORT).show();} catch (RemoteException e) {Toast.makeText(context,"Remote异常:"+e.getMessage(),Toast.LENGTH_SHORT).show();}}} 

4.建立一个用于监听距离感应的类

      package com.org.speaker;    import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;import android.hardware.SensorManager;import android.telephony.TelephonyManager;       public class ProximitySensor {private SensorManager sensorManager;private Sensor sensor; private SensorEventListener listener;public ProximitySensor(Object object){                   //获得外部传入的SensorManager对象 this.sensorManager=(SensorManager)object;                   //取得距离感应类型的感应器this.sensor=sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);listener=new SensorEventListener(){@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) { }@Overridepublic void onSensorChanged(SensorEvent event) {if(event.values[0]==1.0){switch(CommonHelper.phoneState){//空闲   离开耳边并且电话空闲的状态,关闭扬声器case TelephonyManager.CALL_STATE_IDLE:CommonHelper.mam.CloseSpeaker();break;//摘机   离开耳边并且电话状态为摘机状态,打开扬声器case TelephonyManager.CALL_STATE_OFFHOOK:CommonHelper.mam.OpenSpeaker();break;}}else{                               //耳边接听电话关闭扬声器
 CommonHelper.mam.CloseSpeaker();}}  };}//注册监听器public void RegisterListener(){this.sensorManager.registerListener(listener, sensor,SensorManager.SENSOR_DELAY_FASTEST);}//移除监听器public void UnRegisterListener(){this.sensorManager.unregisterListener(listener);}      }

5.现在我们建立我们的Service

     package com.org.speaker;         import android.app.Service;import android.content.Intent;import android.os.IBinder;   public class PhoneCallStateService extends Service{@Overidepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate(){super.onCreate();}/*在Service启动的时候,实例化我们刚才建立的所有类*/@Override public void onStart(Intent intent,int startId){super.onStart(intent, startId);  //音频管理服务
 MyAudioManager am=new MyAudioManager(this.getSystemService(AUDIO_SERVICE),this);                   //将音讯管理对象保存到公共类中
 CommonHelper.mam=am;//电话-监听-服务【是否有来电、去电、是否空闲】
 SpeakMananger sm=new SpeakMananger(this.getSystemService(TELEPHONY_SERVICE),this);sm.RegisterListener();  //距离感应
 ProximitySensor ps=new ProximitySensor(this.getSystemService(SENSOR_SERVICE));ps.RegisterListener();}@Overridepublic void onDestroy(){super.onDestroy();}      }

6.建立一个广播接收类,用于在开机启动完毕后启动我们的Service,并且监听去电获得去电电话号码

package com.org.speaker;   

import android.content.BroadcastReceiver;import android.content.Context; import android.content.Intent;       /** 1.首先开机启动后系统会发出一个Standard Broadcast Action, *    名字叫android.intent.action.BOOT_COMPLETED,这个Action只会发出一次。 * 2.构造一个BroadcastReceiver类,重构其抽象方法onReceive(Context context, Intent intent), *         在其中启动你想要启动的Service。 * 3.在AndroidManifest.xml中,首先加入 *    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission> *    来获得BOOT_COMPLETED的使用许可,然后注册前面重构的IntentReceiver类, *    在其<intent-filter>中加入<action android:name="android.intent.action.BOOT_COMPLETED" /> ,*    以使其能捕捉到这个Action。       * 參考文檔: */public class StartReceiver extends BroadcastReceiver {/*要接收的intent源*/static final String ACTION = "android.intent.action.BOOT_COMPLETED";public void onReceive(Context context, Intent intent) {//如果系統已經開機完畢,則啟動电话状态服務 if (intent.getAction().equals(ACTION)) {//启动电话状态服务
                        context.startService(new Intent(context,PhoneCallStateService.class));}/* *  intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)  去电 *  intent.getAction().equals(Intent.ACTION_CALL)) 来电 *///监听去电获得去电电话号码if(intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)){ CommonHelper.outGoingPhoneNumber=intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); }       }}

7.由有上述类需要使用到一些权限,所以我们要在我们的AndroidManifest.xml配置文件中做如下修改:

      <?xml version="1.0" encoding="utf-8"?>            <manifest xmlns:android=" http://schemas.android.com/apk/res/android "package="com.org.speaker"android:versionCode="1"android:versionName="1.0"><application android:icon="@drawable/icon"><activity android:name="CustomerInfo"></activity><receiver  android:name="StartReceiver" ><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED" /><category android:name="android.intent.category.LAUNCHER" />                                 <!-- 添加过滤条件 监听电话状态 --><action android:name="android.intent.action.PHONE_STATE"/>                                           <!-- 监听电话拨出 --><action android:name="android.intent.action.NEW_OUTGOING_CALL" /></intent-filter></receiver><service android:name="PhoneCallStateService" android:enabled="true"></service></application><uses-sdk android:minSdkVersion="4" />                    <!-- 连接互联网的权限 --><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 android:name="android.permission.MODIFY_AUDIO_SETTINGS" />          <!-- 使用SD卡的权限 这个是我个人用到的 大家可以不使用 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />          <!-- 监听去电的权限 --><uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />            <!-- 修改电话状态的权限 --><uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />          <!--  监听来电的权限 --><uses-permission android:name="android.permission.CALL_PHONE" /></manifest> 

android 2.1 监听电话状态并自动接听来电相关推荐

  1. 监听电话状态并自动接听来电

    在完成全部功能之前,我查询了很多资料,用了一个星期的时间终于陆陆续续的将这些功能全部完成了,为了众多和我一样的菜鸟少走一点弯路,我决定将它贴出来和大家一起分享,仔细一看距上次更新博客已经有半年了 . ...

  2. android 监听电话状态 来电 接听 挂断

    如果想要监听手机的来电状态  需要接收手机的电话广播 首先是静态注册 <receiver android:name=".PhoneReceiver"android:expor ...

  3. Android 监听电话去电接通瞬间[非来电]

    首先感叹一下Android强大,它可以把同一个apk里面得不同Actvity分别运行在不同的进程中,比如我想让自己的应用中Activity运行在Phone进程中,那么我需要做三个事情. 本文包含三个知 ...

  4. android 使用广播监听网络状态

     网络状态发生变化的时候,系统会发出 android.net.conn.CONNECTIVITY_CHANGE . 下面是实现的 demo : package mark.zhang;import ...

  5. Android实时监听网络状态

    Android开发实时监听网络状态变化一般有两种方法: 1. 新建一个基类BasicActivity.class,在基类中注册网络监听广播NetworkChangeReceiver.class,所有页 ...

  6. android 充电监听,Android_Android判断和监听底座状态和类型的方法介绍,底座的状态跟充电状态类似, - phpStudy...

    Android判断和监听底座状态和类型的方法介绍 底座的状态跟充电状态类似,很多底座提供充电功能(座充). 底座状态同样使用sticky Intent广播.可以查询设备是否插入底座,哪种底座. 判断当 ...

  7. Android 监听通话状态(挂断 监听 来电)实现自动外呼 按顺序拨出电话 间隔5秒

    最近项目也是添加一个小功能 监听通话状态实现一个自动外呼的功能 我在这里简单的实现了一下转了几天的博客可各大网站找出了一个最简单也好理解的一个方法(至今为止) 其实就用到了我们Android源生自带的 ...

  8. android监听通话状态

    samsung提审结果报告里: application sound is audible during the call in pop up window //在弹出窗口中的呼叫期间,<缺陷&g ...

  9. android 监听网络状态

    今天,讲讲怎么监听手机网络状态的改变. 一.加入网络权限 获取网络信息需要在AndroidManifest.xml文件中加入相应的权限. <uses-permission android:nam ...

最新文章

  1. 机器学习数据预处理之缺失值:前向填充
  2. 七问唐骏:真的性格好就能成功?
  3. 数据中心用多模光纤技术及发展趋势
  4. 就是把努力涂抹在人生的画卷上
  5. SpringBoot中Tomcat配置(学习SpringBoot实战)
  6. 删除wallet里面登机牌_登机牌丢失问题
  7. stlink 升级固件以后失败_ST-Link不能下载程序的几种解决办法
  8. 0.3 preface
  9. [设计模式-创建型]建造者(Builder)
  10. 几种测量app启动时间的方式
  11. insert_text
  12. 数据库事务4种隔离级别和7种传播行为
  13. Daily Scrum 10.23
  14. 亚马逊云科技携海信集团打造全球服务实践案例标杆
  15. 计算机固态硬盘安装,电脑安装了固态硬盘,需要如何重装系统?详细的方法教程在这里!...
  16. 飞书会议视频会议系统,会议场景全hold住
  17. 本地搭建xxl-job服务及连接验证
  18. May 17th Thursday (五月 十七日 木曜日)
  19. 【智能优化】禁忌搜索算法(Matlab代码实现)
  20. 一个软件公司需要多少前端_自己开发一个app需要多少钱,多少时间

热门文章

  1. Eclipse工程标准目录层次结构
  2. 5G NR — 基站的扇区、小区、跟踪区、注册区、服务区
  3. VNF 的性能测试设计要点
  4. DPDK — DPDK APP 的指令行参数
  5. Linux_LVM/Quota
  6. linux中ping命令的用法
  7. Web安全学习笔记——SQL注入
  8. Docker官方Centos镜像下安装Elasticsearch【详细步骤】
  9. 摩拜联合微信全国免押金骑行 这样的CP组合可以多来一点
  10. [心得分享] 我在 GitHub 上学习开源