如何以编程接听/结束的Andr​​oid 4.1打电话? [英] How to programatically answer/end a call in Android 4.1?

查看:108
本文介绍了如何以编程接听/结束的Andr​​oid 4.1打电话?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写一个Android应用程序中,我需要接听来电,做了一些工作,然后挂断电话。 毕竟谷歌搜索我能找到的两种不同的方法才达到这里面既与近期的Andr​​oid版本专门4.1果冻豆之后就无法正常工作。

我。)访问com.android.internal.telephony.ITelephony利用广播接收器android.intent.action.PHONE_STATEJava反射。下面的示例code可以在数百个相关岗位中找到:

 公共类PhoneCallReceiver扩展的BroadcastReceiver {
 上下文的背景下= NULL;
 私有静态最后字符串变量=电话呼叫;
 私人ITelephony telephonyService;

@覆盖
 公共无效的onReceive(上下文的背景下,意图意图){
  如果(!intent.getAction()。等于(android.intent.action.PHONE_STATE))
    返回;

  Log.v(TAG,Receving ......);
  TelephonyManager电话=(TelephonyManager)
  context.getSystemService(Context.TELEPHONY_SERVICE);
  尝试 {
      Log.v(TAG,获取getTeleService ......);
      C类=的Class.forName(telephony.getClass()的getName());
      方法米= c.getDeclaredMethod(getITelephony);
      m.setAccessible(真正的);
      telephonyService =(ITelephony)m.invoke(电话);
      telephonyService.silenceRinger();
      Log.v(TAG,现在应答呼叫......);
      telephonyService.answerRingingCall();
      Log.v(TAG,呼叫回答......);
      //telephonyService.endCall();
  }赶上(例外五){
   e.printStackTrace();
   Log.e(TAG,
           致命错误:无法连接到电话子系统);
   Log.e(TAG,异常物体+ E);
  }
 }
}
 

本code的问题是,

 <使用-权限的Andr​​oid:名称=android.permission.MODIFY_PHONE_STATE/>
 

需要使用此方法,而这种权限已被定义为从机器人v 2.3系统应用服务只是。总之,普通用户的应用程序不能定义在manifest文件这个权限了。

二。)另一种方式是模拟推的耳机挂钩,这使得安卓接听电话。这是通过广播Intent.ACTION_MEDIA_BUTTON,如下面的code完成的。

 公共类PhoneCallReceiver扩展的BroadcastReceiver {
 上下文的背景下= NULL;
 私有静态最后字符串变量=电话呼叫;

 @覆盖
 公共无效的onReceive(上下文的背景下,意图意图){
     如果(!intent.getAction()。等于(android.intent.action.PHONE_STATE))
         返回;

     字符串状态= intent.getStringExtra(TelephonyManager.EXTRA_STATE);
     如果(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
         串号= intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);

         意图答案=新的意图(Intent.ACTION_MEDIA_BUTTON);
         answer.putExtra(Intent.EXTRA_KEY_EVENT,新的KeyEvent(KeyEvent.ACTION_UP,KeyEvent.KEY code_HEADSETHOOK));
         context.sendOrderedBroadcast(回答,NULL);
         Log.d(TAG,回答来电的:+号);
     }
     返回;
 }
}
 

此方法适用到安卓4.1之后,Android已经从广播Intent.ACTION_MEDIA_BUTTON受限用户的应用程序。

所以,我的结论是,目前还没有办法我们如何能够在安卓4.1或更高版本实现这一目标。

有其他人发现的任何其他解决方法:这个问题?

解决方案

该作品从Android的2.2到4.0,现在增加了尝试捕捉到它适用于4.1.2和4.2的最后一个行之后老实说不知道它是如何工作的但它为我工作。

  Log.d(标签,InSecond方法答呼叫);
    //升级Froyo及以后触发buttonUp代替的buttonDown
    意图buttonUp =新的意图(Intent.ACTION_MEDIA_BUTTON);
    buttonUp.putExtra(Intent.EXTRA_KEY_EVENT,新的KeyEvent(
            KeyEvent.ACTION_UP,KeyEvent.KEY code_HEADSETHOOK));
    sendOrderedBroadcast(buttonUpandroid.permission.CALL_PRIVILEGED);
 

 意图headSetUnPluggedintent =新的意图(Intent.ACTION_HEADSET_PLUG);
    headSetUnPluggedintent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    headSetUnPluggedintent.putExtra(状态,0);
    headSetUnPluggedintent.putExtra(名,耳机);
    尝试 {
        sendOrderedBroadcast(headSetUnPluggedintent,NULL);
    }赶上(例外五){
        // TODO自动生成的catch块
        e.printStackTrace();
    }
 

这是为我工作的安卓4.1.2,以及我在4.2测试 这仍然给它处理的异常。

/ *编辑为结束通话* /

希望这有助于所有的人都在寻找的接听和挂断电话整体解决方案。

  / **
 *拒绝按钮,点击监听器将拒绝来电。
 * /
私有类RejectCallOnClickListener实现OnClickListener {
    @覆盖
    公共无效的onClick(视图v){
        Log.d(标签,OnRejectButton:+拒绝的OnClick);
        ignoreCall();
        exitCleanly();
    }
}

/ **
 *忽略来电
 * /
私人无效ignoreCall(){
    如果(USE_ITELEPHONY)
        ignoreCallAidl();
    其他
        ignoreCallPackageRestart();
}
/ **
 * AIDL / ITelephony技术忽略呼叫
 * /
私人无效ignoreCallAidl(){
    尝试 {
        // telephonyService.silenceRinger();

        telephonyService.endCall();
    }赶上(RemoteException的E){
        e.printStackTrace();
        Log.d(标签,ignoreCall:+错误:+ e.getMessage());

    }赶上(例外五){
        e.printStackTrace();
        Log.d(标签,ignoreCall+错误:+ e.getMessage());

    }
}
/ **
 *无视话费套餐重启技术
 * /
私人无效ignoreCallPackageRestart(){
    ActivityManager AM =(ActivityManager)getSystemService(ACTIVITY_SERVICE);
    am.restartPackage(com.android.providers.telephony);
    am.restartPackage(com.android.phone);
}
/ **
 *清理和退出程序
 * /
私人无效exitCleanly(){
    unHookReceiver();
    this.finish();

}
 

I am writing an android app in which I need to answer an incoming call, do some work and then end the call. After all the Googling I could find two different ways to achive this both of which do not work with recent versions of Android, specifically after 4.1, Jelly Bean.

I.) Access "com.android.internal.telephony.ITelephony" using Java Reflection in the Broadcast receiver for "android.intent.action.PHONE_STATE". Below sample code can be found in hundreds of related post:

public class PhoneCallReceiver extends BroadcastReceiver {
 Context context = null;
 private static final String TAG = "Phone call";
 private ITelephony telephonyService;

@Override
 public void onReceive(Context context, Intent intent) {
  if (!intent.getAction().equals("android.intent.action.PHONE_STATE")) 
    return;

  Log.v(TAG, "Receving....");
  TelephonyManager telephony = (TelephonyManager) 
  context.getSystemService(Context.TELEPHONY_SERVICE);  
  try {
      Log.v(TAG, "Get getTeleService...");
      Class c = Class.forName(telephony.getClass().getName());
      Method m = c.getDeclaredMethod("getITelephony");
      m.setAccessible(true);
      telephonyService = (ITelephony) m.invoke(telephony);
      telephonyService.silenceRinger();
      Log.v(TAG, "Answering Call now...");
      telephonyService.answerRingingCall();
      Log.v(TAG, "Call answered...");
      //telephonyService.endCall();
  } catch (Exception e) {
   e.printStackTrace();
   Log.e(TAG,
           "FATAL ERROR: could not connect to telephony subsystem");
   Log.e(TAG, "Exception object: " + e);
  }
 }
}

The problem with this code is that

<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" /> 

is required for this method to work, and this permission has been defined as "for system apps only" from android v 2.3. In short, normal user apps can not define this permission in the manifest file anymore.

II.) Another way is to simulate pushing of the Headset hook which makes Android answer the call. This is done by broadcasting the "Intent.ACTION_MEDIA_BUTTON" as shown in below code.

public class PhoneCallReceiver extends BroadcastReceiver {
 Context context = null;
 private static final String TAG = "Phone call";

 @Override
 public void onReceive(Context context, Intent intent) {
     if (!intent.getAction().equals("android.intent.action.PHONE_STATE")) 
         return;

     String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
     if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
         String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);

         Intent answer = new Intent(Intent.ACTION_MEDIA_BUTTON);
         answer.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
         context.sendOrderedBroadcast(answer, null);
         Log.d(TAG, "Answered incoming call from: " + number);
     }   
     return;
 } 
}

This method works till Android 4.1 after which android has restricted user apps from broadcasting "Intent.ACTION_MEDIA_BUTTON".

So my conclusion is that currently there is no way how we can achieve this in Android 4.1 or later.

Has anybody else found any other solution or workaround to this problem?

解决方案

This works from Android 2.2 to 4.0 and now after adding the try catch to the last line it works for 4.1.2 and 4.2 Frankly speaking dont know how it works but it works for me.

          Log.d(tag, "InSecond Method Ans Call");
    // froyo and beyond trigger on buttonUp instead of buttonDown
    Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
    buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(
            KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
    sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");

    Intent headSetUnPluggedintent = new Intent(Intent.ACTION_HEADSET_PLUG);
    headSetUnPluggedintent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    headSetUnPluggedintent.putExtra("state", 0);
    headSetUnPluggedintent.putExtra("name", "Headset");
    try {
        sendOrderedBroadcast(headSetUnPluggedintent, null);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

This is working for me in Android 4.1.2 as well as i have tested on 4.2 This still gives an exception which is handled.

/* Edit for End Call */

Hope this helps all the people looking for total solution for answer and end call.

/**
 * Reject button click listener will reject the incoming call.
 */
private class RejectCallOnClickListener implements OnClickListener {
    @Override
    public void onClick(View v) {
        Log.d(tag, "OnRejectButton: " + "Reject OnClick");
        ignoreCall();
        exitCleanly();
    }
}

/**
 * ignore incoming calls
 */
private void ignoreCall() {
    if (USE_ITELEPHONY)
        ignoreCallAidl();
    else
        ignoreCallPackageRestart();
}
/**
 * AIDL/ITelephony technique for ignoring calls
 */
private void ignoreCallAidl() {
    try {
        // telephonyService.silenceRinger();

        telephonyService.endCall();
    } catch (RemoteException e) {
        e.printStackTrace();
        Log.d(tag, "ignoreCall: " + "Error: " + e.getMessage());

    } catch (Exception e) {
        e.printStackTrace();
        Log.d(tag, "ignoreCall" + "Error: " + e.getMessage());

    }
}
/**
 * package restart technique for ignoring calls
 */
private void ignoreCallPackageRestart() {
    ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    am.restartPackage("com.android.providers.telephony");
    am.restartPackage("com.android.phone");
}
/**
 * cleanup and exit routine
 */
private void exitCleanly() {
    unHookReceiver();
    this.finish();

}

这篇关于如何以编程接听/结束的Andr​​oid 4.1打电话?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆