0

我已经实现了清单中的 CallService,如下所示:

 <service
        android:name=".dialer.CallService"
        android:permission="android.permission.BIND_INCALL_SERVICE">
        <meta-data
            android:name="android.telecom.IN_CALL_SERVICE_UI"
            android:value="true"/>

        <intent-filter>
            <action android:name="android.telecom.InCallService"/>
        </intent-filter>
    </service>

就是这样:

@TargetApi(Build.VERSION_CODES.M)
class CallService : InCallService() {

companion object {
    private const val LOG_TAG = "CallService"
}

override fun onCallAdded(call: Call) {
    super.onCallAdded(call)
    App.GSMCALL = true;
    Log.i(LOG_TAG, "onCallAdded: $call")
    Log.i(LOG_TAG, "onCallAdded: ${call.details.handle.schemeSpecificPart}")
    call.registerCallback(callCallback)
    val intent = Intent(this, IncomingCallActivity::class.java)
    if (call.details.handle.schemeSpecificPart.contains("<INSERT PHONE NR HERE>")) { // something similar will be done, if I don't pass new_task it will go through default caller
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    }
    startActivity(intent)
    CallManager.updateCall(call)
}

override fun onCallRemoved(call: Call) {
    super.onCallRemoved(call)
    App.GSMCALL = false;
    Log.i(LOG_TAG, "onCallRemoved: $call")
    call.unregisterCallback(callCallback)
    CallManager.updateCall(null)
}

private val callCallback = object : Call.Callback() {
    override fun onStateChanged(call: Call, state: Int) {
        Log.i(LOG_TAG, "Call.Callback onStateChanged: $call, state: $state")
        CallManager.updateCall(call)
    }
}

}

现在这就是我想要的。如果我的电话是,那么我希望它通过我的通话活动。但如果它是一个不同的电话号码,我希望它回落到电话拨号器。这可能吗?我已经看到,如果我不添加 FLAG_ACTIVITY_NEW_TASK 它将崩溃,从而使手机主拨号器出现。但这只能工作一次,而且我不会使用这样的黑客来使其工作。那么还有其他想法吗?

编辑:

我正在使用带有 Android Pie 的 Google Pixel

我试图实现@marmor 建议的逻辑,但仍然不起作用。

这是我的创建活动:

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    wakeUpDeviceWhenWindowShown()
    setTheme(R.style.AppTheme)
    var params = WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            if (VERSION.SDK_INT >= VERSION_CODES.O) WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY else WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or FLAG_SHOW_WHEN_LOCKED or FLAG_DISMISS_KEYGUARD, ActivityInfo.COLOR_MODE_DEFAULT)
    setContentView(R.layout.activity_call)
    val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager
    wm.addView(window.decorView, params)
}

我在 AndroidManifest 中添加了: <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> 并且还有以下代码:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
    {
        if (!Settings.canDrawOverlays(this))
        {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, 0);
        }
    }

这是我得到的错误:

2019-07-23 13:13:06.600 18418-18418/com.xelion.android.debug E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.xelion.android.debug, PID: 18418
java.lang.IllegalStateException: View DecorView@53d8f92[IncomingCallActivity] has already been added to the window manager.
    at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:328)
    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3906)
    at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:51)
    at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:145)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6718)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

我也试过做:

    window.setType(if (VERSION.SDK_INT >= VERSION_CODES.O) WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY else WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)
    window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or FLAG_SHOW_WHEN_LOCKED or FLAG_DISMISS_KEYGUARD)

不做wm.addView(window.decorView, params)

但我只是明白了:我做错了什么? 在此处输入图像描述

4

1 回答 1

0

好的,就像在评论中一样,我建议收听来电事件,如果有特定的来电,请强制您的 UI 位于系统通话 UI 之上。

监听来电: https ://developer.android.com/reference/android/telephony/PhoneStateListener 添加PhoneStateListener

显示始终处于顶部的视图: 如何在 Android 中创建始终处于顶部的全屏覆盖活动

要使用的 WindowManager.LayoutParams:

WindowManager.LayoutParams(
    LayoutParams.WRAP_CONTENT,
    LayoutParams.WRAP_CONTENT,
    VERSION.SDK_INT >= VERSION_CODES.O ? LayoutParams.TYPE_APPLICATION_OVERLAY : LayoutParams.TYPE_SYSTEM_ERROR,
    LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_SHOW_WHEN_LOCKED | LayoutParams.FLAG_DISMISS_KEYGUARD);

编辑:

您发布的代码试图使 Activity 显示在来电屏幕的顶部,而不是您应该创建一个 View 并将其添加到 windowManager 作为警报视图。即代替:

setContentView(R.layout.activity_call)
val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager
wm.addView(window.decorView, params)

尝试做这样的事情(未经测试的代码):

View view = LayoutInflater.from(this).inflate(R.layout.activity_call)
val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager
wm.addView(view, params)
于 2019-07-17T13:32:32.890 回答