【问题标题】:End call in android programmatically以编程方式结束android中的调用
【发布时间】:2013-08-05 18:28:22
【问题描述】:

我看到很多问题表明在 Android 中无法以编程方式结束通话。 同时,我在 googleplay 市场上看到了很多拨号器应用程序,您可以在其中激活和挂断电话。它们是如何工作的?

编辑:我在某处读到我的应用必须是系统应用。那么如何使其系统化,系统应用程序和用户应用程序有什么区别?

【问题讨论】:

标签: android phone-call


【解决方案1】:

您无需成为系统应用。首先,在您的项目中创建包com.android.internal.telephony,并将其放入一个名为“ITelephony.aidl”的文件中:

package com.android.internal.telephony; 

interface ITelephony {      

boolean endCall();     

void answerRingingCall();      

void silenceRinger(); 

}

一旦你有了它,你就可以使用这个代码来结束通话:

TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Class clazz = Class.forName(telephonyManager.getClass().getName());
Method method = clazz.getDeclaredMethod("getITelephony");
method.setAccessible(true);
ITelephony telephonyService = (ITelephony) method.invoke(telephonyManager);
telephonyService.endCall();

例如,您可以在 PhoneStateListener 中使用它。为此,您需要清单中的权限:

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

编辑:对可怕的格式表示歉意,我仍然无法弄清楚如何在这里正确执行代码块:/

【讨论】:

  • 不能使用,没有上述权限,您不能在运行时访问 TelephonyManager。
  • @VenomVendor 我记得在调试时在 logcat 中收到类似“未授予权限 MODIFY_PHONE_STATE”的警告,但这似乎不是问题,因为上面的代码在各种设备。也许实际上不需要许可?
  • @MAHANTESH 这个特定项目是使用 minSdkVersion="8" 和 targetSdkVersion="15" 构建的。我刚刚重新检查以确认,它确实可以编译和部署,没有任何问题。当应用程序执行时,它会在 logcat 中产生警告“未授予权限 MODIFY_PHONE_STATE”。不过,这似乎不会以任何方式影响功能,所以我猜这个权限并不是真正需要的。您是在编译时还是在运行时收到错误?
  • 这仅在 minSdkVersion 为 14 或更少时有效。如果将 minSdkVersion 设置为 15 或更高,它将停止工作。
  • @WijaySharma 这段代码可以追溯到 2013 年,它的主要作用是使用reflection 来访问 android 电话的内部功能,否则不会公开。自 2013 年以来,许多内部结构都发生了变化,因此这几乎可以保证不再起作用(至少很可能不是此处显示的确切方式),从我的脑海中我认为 Android 4.0.3 仍在工作,不确定关于更高版本。
【解决方案2】:

对于 Android P(自 Beta 2 起)及更高版本,终于有了 endCall 的正式 API:

https://developer.android.com/reference/android/telecom/TelecomManager#endCall()

清单中需要ANSWER_PHONE_CALLS 权限:

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

经许可,API 28 级或以上:

TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);

if (tm != null) {
    boolean success = tm.endCall();
    // success == true if call was terminated.
}

同时原TelephonyManager下的endCall()方法现在被MODIFY_PHONE_STATE权限保护,非系统App在没有权限的情况下不能再通过反射调用(否则会触发Security Exception )。

【讨论】:

  • 您提供了非常有用的信息,但是如何在 Oreo 中处理这些信息?因为我没有得到 endcall 方法。
  • @Panache 查看 Oreo 或之前关于访问 TelephonyManager 中隐藏的 endcall 方法的已接受答案。
  • 我无法解析 endCall 方法,我确实安装了 API 28,有什么提示吗?
  • @David 您是否将build.gradle 中的compileSdkVersion 设置为28?
  • 它已在 API 级别 29 中正式弃用。
【解决方案3】:

供参考。

在某些情况下可能有用。使用InCallService 类有一个潜在的解决方法。大部分所需信息都在这里。https://developer.android.com/reference/android/telecom/InCallService.html#onCallRemoved(android.telecom.Call)

它确实需要将您的应用设置为默认手机应用并确保授予以下权限。

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

如果您实现自己的扩展InCallService 的类,那么当呼叫开始时,呼叫将绑定到您的应用,您可以通过onCallAdded() 函数获取呼叫信息。然后你可以简单地call.disconnect() 通话就会结束。

【讨论】:

  • 重要提示:要使用 ICallService,您需要从设置中将您的应用设置为默认电话应用。这意味着,现在当您有来电时其他应用程序将无法控制,您必须处理应用程序中的所有呼叫功能
  • 我一直在寻找不同的解决方案,但没有任何效果并找到了这个。如此简单,如此有用。谢谢
【解决方案4】:

减少对 Api 28+ 的调用

private void cutCall(){
    ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.READ_PHONE_STATE }, PHONE_STATE);
}

}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        if (requestCode == PHONE_STATE) {
            ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ANSWER_PHONE_CALLS }, ANSWER_CALLS);
        } else if (requestCode == ANSWER_CALLS) {
            cutTheCall;
        }
    }
}

//此代码适用于Android N(Api 28及以上)

private boolean cutTheCall() {
    TelecomManager telecomManager = (TelecomManager) getApplicationContext().getSystemService(TELECOM_SERVICE);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED || telecomManager == null) {
        return false;
    }

    if (telecomManager.isInCall()) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            callDisconnected = telecomManager.endCall();
        }
    }
    return true;
}

【讨论】:

  • 此代码需要 api 26 及以上版本。确保在清单中添加:
【解决方案5】:

除了添加 android 电话接口和广播接收器之外,您还需要为要处理意图的接收器添加带有操作 android.intent.action.PHONE_STATE 的 android manifest 接收器条目。

如果添加会出现编译时错误

uses-permission android:name="android.permission.MODIFY_PHONE_STATE`

在您的清单文件中。但即使我们删除它,它也会自动拒绝来电。

【讨论】:

  • 像这样使用 以避免编译或任何其他错误
【解决方案6】:

SilenceRinger() 不适用于 android 2.3+ 版本。只需评论它,其他代码将正常工作。 希望这对你有用!

【讨论】:

    【解决方案7】:
    public static boolean isCallActive(Context context){
        AudioManager manager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
        if(manager.getMode()==AudioManager.MODE_IN_CALL || manager.getMode()==AudioManager.MODE_IN_COMMUNICATION){
            return true;
        }
    
        return false;
    }
    

    【讨论】:

      【解决方案8】:

      只是为了添加到@headuck 的答案。对于 API 28,您还需要添加:

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

      然后在您的活动中请求权限。我总共请求了这些权限以使其正常工作(READ_PHONE_STATE、CALL_PHONE、ANSWER_PHONE_CALLS、READ_CONTACTS、READ_CALL_LOG)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多