Change Default SMS App handler Android Q RoleManger - android

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
RoleManager roleManager = context.getSystemService(RoleManager.class);
// check if the app is having permission to be as default SMS app
boolean isRoleAvailable = roleManager.isRoleAvailable(RoleManager.ROLE_SMS);
if (isRoleAvailable){
// check whether your app is already holding the default SMS app role.
boolean isRoleHeld = roleManager.isRoleHeld(RoleManager.ROLE_SMS);
if (isRoleHeld){
Intent roleRequestIntent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS);
((AppCompatActivity)context).startActivityForResult(roleRequestIntent, ConstantsValues.REQUEST_CODES.REQUEST_RESET_SMS_HANDLER);
}
}
}else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, Custom_SharedPreference.getInstance(context).getDefaultSMSPackage());
((AppCompatActivity)context).startActivityForResult(intent, ConstantsValues.REQUEST_CODES.REQUEST_RESET_SMS_HANDLER);
}
This is working fine when Change SMS App to MyApp default handler but When I change MyApp to again Default SMS App then its not working and activityResult return 0 Activity.Cancle.
This is happend only Android Q other Versions working fine.

In short, it's not possible to revert default SMS app.
As a work-around I decided to open the previous default SMS app using this code:
runIntent = getPackageManager().getLaunchIntentForPackage(newDefaultSmsApp);
Having the same issue, I tried various workaround, like using old method to request a change of default SMS app, however the OS doesn't care at all. Using RoleManager, when requesting to "revert" the role back to default/previous SMS app, the logs shows something like this:
2021-06-18 08:23:06.246 1770-5101/? I/ActivityTaskManager: START u0 {act=android.provider.Telephony.ACTION_CHANGE_DEFAULT cmp=com.google.android.permissioncontroller/com.android.permissioncontroller.role.ui.RequestRoleActivity (has extras)} from uid 10043
2021-06-18 08:23:06.246 1770-5101/? W/PermissionPolicyService: Action Removed: starting Intent { act=android.provider.Telephony.ACTION_CHANGE_DEFAULT cmp=com.google.android.permissioncontroller/com.android.permissioncontroller.role.ui.RequestRoleActivity (has extras) } from ccc71.sb (uid=10043)
Note the Action Removed on second line.
So in summary, it's only possible to request the role for self, but impossible to revert. A real bummer for backup apps that Google is making look bad, like so many other apps these days.

Related

how can I redirect the user to Setting -> Security -> Notification Access in Flutter?

6
I'm currently developing an app for Android that uses the NotificationListenerService, which requires that the user will enable notification access for my app under Setting -> Security -> Notification Access.
My question is that can I redirect the user to this place so they will enable it? So far I only managed to direct them to Setting -> Security window.
Also, is it possible to first check if the user enabled notification access for my app already and only then redirect them?
For Flutter
After a long search, I found the solution that will show the intended notification settings.
This is only for Flutter.
I found an app_settings plugin. Just add it in pubspec.yaml and install it.
After that just one line of code.
RaisedButton(
onPressed: () {
// AppSettings.openLocationSettings();
AppSettings.openNotificationSettings();
// openWIFISettings();
},
)
For Java
To open the settings for a specific channel, you can use ACTION_CHANNEL_NOTIFICATION_SETTINGS:
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName())
.putExtra(Settings.EXTRA_CHANNEL_ID, yourChannelId);
startActivity(intent);
Using ACTION_APP_NOTIFICATION_SETTINGS will open settings of list all channels of the app:
Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
startActivity(intent);
For Notification check, you can use "areNotificationEnabled" method.
You can read at below doc/
https://developer.android.com/reference/android/support/v4/app/NotificationManagerCompat.html#areNotificationsEnabled()

How to Allow notification sound programmatically in Xiomi devices

Notification sound settings always disable in Xiomi devices. Check below image.
I want to enable sound programatically. Found similar stackoverflow questions but nothing helped.
Device : Redmi Note 5 pro, Redmi Note 9 pro
OS : MIUI 11 , MIUI 12
Note: But it works fine in all other devices. Problem only in Xiomi devices
I was looking for the same kind of issue 2 months ago, due to restrictions by Xiaomi it has become a lot harder, basically you have to have your app running without restriction in save battery settings and to bring the user to autostart where he will have to click on the toggle button to add your app.
Prompt the user to disable battery optimization for your app:
public class MainActivity extends AppCompatActivity {
#Override
protected void onStart()
{
String packageName = "com.example.myapp";
PowerManager powerManager = (PowerManager)getApplicationContext().getSystemService(POWER_SERVICE);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent i = new Intent();
if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
i.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
i.setData(Uri.parse("package:" + packageName));
startActivity(i);
}
}
}
}
For an app to use this, it also must hold the Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission
You also have to prompt the user to add your app to autostart (original credit) :
String manufacturer = "xiaomi";
if (manufacturer.equalsIgnoreCase(android.os.Build.MANUFACTURER)) {
//this will open auto start screen where user can enable permission for your app
Intent intent1 = new Intent();
intent1.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
startActivity(intent1);
}
It should now be working, let me know if it helped!
You may try to use NotificationManager.IMPORTANCE_MAX in new NotificationChannel

Android O+: Some phones seem to lack the option to change sound type for notifications

Again about notification sound on Android O+.
There are some phones where the "notification settings" window doesn't show the sound selection button (and not even the vibration button).
Here are a couple examples:
Samsung A5
Huawei Honor View 10
(not minor brands... I would say)
They were tested with Gmail app (menu -> Settings -> account -> Notification settings) on Android 8.
Here Android O - Notification Channels - Change Vibration Pattern or Sound Type is a solution to avoid the "standard" window, but why should we reinvent the wheel?
Is there any other option that I'm missing?
Thank you,
Max
P.S.
Here is a screenshot from a Honor 9 / Android 8.0.0.
Channel name is "Mail" ("Posta" in Italian). For sound ("Suoneria" in Italian) there is only an On/Off switch.
It's a mess. You need to add workarounds for the different brands/devices. This is the flow we're using to deal with it:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !isDeviceWithWorkaround()) {
// Send to notification channel settings (See https://developer.android.com/training/notify-user/channels#UpdateChannel)
}else{
Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "Sound");
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Uri.parse(someExistingRingTone));
if (isDeviceWithWorkaround()) {
intent.setPackage("com.android.providers.media");
}
try {
startActivityForResult(intent, reqCode);
} catch (ActivityNotFoundException e) {
if (isDeviceWithWorkaround()) {
Log.i(TAG, "Failed to find preferred package [" + intent.getPackage() + "]. Trying again without package.");
intent.setPackage(null);
startActivity(intent);
}
}
}
So what's happening is that if it's a device with a known issue as you talk about we send them to the good old ringtone picker.
I believe that the package com.android.providers.media doesn't have an activity to start on stock Android, but on Huawei it then opens the Media Store where we get back a ringtone URI that can be used as notification sound. (We don't want the user to end up in some other ringtone picker that might not work. We have always recommended our users to use https://play.google.com/store/apps/details?id=com.angryredplanet.android.rings_extended but it won't work with Huawei on Android 8).

Android: register new PhoneAccount for telecom

I'm trying to make a new PhoneAccount to use my implementation of ConnectionService. In the documentation it says I need to register a new PhoneAccount with TelecomManager and then select it in my phone-app's settings.
Here's my code:
TelecomManager telecomManager = (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
ComponentName componentName = newComponentName("se.example.connectionservicestandalonetest", "se.example.connectionservicestandalonetest.MyConnectionService");
PhoneAccountHandle phoneAccountHandle = new PhoneAccountHandle(componentName, "Admin");
PhoneAccount phoneAccount = PhoneAccount.builder(phoneAccountHandle, "Admin").build();
telecomManager.registerPhoneAccount(phoneAccount);
As you can see, it creates a new ComponentName that points towards my implementation of ConnectionService, then creates a new PhoneAccountHandle where I supply the ComponentName and a unique account-name. I then supply the PhoneAccountHandle in the PhoneAccount buildes, as well as label (a name?), to create a new PhoneAccount. Lastly I register the account in the telecomManager.
When I open up the phone app, nothing has changed. I see no where I could possibly change the PhoneAccount... Any ideas?
Thanks!
I've got some information that I'll just leave here for posterity.
When building your PhoneAccount, you must add CAPABILITY_CALL_PROVIDER if you make and receive calls on your own, or CAPABILITY_CONNECTION_MANAGER if you want to make or receive calls using the builtin PhoneAccount. Without either, you won't show up in the UI.
As far as I can tell, there is no dedicated API for checking whether the user has enabled your PhoneAccount. However, you can use TelecomManager.addNewIncomingCall for this purpose. Simply provide a Bundle containing a boolean extra (named whatever you want) and set that boolean to true if you're really receiving a call or false if you just want to do a permission check (or vice-versa). Then your implementation of ConnectionService.onCreateIncomingConnection can check your extra and return Connection.createCanceledConnection if you're just doing a permission check. This does not register as a call in the call log, and the ringtone never plays. addNewIncomingCall will throw if your PhoneAccount is not enabled, and succeed if it is.
As noted in the comments above, you can prompt the user to enable your PhoneAccount using TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS. Because the user can enable or disable your PhoneAccount at any time, all operations that require an enabled PhoneAccount (like addNewIncomingCall) should be placed in a try block.
Here is a little more info that might be helpful to others. After you have configured your phone account, the user needs to enable permission for your app. Getting the user to that screen should be easier. I've only seen the TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS action, but it doesn't take you to the proper screen to enable the permission. You have to select "All calling accounts" after launching that activity.
If you would like to take the user directly to the "Calling accounts" screen, I've found that this Intent will take you there.
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.server.telecom","com.android.server.telecom.settings.EnableAccountPreferenceActivity"));
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);
I've tested this with a Motorola G5S Plus and it should also work with mostly stock devices like Nexus and Pixel devices. I'm not sure if it will work with Samsung devices.
As an addendum to j__m's answer: I found a way to check if the phone account is activated without setting up a call:
private boolean checkAccountConnection(Context context) {
boolean isConnected = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
final List<PhoneAccountHandle> enabledAccounts = telecomManager.getCallCapablePhoneAccounts();
for (PhoneAccountHandle account : enabledAccounts) {
if (account.getComponentName().getClassName().equals(MyConnectionService.class.getCanonicalName())) {
isConnected = true;
break;
}
}
}
}
return isConnected;
}
As stated in the Javadoc to android.telecom.TelecomManager.getCallCapablePhoneAccounts()
Returns a list of {#link PhoneAccountHandle}s which can be used to make and receive phone calls. The returned list includes only those accounts which have been explicitly enabled by the user.

How to check whether my SMS app is default in Android

I want to check whether my SMS app is set as default app in android. I am following this tutorial:
http://android-developers.blogspot.com/2013/10/getting-your-sms-apps-ready-for-kitkat.html
I can set my SMS app as default SMS app by the following code:
Intent intent = new Intent(context, Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, context.getPackageName());
startActivity(intent);
But I want to check whether my SMS app is set as default app. How can I do that?
You can use getDefaultSmsPackage (Context context):
Used to determine the currently configured default SMS package.
For example:
public static boolean isDefaultSmsApp(Context context) {
return context.getPackageName().equals(Telephony.Sms.getDefaultSmsPackage(context));
}

Categories

Resources