android 监听电话去电接通瞬间[非来电]

来源:互联网 发布:星推网络招聘 编辑:程序博客网 时间:2024/05/03 22:26

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

本文包含三个知识点:

1.监听去电接通     2.apk获取root权限 3. 运行时将apk push 到system/app

(1)

    <activity     android:process="com.android.phone"                android:label="@string/app_name"                  android:name=".AutoCallActivity" >                                </activity>  
(2)

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"          package="com.spreadst.drag"          coreApp="true"  android:sharedUserId="android.uid.system"        android:versionCode="1"  

(3)
    LOCAL_PACKAGE_NAME := autocall      #LOCAL_CERTIFICATE := shared  LOCAL_CERTIFICATE := platform 
为什么会有这个需求呢?TelephonyManager 中状态 只有  IDLE 空闲状态, 来电接通状态 ,拨打状态,没有去电接通状态,参考phone中得实现如下:
Phone  phone = PhoneFactory.getDefaultPhone();
这个调用是不能运行在phone以外的进程中的,不信你可以试一下,请记住一个进程的主线程的looper是唯一的

原因如下:

if (sLooper != Looper.myLooper()) {            throw new RuntimeException(                "PhoneFactory.getDefaultPhone must be called from Looper thread");        }
去电接通若干秒之后挂断代码如下,由于使用了hide class,所以必须在android源代码底下编译,当然你也可以通过反射、AIDL、class.jar等方式解决这个问题。

CallManager mCM = CallManager.getInstance();     Phone  phone = PhoneFactory.getDefaultPhone();    mCM.registerPhone(phone);         mCM.registerForPreciseCallStateChanged(mHandler, PHONE_STATE_CHANGED, null); 

    private Handler mHandler=new Handler(){                    public void handleMessage(android.os.Message msg) {                  switch (msg.what) {                  case PHONE_STATE_CHANGED:                      updatePhoneSateChange();                      break;                  default:                      break;                  }              };                        };  

    private void updatePhoneSateChange(){              Call fgCall = mCM.getActiveFgCall();              if (mCM.hasActiveRingingCall()) {                      fgCall = mCM.getFirstActiveRingingCall();                }                    final Call.State state = fgCall.getState();              switch (state) {                  case IDLE:                      break;                        case ACTIVE://去电接通                      Log.d("yzy","ACTVIE");                      final Timer timer = new Timer();                      if(mode == Mode.mode2){                          timer.schedule(new TimerTask() {                              @Override                              public void run() {                                  try {                                      Log.d("yzy", "endcall()");                                            mITelephony.endCall();                                      timer.cancel();                                  } catch (RemoteException e) {                                      e.printStackTrace();                                  }                              }                          }, holdonDuration * 1000, holdonDuration * 1000);                      }                      //mITelephony.endCall();                      break;                  default:                      break;              }                        }  

如果你将这个apk 简单的install 会报告如下错误:不存在该共享用户或签名不匹配,这是因为
android:sharedUserId="android.uid.system"

必须放到system/app目录下才能工作。这就由牵扯出了两个问题,临时获取root权限与运行时拷贝.

其他关键代码:

private ITelephony mITelephony;mITelephony = ITelephony.Stub.asInterface(ServiceManager                .getService(Context.TELEPHONY_SERVICE));        mPhoneStateListener = getPhoneStateListener();        ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)).listen(                mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);private PhoneStateListener getPhoneStateListener() {        return new PhoneStateListener() {            @Override            public void onCallStateChanged(int state, String incomingNumber) {                try {                     Log.d("yzy"," state: "                     + mITelephony.getCallState());                } catch (RemoteException e) {                    e.printStackTrace();                }            }        };    }