`
ljl_xyf
  • 浏览: 636891 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

android 2.1 监听电话状态并自动接听来电

阅读更多

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

 
一、开发环境

      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="";
           

           //启动一个新的Activity
          public static void StartCustomerInfoActivity(Context context,String telNo)
          {

               //第一个参数 启动新的Acitivity的Context;  第二个参数 启动的Acitivity的类
               Intent intent = new Intent(context,CustomerInfo.class);

               //在Service中启动一个Activity并需添加此Flag
               intent.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
            {
                 @Override
                 public 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;
                               //振铃   
在此处我需要在振铃的时候自动接听电话并且打开扬声器和新启动一个Activity
                               case 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()
                  {
                        @Override
                        public void onAccuracyChanged(Sensor sensor, int accuracy) { 
                         }
                        @Override
                        public 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{
           @Overide
           public IBinder onBind(Intent intent) {
                return null;
           }
 
           @Override
           public 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();
           }
 
           @Override
           public 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>
 

 

     在项目中,我们使用反编译来完成自动接听还需要官方提供的两个底层包:

分享到:
评论
1 楼 zhanggaobo 2011-11-28  
您好,我是初学者,我想实现自动接听的功能。您能将这个应用所用到的工具包 import com.android.internal.telephony.ITelephony; 发我用用吗?我的QQ号460177831,非常感谢。

相关推荐

    Android实现监听电话呼叫状态的方法

    在Android平台上,监听电话呼叫状态是一项重要的功能,它允许开发者获取到电话的实时状态,例如来电、通话中或挂断等。以下将详细介绍如何在Android应用中实现这一功能,包括必要的权限控制和电话状态监听。 首先,...

    Android应用源码之 实现自动接听和挂断电话功能).zip

    在Android应用开发中,实现自动接听和挂断电话的功能是一个高级话题,涉及到系统级权限、来电监听和服务等关键概念。这个源码项目提供了一个实际的示例,可以帮助开发者理解和掌握这些技术。 首先,我们要理解...

    android 2.1 launcher源码,可以正常运行

    本篇将深入探讨 Android 2.1 Launcher 的源码,帮助开发者理解其内部工作原理,并可能为自定义 Launcher 开发提供启示。 1. **Launcher 结构** Android 2.1 的 Launcher 主要由以下几个关键组件组成: - `...

    Android中监听电话状态.zip

    在Android系统中,监听电话状态是一项重要的功能,它允许开发者获取到电话的实时信息,比如来电、去电、通话结束等事件。这项功能通常应用于电话录音、来电管理、短信拦截等场景。本教程将深入探讨如何在Android应用...

    Android自动接听电话程序

    在Android平台上,开发一个自动接听电话的程序涉及到多个核心知识点,包括权限管理、来电监听、系统服务、广播接收器以及电话API的使用。下面将详细阐述这些关键点。 首先,**权限管理**是Android应用程序的基础,...

    基于Android的监听微信红包+自动抢红包(抢红包必备助手)).zip

    基于Android的监听微信红包+自动抢红包(抢红包必备助手)(利用AccessibilityService这个辅助服务类,监听通知栏微信消息,如果有微信红包,就模拟界面一些控件的点击事件).zip 基于Android的监听微信红包+自动抢...

    Android手机模拟点击实现自动接听电话和免提功能 模拟点击自动免提TelPhone1.1.5.rar

    8. **代码实现**:创建一个AccessibilityService类,重写其`onAccessibilityEvent()`方法来监听电话状态变化。在电话振铃时,计算接听按钮的坐标,然后通过`sendPointerDownUpEvents()`等方法模拟点击。同时,根据...

    Android程序研发源码Android中监听电话状态.zip

    在Android系统中,监听电话状态是一项重要的功能,它允许开发者获取到电话的实时信息,比如来电、去电、通话结束等事件。这个压缩包“Android程序研发源码Android中监听电话状态.zip”很可能包含了实现这一功能的...

    Android 利用广播监听usb连接状态(变化情况)

    在Android开发中,监听USB连接状态是一个常见需求,尤其是在涉及到需要与USB设备通信的应用场景中。当USB设备插入或者拔出时,应用程序可能需要执行相应的操作,比如启动服务、弹出提示信息等。为了实现这一功能,...

    基于Android2.1系统的蓝牙编程

    本文将深入探讨基于Android 2.1系统进行蓝牙编程的关键知识点,并提供如何使用这些知识来提高开发效率。 1. **Android Bluetooth API** Android 2.1版本提供了Bluetooth API,允许开发者创建能够发现、连接和交换...

    Text 自动接听电话

    - **监听电话状态**:使用TelephonyManager的listen()方法注册电话状态监听器,当接收到PHONE_STATE变化时,可以判断是否为来电状态。 - **启动Activity并传递参数**:当检测到来电时,通过CommonHelper的...

    Android通过使用广播监听网络状态的改变

    在Android系统中,开发者可以利用系统的广播机制来监听网络状态的变化。这是一项非常重要的功能,因为应用程序往往需要根据网络连接的状态来决定是否加载在线数据或者执行网络相关的操作。本篇文章将详细探讨如何在...

    实现自动接听和挂断电话功能

    通过获取到`TelephonyManager`的实例,你可以监听电话状态的变化,如来电、去电、通话结束等。在AndroidManifest.xml文件中,确保添加了必要的权限: ```xml &lt;uses-permission android:name="android.permission....

    android 2.1 多点触摸演示

    本篇将深入探讨Android 2.1中的多点触摸功能,并通过具体的代码示例——"ch25_MultiTouchDemo1"来解析其工作原理。 一、Android 2.1的多点触摸支持 在Android 2.1中,系统提供了`MotionEvent`类来处理触摸事件,...

    Android中监听电话状态-IT计算机-毕业设计.zip

    在Android平台上,监听电话状态是开发者常常需要处理的一项任务,特别是在构建特定功能的应用时,比如通话录音、来电提醒或是管理通话记录。这个“Android中监听电话状态”的项目,作为一个毕业设计的学习示例,旨在...

    android2.1实现通讯录

    此外,BroadcastReceiver可以用来监听系统事件,比如当系统启动时自动加载通讯录数据。 6. **Activity和Fragment**:主Activity负责管理整个通讯录界面,而每个联系人的详细信息可以通过Fragment来展示。Fragment...

    安卓Android源码——实现自动接听和挂断电话功能.zip

    2. **电话状态监听**:使用`PhoneStateListener`监听电话状态变化。创建一个内部类,继承自`PhoneStateListener`,并重写`onCallStateChanged()`方法。在这个方法里,可以根据通话状态(如IDLE、OFFHOOK、RINGING)...

    android2.1小游戏源码

    这个项目很可能是基于早期的Android 2.1版本,尽管现在最新的Android版本已经发展到了Android 12,但学习老版本的代码可以帮助我们了解Android开发的历史和演变。 首先,我们要理解的是Android 2.1(API级别7)的...

    Android2.1系统通讯录源码

    Android 2.1(Eclair)版本的通讯录源码提供了一个深入理解Android系统如何处理联系人数据、显示联系人列表以及与用户交互的基础。下面将详细探讨这个源码中的关键知识点。 1. **SQLite数据库**: Android 2.1的...

    android2.1 实例

    14. **单元测试与自动化测试**:Android 2.1支持JUnit进行单元测试,以及 Espresso 进行UI自动化测试,确保应用的稳定性和质量。 通过对这些知识点的深入理解和实践,开发者可以创建出适应Android 2.1环境的高质量...

Global site tag (gtag.js) - Google Analytics