如何在Android 4.1中以编程方式接听/挂断电话? [英] How to programmatically answer/end a call in Android 4.1?

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

问题描述

我正在编写一个Android应用程序,需要在其中应答来电,做一些工作然后结束通话. 毕竟,在Googling上,我可以找到两种不同的方式来实现此目的,但这两种方式都不适用于最新版本的Android,尤其是在4.1(Jelly Bean)之后.

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 achieve this both of which do not work with recent versions of Android, specifically after 4.1, Jelly Bean.

I.)在广播接收器中使用Java Reflection访问"com.android.internal.telephony.ITelephony",以获取"android.intent.action.PHONE_STATE".以下示例代码可在数百篇相关文章中找到:

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);
  }
 }
}

此代码的问题是

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

是此方法起作用所必需的,并且此权限已从android v 2.3定义为仅适用于系统应用程序".简而言之,普通用户应用程序无法再在清单文件中定义此权限.

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.)另一种方法是模拟耳机挂钩的推动,这会使Android接听电话.如下面的代码所示,通过广播"Intent.ACTION_MEDIA_BUTTON"来完成.

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;
 } 
}

此方法在Android 4.1之前有效,此后android限制了用户应用广播"Intent.ACTION_MEDIA_BUTTON".

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

所以我的结论是,目前尚无办法在Android 4.1或更高版本中实现此目标.

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?

推荐答案

这适用于Android 2.2到4.0,现在在将try catch添加到最后一行后,它适用于4.1.2和4.2.坦白地说,不知道它是如何工作的但这对我有用.

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) { 
    e.printStackTrace();
}

这对于Android 4.1.2以及我在4.2上进行的测试都适用 这仍然给出了可以处理的异常.

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.

编辑结束通话

希望这可以帮助所有寻求答案和结束呼叫总体解决方案的人.

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();

}

这篇关于如何在Android 4.1中以编程方式接听/挂断电话?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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