Broadcast Receivers not working in Android 6.0 Marshmallow - android

I just updated my Nexus 5 to android 6, until now my app was working fine, but now the broadcast receivers are not working. Has something changed in the new version?
Here is the code I tried that was working on previous versions but not in marshmallow -
Android Manifest
<intent-filter >
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
<uses-permission android:name="android.permission.READ_SMS" ></uses-permission>
Broadcast Receiver
public String TAG ="someClass";
private static String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equalsIgnoreCase(ACTION_SMS_RECEIVED)) {
Log.d(TAG, "Received...");
}
}
Service
Broadcast_receiver broadcast_receiver = new Broadcast_receiver();
IntentFilter filter1 = new IntentFilter();
filter1.addAction("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(broadcast_receiver, filter1);
Similarly the broadcast receiver for PHONE_STATE is also not working.

Your app's target API level is 23, that is android M (6.0). In android M there are huge changes related to user-permissions.
Here is nice article explaining the changes.

As stated in Android - Requesting Permissions
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app... The user can revoke the permissions at any time...
It's also stated that:
System permissions are divided into two categories, normal and dangerous:
Normal permissions do not directly risk the user's privacy. If your app lists a normal permission in its manifest, the system grants the permission automatically
Dangerous permissions can give the app access to the user's
confidential data. If you list
a dangerous permission, the user has to explicitly give approval to
your app
Here are full lists of Dangerous Permissions and Normal Permissions
All that basically means that you need to manually request for any dangerous permission, when it's actually needed.
Since it potentially might be needed multiple times in your code, you can create a reusable method that checks whether specific permission is granted already and if it's not - to request it from user.
Here an example:
Java
public class PermissionManager {
//A method that can be called from any Activity, to check for specific permission
public static void check(Activity activity, String permission, int requestCode){
//If requested permission isn't Granted yet
if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
//Request permission from user
ActivityCompat.requestPermissions(activity,new String[]{permission},requestCode);
}
}
}
Kotlin
object PermissionManager {
//A method that can be called from any Activity, to check for specific permission
fun check(activity: Activity, permission: String, requestCode: Int) {
//If requested permission isn't Granted yet
if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
//Request permission from user
ActivityCompat.requestPermissions(activity, arrayOf(permission), requestCode)
}
}
}
Usage:
Java
//Inside your activity:
//1. Define static constant for each permission request
public static final int REQUEST_CODE_FOR_SMS=1;
//2. When needed (for example inside .onStart event) use method PermissionManager.check for requested permission
#Override
protected void onStart() {
super.onStart();
PermissionManager.check(this, Manifest.permission.RECEIVE_SMS, REQUEST_CODE_FOR_SMS);
}
//3. Handle User's response for your permission request
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if(requestCode==REQUEST_CODE_FOR_SMS){//response for SMS permission request
if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
//What to do if User allowed SMS permission
}else{
//What to do if user disallowed requested SMS permission
}
}
}
Kotlin
//Inside your activity:
//1. Define static constant for each permission request
val REQUEST_CODE_FOR_SMS = 1
//2. When needed (for example inside .onStart event) use method PermissionManager.check for requested permission
override fun onStart() {
super.onStart()
PermissionManager.check(this, Manifest.permission.RECEIVE_SMS, REQUEST_CODE_FOR_SMS)
}
//3. Handle User's response for your permission request
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
if (requestCode == REQUEST_CODE_FOR_SMS) {//response for SMS permission request
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//What to do if User allowed SMS permission
} else {
//What to do if user disallowed requested SMS permission
}
}
}
Note:
If you need to use PermissionManager.check inside Fragment instance, use: getActivity() as its first parameter.
You can use checkSelfPermission inside Service instance, to check if some permission is granted already, but not requestPermissions to request it. Because checkSelfPermission can be used for any Context, but requestPermissions only for Activity

Marshmallow is blocking the dangerous permissions.
This doesn't apply to the scenario listed, but it might help someone else. I kept coming to this SO for why some of our Broadcast Receiver's weren't working. We have a custom permission setup and had the android:protectionLevel="dangerous". Changed it to android:protectionLevel= "signature"and everything started working.

Related

Why is my runtime dangerous permission auto denied?

I am trying to use the "new" way of requesting external storage write permission.
But the request is automatically denied and no window pops up asking the user for permission.
Virtual Device: Pixel 2 API 30
SDK 30
I did add the permissions into the manifest file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.lab6">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE "/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
WRITE_EXTERNAL_STORAGE is a dangerous permission from my knowledge, so it has to be requested at runtime.
into my gradle dependencies I added these:
implementation 'androidx.activity:activity:1.2.0'
implementation 'androidx.fragment:fragment:1.3.0'
The activity looks like this:
public class MainActivity extends AppCompatActivity {
private ActivityResultLauncher<String> requestPermissionLauncher =
registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
if (isGranted) {
Log.d("mihai", "Permission is granted now.");
} else {
Log.d("mihai", "Permission refused ");
}
});
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button downloadBtn = findViewById(R.id.downloadButton);
Button loadBtn = findViewById(R.id.loadButton);
downloadBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d("mihai", "requesting permission");
if (ContextCompat.checkSelfPermission(
getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) ==
PackageManager.PERMISSION_GRANTED) {
Log.d("mihai", "permission already granted");
} else {
Log.d("mihai", "launching");
requestPermissionLauncher.launch(
Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
}
});
}
}
And these are the logs I get. As you can see, the request is denied. No question pops up on the phone.
2022-04-28 19:55:15.351 7499-7499/com.example.lab6 D/mihai: requesting permission
2022-04-28 19:55:15.353 7499-7499/com.example.lab6 D/mihai: launching
2022-04-28 19:55:15.592 7499-7499/com.example.lab6 D/mihai: Permission refused
Because you have denied the permission multiple times.
From the documentation:
Starting in Android 11 (API level 30), if the user taps Deny for a specific permission more than once during your app's lifetime of installation on a device, the user doesn't see the system permissions dialog if your app requests that permission again. The user's action implies "don't ask again." On previous versions, users would see the system permissions dialog each time your app requested a permission, unless the user had previously selected a "don't ask again" checkbox or option.
You will need to redirect the user to the app's setting detail to grant the permission manually.
To open an app specific app's detail setting screen:
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);

Permissions needed for NotificationManager

I'm trying to set the Ringer to Silent and Do not Disturb to Priority Only using the following
AudioManager myAudioMgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
NotificationManager myNOtificationMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
myAudioMgr.setRingerMode(AudioManager.RINGER_MODE_SILENT);
myNOtificationMgr.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY);
I keep getting a security error
java.lang.RuntimeException: Unable to start receiver MyBroadcastReceiver: java.lang.SecurityException: Notification policy access denied
I've added the Access Notification Policy permission to my Manifest file
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
Am I missing an additional permission?
It seems like the user needs to explicity grant the permission to app via the settings screen in order for the app to manipulate the priority/silent via the notifications api. I am assuming that you are using the notificationManager class for this. Some links that might help you:
https://developer.android.com/reference/android/provider/Settings.html#ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS
https://developer.android.com/reference/android/app/NotificationManager.html#ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED
I think essentially what you need to do is direct the user to the "Show Do Not Disturb access settings" and have him enable the option for notification management (Something similar for what would you do for mock location for example)
Sample code:
startActivityForResult(new Intent(android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS), 0);
Hope this helps.
From Android Developers:
Request policy access by sending the user to the activity that matches
the system intent action ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS.
Use ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED to listen for
user grant or denial of this access.
So, to get permission you should request policy access by sending the user to the activity that matches the system intent action ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS and listen for response using BroadcastReceiver with action ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED.
Also take a look at method isNotificationPolicyAccessGranted() from NotificationManager to check if permission granted.
You'll need to do something like
public class SomeFragment extends FragmentCompat {
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
int permissionNotifications = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission. ACCESS_NOTIFICATION_POLICY);
if (permissionNotifications != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(
getActivity(),
new String[] { Manifest.permission.ACCESS_NOTIFICATION_POLICY },
PERMISSION_REQUEST
);
}
}
}
keep in mind I'm not able to run this code so it may require some TLC but it's a start
To correct the java.lang.SecurityException: Access denied to process: 3454 error, android.permission.SET_WALLPAPER permission must be added to the Android Manifest.
Add the following line in your AndroidManifest.xml:
uses-permission android:name="android.permission.SET_WALLPAPER"

Android 6 bluetooth

I upgraded to Android 6 and my applications who use Bluetooth doesn't work with this new API version. It's the same problem with application on Play Store: Bluetooth spp tools pro (good application to view if bluetooth works) which doesn't discovery of devices.
The problem seems to be in Bluetooth discovery:
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.startDiscovery()
Log.i("BLUETOOTH", String.valueOf(mBluetoothAdapter.isDiscovering())); // Return false
My applications work well with Android 4/5 and I followed : http://developer.android.com/guide/topics/connectivity/bluetooth.html
Staring with Android 6.0 it is not enough to include permissions on manifest.
You have to ask the user explicitly about each permission that is considered "dangerous".
BluetoothDevice.ACTION_FOUND requires BLUETOOTH and ACCESS_COARSE_LOCATION permissions
http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#ACTION_FOUND
The ACCESS_COARSE_LOCATION
http://developer.android.com/reference/android/Manifest.permission.html#ACCESS_COARSE_LOCATION
is a "dangerous" permission and therefore you have to ask for it using requestPermission before doing actual discovery.
public void doDiscovery() {
int hasPermission = ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION);
if (hasPermission == PackageManager.PERMISSION_GRANTED) {
continueDoDiscovery();
return;
}
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{
android.Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_COARSE_LOCATION_PERMISSIONS);
}
then on you will get the user answer on onRequestPermissionsResult
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_COARSE_LOCATION_PERMISSIONS: {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
continueDoDiscovery();
} else {
Toast.makeText(this,
getResources().getString(R.string.permission_failure),
Toast.LENGTH_LONG).show();
cancelOperation();
}
return;
}
}
}
To work with previous versions of android you should use compatibility libraries and make the calls using ActivityCompat
I've spent some time investigating the problem.
Created bug report on Android bug tracker here
The problem is that system does not forward BluetoothDevice.ACTION_FOUND intents to the registered BroadcastReceiver. Logcat shows lines like this:
10-16 07:34:09.147 786-802/? W/BroadcastQueue﹕ Permission Denial: receiving Intent { act=android.bluetooth.device.action.FOUND flg=0x10 (has extras) } to ProcessRecord{5ce2d92 21736:com.example.mvl.bluetoothtest/u0a74} (pid=21736, uid=10074) requires android.permission.ACCESS_COARSE_LOCATION due to sender com.android.bluetooth (uid 1002)
Which themes for me that the application needs android.permission.ACCESS_COARSE_LOCATION permission to receive this intents. i personaly don't understand why I need that permission to get the Bluetooth devices around.
So if you add this permission to you Manifest, then it should work with one more precondition - You have to set target SDK and compile with SDK not higher, then 22.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
When checking the source code in GattService.java,you will find some code comments in method onScanResult:
// Do no report if location mode is OFF or the client has no location permission
// PEERS_MAC_ADDRESS permission holders always get results
if (hasScanResultPermission(client) && matchesFilters(client, result)) {
try {
ScanSettings settings = client.settings;
if ((settings.getCallbackType() &
ScanSettings.CALLBACK_TYPE_ALL_MATCHES) != 0) {
app.callback.onScanResult(result);
}
} catch (RemoteException e) {
Log.e(TAG, "Exception: " + e);
mClientMap.remove(client.clientIf);
mScanManager.stopScan(client);
}
}
this clarified what is needed to get a Bluetooth LE advertising report.

SecurityException thrown when calling WifiManager startScan

I'm using a PendingIntent launched by AlarmManager (with setRepeating) to start wifi scans (using IntentService) every few minutes.
On most devices and in most cases, there is no problem with that.
However, on several devices I get the following error (Couldn't reproduce the error on any test device. This is a crash log from a user's device):
java.lang.RuntimeException: Unable to start service com.myapp.android.service.MyService#44a9701 with Intent { act=com.myapp.android.ACTION_PERFORM_WIFI_SCAN flg=0x4 cmp=com.myapp/com.mayapp.android.service.MyService (has extras) }: java.lang.SecurityException: Permission Denial: broadcast from android asks to run as user -1 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL or android.permission.INTERACT_ACROSS_USERS
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3021)
at android.app.ActivityThread.-wrap17(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1443)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5415)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:725)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:615)
Caused by: java.lang.SecurityException: Permission Denial: broadcast from android asks to run as user -1 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL or android.permission.INTERACT_ACROSS_USERS
at android.os.Parcel.readException(Parcel.java:1599)
at android.os.Parcel.readException(Parcel.java:1552)
at android.net.wifi.IWifiManager$Stub$Proxy.startScan(IWifiManager.java:1045)
at android.net.wifi.WifiManager.startScan(WifiManager.java:1088)
...
I'm creating the PendingIntent from my app so I see no reason for the SecurityException thrown from WifiManager (Especially since this happens rarely).
The IntentService launched from the PendingIntent code is as follows:
mContext.registerReceiver(mWifiScanReceiver, new IntentFilter(
WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
boolean ok = mWifiManager.startScan();
Any ideas on what might be causing this?
This is happening because of the new app permissions for android m.
See the comment above the source code of wifimanager's getScanResults() for api 23-
/**
* Return the results of the latest access point scan.
* #return the list of access points found in the most recent scan. An app must hold
* {#link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
* {#link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
* in order to get valid results.
*/
public List<ScanResult> getScanResults() {
try {
return mService.getScanResults(mContext.getOpPackageName());
} catch (RemoteException e) {
return null;
}
}
Hence, you will have to ask the user for permissions on runtime. Put these permissions in your manifest-
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
From api 23 onwards you require a permission to access user location to use it. I suggest you use a permissions check based on the api level and start intent only if the permissions have been granted.
Something like this-
if (Build.VERSION.SDK_INT >= 23) {
int hasReadLocationPermission = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
if (hasReadLocationPermission != PackageManager.PERMISSION_GRANTED) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(HomeActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)) {
showMessageOKCancel("You need to allow access to GPS",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(HomeActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, GPS_ENABLE_REQUEST);
}
});
return;
}
ActivityCompat.requestPermissions(HomeActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, GPS_ENABLE_REQUEST);
return;
}
if (locationManager != null && !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
gotoGPSEnableScreen();
} else {
//Permissions granted and gps is on
launchService(true);
}
}
Further to check results-
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case GPS_ENABLE_REQUEST:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
gotoGPSEnableScreen();
}
} else {
launchService(false);
}
default:
return;
}
}
UPDATE:
android.permission.INTERACT_ACROSS_USERS_FULL is a signature level permission.
Just add this android:protectionLevel="signature" in your manifest .
For more details you can check this
http://developer.android.com/guide/topics/manifest/permission-element.html
<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" android:protectionLevel="signature"/>
If you're going to override
onCreate()
in your
IntentService,
then make sure you call
super.onCreate()
in it. That seems to quite likely be your problem.
Your issue is you are calling from different user and asking to run on different user and that requires android.permission.INTERACT_ACROSS_USERS_FULL and that is signature level permission. Just add this android:protectionLevel="signature" in your manifest .
For more details you can check this
http://developer.android.com/guide/topics/manifest/permission-element.html
<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" android:protectionLevel="signature"/>

End call in android programmatically

I see a lot of questions that it's impossible to end call programmatically in Android.
At the same time, I see a lot of dialer apps in googleplay market where you can activate the call and drop it also. How do they work?
Edit: I've read somewhere that my app has to be system app. Then how to make it system, and what is the difference between system and user apps?
You do not need to be a system app. First, create package com.android.internal.telephony in your project, and put this in a file called "ITelephony.aidl":
package com.android.internal.telephony;
interface ITelephony {
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
Once you have that, you can use this code to end a call:
TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Class clazz = Class.forName(telephonyManager.getClass().getName());
Method method = clazz.getDeclaredMethod("getITelephony");
method.setAccessible(true);
ITelephony telephonyService = (ITelephony) method.invoke(telephonyManager);
telephonyService.endCall();
You could use this inside a PhoneStateListener, for example. For this to work, you require permissions in manifest:
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Edit: Apologies for horrible formatting, I still can't figure out how to properly do code blocks here :/
For Android P (since Beta 2) and above, there is finally a formal API for endCall:
https://developer.android.com/reference/android/telecom/TelecomManager#endCall()
The ANSWER_PHONE_CALLS permission is required in manifest:
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
With the permission, for API level 28 or above:
TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
if (tm != null) {
boolean success = tm.endCall();
// success == true if call was terminated.
}
At the same time the original endCall() method under TelephonyManager is now protected by MODIFY_PHONE_STATE permission, and can no longer be invoked by non-system Apps by reflection without the permission (otherwise a Security Exception will be triggered).
For Information.
May be of use in some situations. There is a potential workaround using the InCallService class. Most of the required information is here.https://developer.android.com/reference/android/telecom/InCallService.html#onCallRemoved(android.telecom.Call)
It does require setting your app as the default phone app and ensuring the following is granted.
<uses-permission android:name="android.permission.CALL_PHONE" />
If you implement your own class extending InCallService then when a call starts the call binds to your app and you get the call information through the onCallAdded() function. You can then simply call.disconnect() and the call will end.
Cut Call for the Api 28+
private void cutCall(){
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.READ_PHONE_STATE }, PHONE_STATE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestCode == PHONE_STATE) {
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ANSWER_PHONE_CALLS }, ANSWER_CALLS);
} else if (requestCode == ANSWER_CALLS) {
cutTheCall;
}
}
}
//This code will work on Android N (Api 28 and Above)
private boolean cutTheCall() {
TelecomManager telecomManager = (TelecomManager) getApplicationContext().getSystemService(TELECOM_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED || telecomManager == null) {
return false;
}
if (telecomManager.isInCall()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
callDisconnected = telecomManager.endCall();
}
}
return true;
}
SilenceRinger() does not work for android 2.3+ versions. Just comment it, other code will work fine.
Hope this works for you!
Along with Adding android telephony interface and a broadcast receiver, you will also need to add android manifest receiver entry with the action android.intent.action.PHONE_STATE for the reciever you want to handle intent.
You will get compile time error if you add
uses-permission android:name="android.permission.MODIFY_PHONE_STATE`
in your manifest file. But even if we remove this, it automatically rejects the incoming calls.
public static boolean isCallActive(Context context){
AudioManager manager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
if(manager.getMode()==AudioManager.MODE_IN_CALL || manager.getMode()==AudioManager.MODE_IN_COMMUNICATION){
return true;
}
return false;
}
Just to add to #headuck's answer. For API 28, you also need to add:
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
then request the permission in your activity. In total I requested these permissions to make it work (READ_PHONE_STATE, CALL_PHONE, ANSWER_PHONE_CALLS, READ_CONTACTS, READ_CALL_LOG)
You can end calls using Telecom manager. I tested it and it worked.
You need permission ANSWER_PHONE_CALLS to do so. Even though it hints to answered calls I had it ending a call made from this phone. And this works for modern Androids.
TelecomManager telecomManager = (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
telecomManager.endCall();

Categories

Resources