Deprecated telecomManager.endCall() in android API 29 android - android

Before I used below code to end the call
val telecomManager = context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
if (PermissionsUtil(context).checkPermissions()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
telecomManager.endCall()
} else {
//telecomManager.isInCall
declinePhone(context)
}
}
but now in API 29 telecomManager.endCall() shows deprecated.
Do I have to create a service running in the background CallScreeningService or InCallService? where there is no direct method for endCall() third party apps cannot do this without becoming a default caller app.
If so then how I will get the call details and how to keep my service running in the background for Chinese rom

Yes, you have to create a CallScreeningService and users have to choose your app as an default app for Call Screening service....

Related

How to handle `is deprecated. Deprecated in Java`?

The code I want to use:
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
There is FLAG_SHOW_WHEN_LOCKED that is deprecated in the API 27 and its alternative setShowWhenLocked added in the API 27
How should I use it properly if the minSdk in my project is 21 and the targetSdk is 33?
I get the warning is deprecated. Deprecated in Java
Even if I handle it this way:
if(Build.VERSION.SDK_INT >= 27) {
setShowWhenLocked(true)
setTurnScreenOn(true)
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
}
I still get the warning. What is the right way to support both old and new API?
TLDR
1.Use different code for different API versions.
2.Ignore/surpress this warning if you properly proccess all the API versions that your app is created for
3.If there is a new alternative that works for all the API levels - use it
Instruction
Use Build.VERSION.SDK_INT in the condition to behave accordingly to the SDK_INT
Use setshowwhenlocked if SDK_INT>=27 and FLAG_SHOW_WHEN_LOCKED if SDK_INT<27
Surpress the warning
Example with the FLAG_SHOW_WHEN_LOCKED/setShowWhenLocked
if(Build.VERSION.SDK_INT >= 27) {
setShowWhenLocked(true)
setTurnScreenOn(true)
} else {
#Suppress("DEPRECATION")
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
}
But why do we have to surpsess the warning?
The warning exists only because #Deprecated APIs do not have any metadata that would indicate which SDK they were deprecated in. as you can see in this issue.
We can surpress the error because we have properly processed both old api (5-27) and new api (27>)
Warning
Do not surpress these warnings if the code is not properly processed by using if conditions where the right API is used.
Example how you must not do
#Suppress("DEPRECATION")
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
Your minSdk is 21 and targetSdk is 33
This code will work on devices with 5-27 API (Android 5 - Android 8.1) but will not work on new devices. You must properly handle both conditions.
Example with the Vibrator
The old way to get the vibrator
context.getSystemService(VIBRATOR_SERVICE) as Vibrator
The new way to get the vibrator
val vibrator = if (Build.VERSION.SDK_INT >= 31) {
val vibratorManager =
context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
vibratorManager.defaultVibrator
} else {
#Suppress("DEPRECATION")
context.getSystemService(VIBRATOR_SERVICE) as Vibrator
}
Will show you the warning `'VIBRATOR_SERVICE: String' is deprecated. Deprecated in Java`. Go to the [documentation](https://developer.android.com/reference/kotlin/android/content/Context#vibrator_service) and see that this constant can be used in the API 1-31 so we must. And in both IDE and documentation there is the info about the alternative: `Deprecated: Use android.os.VibratorManager to retrieve the default system vibrator.`. As you can see the [VibrationManager](https://developer.android.com/reference/kotlin/android/os/VibratorManager) is added in the API 31 therefore we must write the different code for different sdk versions
If an alternative is backwards compatible
If an alternative is backwards compatible you can just use it instead of the old way
Example
If you inherit AppCompatActivity in your activity:
class SaveMyLifeActivity : AppCompatActivity()
You can meet the warning startActivityForResult(Intent!, Int): Unit' is deprecated. Deprecated in Java if you call startActivityForResult:
val intent = Intent(this, SaveMyLifeActivity::class.java)
startActivityForResult(intent, 0)
You can press Alt+Q (Default keybind) to see the Context info(it is called this way in the AndroidStudio is you check your keymap) or use the website do see the documentation
Take a look to the words that this method is deprecated and you must use registerForActivityResult instead. This method can be called in any version right now, there are no Added/Deprecated "section" in the documentation.
Question: How have you found this documentation? I google AppCombatActivity startActivityForResult and come to this documentation. There is no word about startActivityForResult.
Answer: Open the context info about this method in the IDE (Alt+Q) and look at the bottom of the Context info . There is a class name where this method is located in (ComponentActivity). You have to google ComponentActivity startActivityForResult instead of AppCombatActivity startActivityForResult

telephony.listen , phoneStateListener not working when app is closed

This PhoneStateListener only works if the app is open for API>28(P) but i want the incoming/outgoing phone number even if the app is closed just like it works in API<=28(P).
i am getting the phone number if the app is open at the time of call, but otherwise number is coming as blank.
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
phnNbr = intent?.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER).toString()
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P && Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
val telephony =
context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
telephony.listen(object : PhoneStateListener() {
override fun onCallStateChanged(state: Int, incomingNumber: String) {
super.onCallStateChanged(state, incomingNumber)
println("incomingNumber API>28: $incomingNumber")
phnNbr = incomingNumber
}
}, PhoneStateListener.LISTEN_CALL_STATE)
}
I was using onCallStateChanged as i learned from the documentation that the getStringExtra(EXTRA_INCOMING_NUMBER) is deprecated in SDK<= Android P. But to my surprise, as I had READ_PHONE_NUMBERS & READ_CALL_LOG permissions, the old way getStringExtra(EXTRA_INCOMING_NUMBER) worked for me and this also solved wrong responses when operating Sim 2. Just be sure to handle multiple calls to fun onReceive of the BroadcastReceiver.
It is normal behavior for Android OS to protect user privacy against malicious apps from stealing user information. However, You can resolve the problem by using a System Event Broadcast Receiver to be notified of incoming phone calls. Here is a good example to follow. The example is not enough and applicable for current android API levels and you need to have a Foreground Service when a call is received then run the Foreground Service and execute your codes.

Is there any way to receive implicit broadcasts in android API 26 and above

I want to receive BroadCast if an application on the target device is updated or uninstalled. Based on the document I can use ACTION_PACKAGE_REPLACED and ACTION_PACKAGE_REMOVED.
Replace action: A new version of an application package has been installed, replacing an existing version that was previously installed.
Remove Action: An existing application package has been removed from the device. The data contains the name of the package. The package that is being removed does not receive this Intent.
so I implemented this in my foreground service:
val mIntentFilter = IntentFilter()
mIntentFilter.addAction("android.intent.action.PACKAGE_REMOVED")
mIntentFilter.addAction("android.intent.action.PACKAGE_REPLACED")
mIntentFilter.addDataScheme("package")
this.registerReceiver(applicationReceiver, mIntentFilter)
It works perfectly for removing action, But unfortunately, I didn't receive any broadcast for updating action.
I found out that it is because of the Limits imposed by Google on API 26 and above:
As part of the Android 8.0 (API level 26) Background Execution Limits, apps that target the API level 26 or higher can no longer register broadcast receivers for implicit broadcasts in their manifest.
As this is one of the key features of my application, can anybody help me how to handle this?
You could try this
class Test(var context: Context) {
var version: Long = -1
var pm: PackageManager = context.packageManager
var e: PackageManager.NameNotFoundException? = null
init {
val info = pm.getPackageInfo("com.google.maps", 0)
version = if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P) {
info.longVersionCode
} else info.versionCode.toLong()
}
init {
e!!.printStackTrace()
}
}
And then compare your retrieved value to a stored value

Simulate long press of KEYCODE_HEADSETHOOK

I am trying to programmatically control incoming call (Accept and reject) Target Android 6.0 and above in my companion app.
Working method but deprecated
telecomManager.acceptCall() and telecomManager.endCall()
This method is working fine till Android 10 and also in virtual Android 11 but in developers site it says it is deprecated.
This method was deprecated in API level 29.
Companion apps for wearable devices should use the InCallService API instead.
Partially working method
By simulation headset press button key event found that the call can be controlled. The following is my implementation
void sendHeadsetHookLollipop() {
MediaSessionManager mediaSessionManager = (MediaSessionManager) getApplicationContext().getSystemService(Context.MEDIA_SESSION_SERVICE);
try {
List<MediaController> mediaControllerList = mediaSessionManager.getActiveSessions
(new ComponentName(getApplicationContext(), NotificationReceiverService.class));
for (MediaController m : mediaControllerList) {
if ("com.android.server.telecom".equals(m.getPackageName())) {
m.dispatchMediaButtonEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
log.info("HEADSETHOOK sent to telecom server");
break;
}
}
} catch (SecurityException e) {
log.error("Permission error. Access to notification not granted to the app.");
}
}
in the above piece of code, I am able to answer the ringing call. To reject, I need to simulate a long press of the same KeyEvent.
1.How to achieve long press of a keyEvent?
2. Is there any other non deprecated implementation method for the above need?
3.In the telecomManager class, they have suggested to implement InCallService . How to implement InCallService without making my app default app?

How to end GSM call programmatically on Android 10

We develop an Android app which is capable of ending a GSM call.
We used this solution for years:
end incoming call programmatically
On Android 10 this solution unfortunately fails.
I can't find any other solution which actually works on Android 10.
Any suggestions?
It is possible to stop GSM call on Android 10.
Next code is in Xamarin Android API level 27 using reflection.
First request for permission:
// Check permission AnswerPhoneCalls
if (ContextCompat.CheckSelfPermission(context, Android.Manifest.Permission.AnswerPhoneCalls) != (int)Permission.Granted)
{
activity?.RunOnUiThread(() =>
ActivityCompat.RequestPermissions(activity, new string[1] { Android.Manifest.Permission.AnswerPhoneCalls }, 0));
}
Then stop GSM call by:
TelecomManager telecomManager = (TelecomManager)activity.GetSystemService(Context.TelecomService);
var endcall = telecomManager.Class.GetDeclaredMethod("endCall");
endcall.Accessible = true;
endcall.Invoke(telecomManager);

Categories

Resources