Allow answering call without unlocking the device

This commit is contained in:
Juha Heinanen
2022-01-09 10:47:44 +02:00
parent 84b132cc86
commit f6a81bc9bd
5 changed files with 136 additions and 55 deletions
+6
View File
@@ -61,6 +61,12 @@
<data android:scheme="sip" /> <data android:scheme="sip" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".ProxyActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:launchMode="singleTop"
android:noHistory="true" >
</activity>
<activity <activity
android:name=".AccountsActivity" android:name=".AccountsActivity"
android:configChanges="orientation|keyboardHidden|screenSize" android:configChanges="orientation|keyboardHidden|screenSize"
@@ -72,6 +72,7 @@ class BaresipService: Service() {
@SuppressLint("WakelockTimeout") @SuppressLint("WakelockTimeout")
override fun onCreate() { override fun onCreate() {
super.onCreate()
Log.d(TAG, "At onCreate") Log.d(TAG, "At onCreate")
@@ -229,7 +230,9 @@ class BaresipService: Service() {
} }
} }
this.registerReceiver(screenReceiver, IntentFilter(Intent.ACTION_SCREEN_ON)) this.registerReceiver(screenReceiver, IntentFilter().apply {
addAction(Intent.ACTION_SCREEN_ON)
})
tm = getSystemService(Context.TELECOM_SERVICE) as TelecomManager tm = getSystemService(Context.TELECOM_SERVICE) as TelecomManager
@@ -318,8 +321,6 @@ class BaresipService: Service() {
this.registerReceiver(bluetoothReceiver, filter) this.registerReceiver(bluetoothReceiver, filter)
} }
super.onCreate()
} }
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
@@ -503,8 +504,8 @@ class BaresipService: Service() {
} }
override fun onDestroy() { override fun onDestroy() {
Log.d(TAG, "At Baresip Service onDestroy")
super.onDestroy() super.onDestroy()
Log.d(TAG, "At Baresip Service onDestroy")
this.unregisterReceiver(bluetoothReceiver) this.unregisterReceiver(bluetoothReceiver)
this.unregisterReceiver(hotSpotReceiver) this.unregisterReceiver(hotSpotReceiver)
this.unregisterReceiver(screenReceiver) this.unregisterReceiver(screenReceiver)
@@ -642,9 +643,15 @@ class BaresipService: Service() {
} }
} }
if (!Utils.isVisible()) { if (!Utils.isVisible()) {
val intent = Intent(applicationContext, MainActivity::class.java) val intent = if (isMainAlive)
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent(applicationContext, ProxyActivity::class.java)
Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK else
Intent(applicationContext, MainActivity::class.java)
intent.flags = if (isMainAlive)
Intent.FLAG_ACTIVITY_NEW_TASK
else
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP or
Intent.FLAG_ACTIVITY_NEW_TASK
intent.putExtra("action", "call show") intent.putExtra("action", "call show")
.putExtra("callp", callp) .putExtra("callp", callp)
val pi = if (VERSION.SDK_INT >= 23) val pi = if (VERSION.SDK_INT >= 23)
@@ -660,13 +667,14 @@ class BaresipService: Service() {
.setColor(ContextCompat.getColor(this, R.color.colorBaresip)) .setColor(ContextCompat.getColor(this, R.color.colorBaresip))
.setContentIntent(pi) .setContentIntent(pi)
.setCategory(Notification.CATEGORY_CALL) .setCategory(Notification.CATEGORY_CALL)
.setAutoCancel(true) .setAutoCancel(false)
.setOngoing(true) .setOngoing(true)
.setContentTitle(getString(R.string.incoming_call_from)) .setContentTitle(getString(R.string.incoming_call_from))
.setContentText(caller) .setContentText(caller)
.setWhen(System.currentTimeMillis()) .setWhen(System.currentTimeMillis())
.setShowWhen(true) .setShowWhen(true)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setFullScreenIntent(pi, true) .setFullScreenIntent(pi, true)
if (VERSION.SDK_INT < 26) { if (VERSION.SDK_INT < 26) {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
@@ -1447,6 +1455,7 @@ class BaresipService: Service() {
var sipTrace = false var sipTrace = false
var callActionUri = "" var callActionUri = ""
var isMainVisible = false var isMainVisible = false
var isMainAlive = false
var isMicMuted = false var isMicMuted = false
val uas = ArrayList<UserAgent>() val uas = ArrayList<UserAgent>()
@@ -121,12 +121,15 @@ class MainActivity : AppCompatActivity() {
if (intent?.action == ACTION_CALL && !BaresipService.isServiceRunning) if (intent?.action == ACTION_CALL && !BaresipService.isServiceRunning)
BaresipService.callActionUri = URLDecoder.decode(intent.data.toString(), "UTF-8") BaresipService.callActionUri = URLDecoder.decode(intent.data.toString(), "UTF-8")
kgm = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
window.addFlags(WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) window.addFlags(WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES)
setContentView(binding.root) setContentView(binding.root)
// Must be done after view has been created
Utils.setShowWhenLocked(this, true)
Utils.setTurnScreenOn(this, true)
Utils.requestDismissKeyguard(this)
setSupportActionBar(binding.toolbar) setSupportActionBar(binding.toolbar)
layout = binding.mainActivityLayout layout = binding.mainActivityLayout
@@ -154,6 +157,7 @@ class MainActivity : AppCompatActivity() {
imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
nm = getSystemService(NOTIFICATION_SERVICE) as NotificationManager nm = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
am = getSystemService(AUDIO_SERVICE) as AudioManager am = getSystemService(AUDIO_SERVICE) as AudioManager
kgm = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
serviceEventReceiver = object : BroadcastReceiver() { serviceEventReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
@@ -161,16 +165,20 @@ class MainActivity : AppCompatActivity() {
intent.getStringArrayListExtra("params")!!) intent.getStringArrayListExtra("params")!!)
} }
} }
LocalBroadcastManager.getInstance(this).registerReceiver(serviceEventReceiver, LocalBroadcastManager.getInstance(this).registerReceiver(serviceEventReceiver,
IntentFilter("service event")) IntentFilter("service event"))
screenEventReceiver = object : BroadcastReceiver() { screenEventReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
val event = intent.getStringExtra("event")!! val event = intent.getStringExtra("event")!!
if (event == Intent.ACTION_SCREEN_ON && !Call.isStatus("incoming")) if (event == Intent.ACTION_SCREEN_ON && Call.calls().size == 0) {
dismissKeyguard() Log.d(TAG, "setShowWhenLocked == falsed")
Utils.setShowWhenLocked(this@MainActivity, false)
} }
} }
}
LocalBroadcastManager.getInstance(this).registerReceiver(screenEventReceiver, LocalBroadcastManager.getInstance(this).registerReceiver(screenEventReceiver,
IntentFilter("screen event")) IntentFilter("screen event"))
@@ -603,7 +611,7 @@ class MainActivity : AppCompatActivity() {
if (intent.hasExtra("action")) if (intent.hasExtra("action"))
// MainActivity was not visible when call, message, or transfer request came in // MainActivity was not visible when call, message, or transfer request came in
handleIntent(intent) handleIntent(intent, intent.getStringExtra("action"))
else else
if (!BaresipService.isServiceRunning) if (!BaresipService.isServiceRunning)
if (File(filesDir.absolutePath + "/accounts").exists()) { if (File(filesDir.absolutePath + "/accounts").exists()) {
@@ -629,11 +637,13 @@ class MainActivity : AppCompatActivity() {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO), ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO),
MIC_PERMISSION_REQUEST_CODE) MIC_PERMISSION_REQUEST_CODE)
BaresipService.isMainAlive = true
} // OnCreate } // OnCreate
override fun onStart() { override fun onStart() {
Log.d(TAG, "Main onStart")
super.onStart() super.onStart()
Log.d(TAG, "Main onStart")
} }
override fun onResume() { override fun onResume() {
@@ -642,9 +652,10 @@ class MainActivity : AppCompatActivity() {
nm.cancelAll() nm.cancelAll()
BaresipService.isMainVisible = true BaresipService.isMainVisible = true
when (resumeAction) { when (resumeAction) {
"call show" -> "call show" -> {
handleServiceEvent ("call incoming", handleServiceEvent ("call incoming",
arrayListOf(resumeCall!!.ua.uap, resumeCall!!.callp)) arrayListOf(resumeCall!!.ua.uap, resumeCall!!.callp))
}
"call answer" -> { "call answer" -> {
answerButton.performClick() answerButton.performClick()
showCall(resumeCall!!.ua) showCall(resumeCall!!.ua)
@@ -692,32 +703,38 @@ class MainActivity : AppCompatActivity() {
} }
override fun onPause() { override fun onPause() {
super.onPause()
Log.d(TAG, "Main onPause") Log.d(TAG, "Main onPause")
Utils.addActivity("main") Utils.addActivity("main")
BaresipService.isMainVisible = false BaresipService.isMainVisible = false
saveCallUri() saveCallUri()
super.onPause()
} }
override fun onStop() { override fun onStop() {
Log.d(TAG, "Main onStop")
super.onStop() super.onStop()
Log.d(TAG, "Main onStop")
} }
override fun onDestroy() { override fun onDestroy() {
Log.d(TAG, "Main onDestroy")
LocalBroadcastManager.getInstance(this).unregisterReceiver(serviceEventReceiver)
BaresipService.activities.clear()
super.onDestroy() super.onDestroy()
Log.d(TAG, "Main onDestroy")
LocalBroadcastManager.getInstance(this).unregisterReceiver(screenEventReceiver)
LocalBroadcastManager.getInstance(this).unregisterReceiver(serviceEventReceiver)
BaresipService.activities.clear()
BaresipService.isMainAlive = false
} }
override fun onNewIntent(intent: Intent) { override fun onNewIntent(intent: Intent) {
// Called when MainActivity already exists at the top of current task // Called when MainActivity already exists at the top of current task
super.onNewIntent(intent) super.onNewIntent(intent)
resumeAction = "" resumeAction = ""
resumeUri = "" resumeUri = ""
Log.d(TAG, "onNewIntent ${intent.action} ${intent.data}")
if (intent.action == ACTION_CALL) { if (intent.action == ACTION_CALL) {
Log.d(TAG, "onNewIntent $ACTION_CALL ${intent.data}")
if (Call.calls().isNotEmpty() || UserAgent.uas().isEmpty()) { if (Call.calls().isNotEmpty() || UserAgent.uas().isEmpty()) {
return return
} }
@@ -746,13 +763,14 @@ class MainActivity : AppCompatActivity() {
} }
} }
} else { } else {
if (intent.getStringExtra("action") != null) val action = intent.getStringExtra("action")
handleIntent(intent) Log.d(TAG, "onNewIntent action `$action'")
if (action != null)
handleIntent(intent, action)
} }
} }
private fun handleIntent(intent: Intent) { private fun handleIntent(intent: Intent, action: String?) {
val action = intent.getStringExtra("action")
Log.d(TAG, "Handling intent '$action'") Log.d(TAG, "Handling intent '$action'")
when (action) { when (action) {
"accounts" -> { "accounts" -> {
@@ -765,7 +783,6 @@ class MainActivity : AppCompatActivity() {
} }
"call" -> { "call" -> {
if (Call.calls().isNotEmpty()) { if (Call.calls().isNotEmpty()) {
Toast.makeText(applicationContext, getString(R.string.call_already_active), Toast.makeText(applicationContext, getString(R.string.call_already_active),
Toast.LENGTH_SHORT).show() Toast.LENGTH_SHORT).show()
return return
@@ -1088,9 +1105,8 @@ class MainActivity : AppCompatActivity() {
Toast.LENGTH_LONG).show() Toast.LENGTH_LONG).show()
} }
restoreActivities() restoreActivities()
if (Build.VERSION.SDK_INT >= 22 && kgm.isDeviceLocked && kgm.isKeyguardSecure) { if (Build.VERSION.SDK_INT >= 22 && kgm.isDeviceLocked)
dismissKeyguard() moveTaskToBack(true)
}
} }
"message", "message show", "message reply" -> { "message", "message show", "message reply" -> {
val peer = params[1] val peer = params[1]
@@ -1918,20 +1934,6 @@ class MainActivity : AppCompatActivity() {
} }
} }
@Suppress("DEPRECATION")
private fun dismissKeyguard() {
Log.d(TAG, "Dismissing keyguard")
if (Build.VERSION.SDK_INT >= 27) {
setShowWhenLocked(true)
setTurnScreenOn(true)
kgm.requestDismissKeyguard(this, null)
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD)
}
}
companion object { companion object {
var accountRequest: ActivityResultLauncher<Intent>? = null var accountRequest: ActivityResultLauncher<Intent>? = null
@@ -0,0 +1,30 @@
package com.tutpro.baresip
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class ProxyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Utils.setShowWhenLocked(this, true)
Utils.setTurnScreenOn(this, true)
Log.d(TAG, "ProxyActivity onCreate")
val intent = Intent(applicationContext, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or
Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
intent.putExtras(getIntent())
startActivity(intent)
finish()
}
}
@@ -1,5 +1,7 @@
package com.tutpro.baresip package com.tutpro.baresip
import android.app.Activity
import android.app.KeyguardManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
@@ -18,6 +20,7 @@ import android.provider.OpenableColumns
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.view.View import android.view.View
import android.view.WindowManager
import android.widget.TextView import android.widget.TextView
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
@@ -660,6 +663,37 @@ object Utils {
BaresipService.activities.add(0, activity) BaresipService.activities.add(0, activity)
} }
@Suppress("DEPRECATION")
fun setShowWhenLocked(activity: Activity, show: Boolean) {
when {
Build.VERSION.SDK_INT >= 27 -> activity.setShowWhenLocked(show)
show -> activity.window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
else -> activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
}
}
fun setTurnScreenOn(activity: Activity, turn: Boolean) {
if (Build.VERSION.SDK_INT >= 27) {
activity.setTurnScreenOn(turn)
} else
@Suppress("DEPRECATION")
if (turn) {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
} else {
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
}
}
@Suppress("DEPRECATION")
fun requestDismissKeyguard(activity: Activity) {
if (Build.VERSION.SDK_INT >= 26) {
val keyguardManager = activity.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
keyguardManager.requestDismissKeyguard(activity, null)
} else {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD)
}
}
@Suppress("unused") @Suppress("unused")
fun darkTheme(ctx: Context): Boolean { fun darkTheme(ctx: Context): Boolean {
return ctx.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) == return ctx.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) ==