Если мое приложение выбрано в качестве приложения для набора номера по умолчанию. Можно ли сделать намерение показать вызов в номеронабирателе

Я реализовал 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, произойдет сбой, в результате чего появится основной номеронабиратель телефона. Но это работает только один раз, и я бы не стал использовать такой хак, чтобы заставить его работать. Так есть другие идеи?

РЕДАКТИРОВАТЬ:

Я использую Google Pixel с Android Pie.

Я попытался реализовать логику, которую предложил @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)

Но я просто понимаю: что я делаю неправильно? введите здесь описание изображения


person rosu alin    schedule 15.07.2019    source источник
comment
не уверен, что понимаю, о каком намерении вы говорите? это ACTION_CALL, ACTION_DIAL или что-то другое?   -  person marmor    schedule 16.07.2019
comment
При получении звонка с другого телефона я хочу, чтобы он отображался для определенного номера (для определенного списка номеров нужен пользовательский интерфейс). Я реализовал это: github.com/mbarrben/android_dialer_replacement Это работает. Но для остальных номеров я хочу НЕ показывать свой пользовательский интерфейс, а просто вернуться к исходному приложению телефона по умолчанию (как я буду получать звонки, если не изменю приложение Caller по умолчанию на свое собственное). Теперь я увидел, что если я не установлю FLAG_ACTIVITY_NEW_TASK в своем намерении, он запустит экран звонящего по телефону в качестве запасного варианта. Но я хочу что-то более чистое   -  person rosu alin    schedule 17.07.2019
comment
пожалуйста, не делайте этого... вы возитесь с входящими звонками людей и можете создать мир боли. если вы хотите отобразить некоторый пользовательский интерфейс для определенных вызовов, я бы предложил обнаруживать такие входящие вызовы с помощью прослушивателя состояния телефонии и добавить постоянно отображаемый пользовательский интерфейс поверх пользовательского интерфейса системного вызова. дайте мне знать, если вам нужны ссылки   -  person marmor    schedule 17.07.2019
comment
Так что просто сделайте телефонный государственный приемник. И когда я получаю флаги для получения вызова, я принудительно использую свой собственный пользовательский интерфейс поверх пользовательского интерфейса системного вызова? Если так? Вы можете предоставить некоторые ссылки?   -  person rosu alin    schedule 17.07.2019
comment
@marmor Я отредактировал свой вопрос, чтобы включить больше данных, если у вас есть возможность проверить   -  person rosu alin    schedule 23.07.2019


Ответы (1)


Итак, как и в комментариях, я бы порекомендовал прослушивать события входящего вызова и, если поступает конкретный вызов, принудительно использовать ваш пользовательский интерфейс поверх системного пользовательского интерфейса вызова.

Прослушивание входящих звонков: 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);

ИЗМЕНИТЬ:

Код, который вы разместили, пытается сделать так, чтобы действие отображалось поверх экрана входящего вызова, вместо этого вы должны создать представление и добавить его в оконный менеджер в качестве представления предупреждения. то есть вместо:

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)
person marmor    schedule 17.07.2019
comment
Я пробовал это, но, к сожалению, это не сработает. Номеронабиратель по умолчанию имеет приоритет, поэтому он будет перекрывать мою активность :( - person rosu alin; 23.07.2019
comment
У меня это работает в популярном производственном приложении, проверьте еще раз. частым вариантом использования этого шаблона являются приложения для идентификации вызывающего абонента, которые показывают всплывающее окно поверх экрана входящего вызова, устанавливают любое приложение для идентификации вызывающего абонента, и вы можете убедиться, что оно работает. - person marmor; 23.07.2019
comment
Можете ли вы сказать мне название производственного приложения? чтобы я мог посмотреть, пожалуйста, заранее спасибо - person rosu alin; 23.07.2019
comment
просто найдите в Google Play идентификатор вызывающего абонента, и вы найдете множество приложений, которые отображают всплывающее окно поверх экрана входящего вызова. - person marmor; 23.07.2019
comment
Хорошо спасибо. Затем из ссылки «Как создать всегда верхний полноэкранный оверлей», какой ответ сработал для вас? Принятый? PS: я хочу, чтобы это приложение не устанавливалось в качестве приложения для звонков по умолчанию. Я также могу сделать это в своем приложении, если я установил в настройках приложение по умолчанию. Но я хочу просто перехватить и показать свою активность в случае специальных номеров - person rosu alin; 23.07.2019
comment
см. редактирование моего ответа с версией LayoutParams, которая работает - person marmor; 23.07.2019