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?
Related
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);
When a phone is ringing ( by an incoming call) If the phone number is a specific number I want to show my custom UI. If It is not, I want to pass it to the (built-in) system call app(Or any other call app is okay).
I should use 'InCallService' and the device set my app as 'a default call app' so that even when the phone screen is locked my custom-UI-activity be shown. The following kotlin source code is my goal.
override fun onCallAdded(call: Call) {
//app should receive a new incoming call via 'onCallAdded'
super.onCallAdded(call)
val phoneNumber = getPhoneNumber(call)
if (isMyTargetNumber(phoneNumber)) {
//show my custom UI
} else {
//run a built-in call app
}
}
The problem that I want to solve is how to run a built-in call app appropriately. I mean I want to complete to wirte the blank of 'else'
else {
//run a built-in call app
}
Apps on the android market like 'truecaller' or 'whosecall' works well the way I want to acheive. I want to make my app such apps. Please help me and advise something to me.
We have a custom scanner to scan barcode using, which works with SOFT trigger (Using App Button) by using Motorola's emdk library.
barcodeManager = (BarcodeManager) this.emdkManager.getInstance(EMDKManager.FEATURE_TYPE.BARCODE);
scanner = barcodeManager.getDevice(BarcodeManager.DeviceIdentifier.DEFAULT);
scanner.addStatusListener(articleListener);
scanner.addDataListener(new Scanner.DataListener() {
#Override
public void onData(ScanDataCollection scanDataCollection) {
processData(scanDataCollection);
}
});
scanner.addDataListener(dataListener);
scanner.triggerType = Scanner.TriggerType.SOFT_ALWAYS;
scanner.enable();
How can i have both soft and Hard trigger to scan the data?
and with datalistener process the data received from both?
Zebra Technologies acquire Motorola Solution enterprise business in Oct. 2014, most of the updated documentation is now available under the Zebra Launchpad.
Scanner.TriggerType controls how you want to activate the barcode scanner on Zebra Android devices, usually you can set it up or Hard (scan is activated pressing the hardware trigger button) or Soft (scan is activated as soon as you call the Scanner.read() method).
To have an application that can use the Hardware trigger and having an on screen button to activate the scanner you can leave set the triggerType to Scanner.TriggerType.HARD and implement a login in the click event handler for the soft scan button so that you set the TriggerType to Scanner.TriggerType.SOFT_ONCE and then you call the Scanner.read() method. You can eventually check if there's another read active.
This is a sample implementation that you can test adding a button in the Barcode API sample included in the EMDK for Android (latest is v4.0):
private void softScan() {
if (scanner != null) {
try {
// Reset continuous flag
bContinuousMode = false;
if (scanner.isReadPending()) {
// Cancel the pending read.
scanner.cancelRead();
}
scanner.triggerType = TriggerType.SOFT_ONCE;
scanner.read();
new AsyncUiControlUpdate().execute(true);
} catch (ScannerException e) {
textViewStatus.setText("Status: " + e.getMessage());
}
}
}
So, usually you work with a TriggerType.HARD, but when you press the SCAN button you disable any pending read and you switch to TriggerType.SCAN_ONCE.
The implementation of the status listener needs to switch back the scanner to TriggerType.HARD and call the read() method.
You can find a complete sample at this github repository where I've added a Soft Scan button to the standard Zebra's EMDK Barcode API sample.
All the data are received by the same Data Listener.
Am i the only one having problems connecting to the bluetooth with startBluetoothSco? This works fine in all versions of Android except 4.4.2 (kitkat). Any suggestions? And yes, I have verified that I am connected to Bluetooth before I call this. Did something changed in 4.4.2?
Here is my code:
am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
am.setMode(AudioManager.MODE_IN_CALL);
am.setBluetoothScoOn(true);
am.startBluetoothSco();
Following your suggestion i did the following, but this is driving me nuts! What am I doing wrong. I have the listener in my MainActivity as follows...
private final BluetoothHandler.Listener mBluetoothListener = new BluetoothHandler.Listener() {
#Override
public void onConnectionComplete() {
final BluetoothHandler bluetoothHandler = mBluetoothHandler;
if (bluetoothHandler != null) {
am.setMode(AudioManager.MODE_IN_COMMUNICATION);
}
}
};
Then in my OnCreate I initialize the BluetoothHandler
if(mBluetoothHandler == null){
mBluetoothHandler = new BluetoothHandler(5000, mBluetoothListener);
} else {
mBluetoothHandler.stopSco();
mBluetoothHandler.stop();
mBluetoothHandler = null;
}
if (!mBluetoothHandler.isAudioConnected()) {
mBluetoothHandler.start(mContext);
}
The problem I'm having is that the listener doesn't detect when a BT device connects or even says that one is connected. Any suggestions? I appreciate your help...
The functionality of startBluetoothSco() changed between API 17 and API 18. In API 17, this function initiates a virtual call via SCO. In API 18, the function opens a raw SCO link. Some Bluetooth units will only respond to a virtual call.
Unfortunately it doesn't seem that Google have given us an option of choosing whether to open a virtual call or raw link so if you require a virtual call, you will need to ensure your app is built with API 17.
From the Android Developer reference:
"NOTE: up to and including API version JELLY_BEAN_MR1, this method
initiates a virtual voice call to the bluetooth headset. After API
version JELLY_BEAN_MR2 only a raw SCO audio connection is
established."
http://developer.android.com/reference/android/media/AudioManager.html#startBluetoothSco()
Which device do you use? I know that there is sometimes a Bluetooth problem with nexus devices (nexus 5 with kit at also) as described here:
http://www.androidpolice.com/2013/12/28/bug-watch-many-nexus-devices-still-suffer-from-assorted-bluetooth-issues/
Had the same problem with an app I was developming. Upong updating my phone to KitKat, the SCO connection to my car stopped working.
I finally come up with a solultion using a somehow private api in the bluetooth headset profile, while keeping my code compatible with API 19.
Fist I'm checking if current version is API 17, in that case, I use the standard startBluetoothSco from AudioManager, if not the case, I get the current BluetoothHeadset profile and use the following method to create the virtual call sco link (I can't take credit for this, I found it in the Google TalkBack application):
class BluetoothHeadsetCompatWrapper {
private static final Class<?> CLASS_BluetoothHeadset = BluetoothHeadset.class;
private static final Method METHOD_startScoUsingVirtualVoiceCall = CompatUtils.getMethod(
CLASS_BluetoothHeadset, "startScoUsingVirtualVoiceCall", BluetoothDevice.class);
private static final Method METHOD_stopScoUsingVirtualVoiceCall = CompatUtils.getMethod(
CLASS_BluetoothHeadset, "stopScoUsingVirtualVoiceCall", BluetoothDevice.class);
private final BluetoothHeadset mHeadset;
public BluetoothHeadsetCompatWrapper(BluetoothHeadset headset) {
mHeadset = headset;
}
public boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) {
return (Boolean) CompatUtils.invoke(mHeadset, false, METHOD_startScoUsingVirtualVoiceCall,
device);
}
public boolean stopScoUsingVirtualVoiceCall(BluetoothDevice device) {
return (Boolean) CompatUtils.invoke(mHeadset, false, METHOD_stopScoUsingVirtualVoiceCall,
device);
}
}
I found this solution when I was looking into the BluetoothHeadset code and found out the method actually exists, but it's hidden to the compiler https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth/BluetoothHeadset.java
I know my anwser may be late, but I posted anyway to help others.
in agreement with the recent post from Android Developers http://android-developers.blogspot.pt/2013/10/getting-your-sms-apps-ready-for-kitkat.html ,I was trying to prepare my app to the new android version, but encountered a problem with the part they suggest to create a dialog to let the user set the app as the default application to handle SMS's :
Android Developers Post
public class ComposeSmsActivity extends Activity {
#Override
protected void onResume() {
super.onResume();
final String myPackageName = getPackageName();
if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) {
// App is not default.
// Show the "not currently set as the default SMS app" interface
View viewGroup = findViewById(R.id.not_default_app);
viewGroup.setVisibility(View.VISIBLE);
// Set up a button that allows the user to change the default SMS app
Button button = (Button) findViewById(R.id.change_default_app);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent =
new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,
myPackageName);
startActivity(intent);
}
});
} else {
// App is the default.
// Hide the "not currently set as the default SMS app" interface
View viewGroup = findViewById(R.id.not_default_app);
viewGroup.setVisibility(View.GONE);
}
}
}
the code itself in pretty much straightforward, but I'm unable to access to Telephony.Sms.getDefaultSmsPackage because it says that Telephony cannot be resolved, and I can't find any import or declaration that would fix that.
Can anyone please help?
android.provider.Telephony simply doesn't exist yet (as of API 18 - 4.3).
This class will be added in 4.4 (presumably API 19), and that blog post is highlighting the changes that you should make once the new API is released so you aren't surprised when the time comes.
From the end of the post:
To help you make the changes, we'll soon be providing the necessary SDK components for Android 4.4 that allow you to compile and test your changes on Android 4.4.
Don't forget that you should wrap this code in an API version check so you don't run into issues with older versions that don't have this class.
this change will break all the SMS blocking apps.
"Note that—beginning with Android 4.4—any attempt by your app to abort the SMS_RECEIVED_ACTION broadcast will be ignored so all apps interested have the chance to receive it."
Do you think there is a way to go around this?!
Maybe at least on Root?
Apparently there is with root access. The latest version Cerberus app claim to be doing this.
Now, if only I knew how they do it :(