Background
I need to get notified when a phone call is answered and hanged.
For incoming call, I use the TelephonyManager.ACTION_PHONE_STATE_CHANGED
Intent with the TelephonyManager.EXTRA_STATE
that comes with it.
The problem
For outgoing calls, you get a callback of TelephonyManager.ACTION_PHONE_STATE_CHANGED
right after starting to dial, but not when the call was answered.
I've searched over the Internet, and all claim it's impossible to do it.
However, I've noticed that some call-recording apps (such as "Boldbeast recorder") have managed to overcome this, and somehow identify the moment that the call was answered.
What I've tried
I tried to register a ContentObserver to call logs, but this didn't help, because it only gets a callback when the call has ended.
For checking the issue, here's some code I've played with:
MainActivity.kt
class MainActivity : AppCompatActivity() {
companion object {
private val REQUEST_CODE = 0
@JvmStatic
fun getAppDeclaredPermissions(context: Context): Array<out String>? {
val pm = context.packageManager
try {
val packageInfo = pm.getPackageInfo(context.packageName, PackageManager.GET_PERMISSIONS)
return packageInfo.requestedPermissions ?: return null
} catch (ignored: PackageManager.NameNotFoundException) {
}
throw RuntimeException("cannot find current app?!")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val permissionsToRequest = getAppDeclaredPermissions(this)
requestPermissions(permissionsToRequest, 0)
}
}
}
PhoneBroadcastReceiver.kt
class PhoneBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
val state = intent.getStringExtra(TelephonyManager.EXTRA_STATE)
val incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER)
Log.d("AppLog", "PhoneBroadcastReceiver $action $state $incomingNumber")
}
}
manifest
<manifest package="com.example.user.myapplication" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<application
android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver android:name=".PhoneBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
</application>
</manifest>
The questions
How do those apps work? How do they get notified when an outgoing call is answered?