In my app, I am enabling "enabled_notification_listeners" it is working in all cases except one case.
If we run the app the first time I am checking if is it enables or not if not then redirecting a user to the setting of notification access and if I upgrade the app or run the app from the android studio and I am checking that it is enabled or not it gives me it is enabled but when a notification comes I didn't receive any callbacks.
If I manually disable it and enable it, it starts working.
So is there any way that we can disable it programmatically?
Here is how I am opening the setting page:
startActivity(new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS));
How I am checking if is it enables or disables:
boolean hasNotificationAccess()
{
ContentResolver contentResolver = this.getContentResolver();
String enabledNotificationListeners = Settings.Secure.getString(contentResolver, "enabled_notification_listeners");
String packageName = this.getPackageName();
return !(enabledNotificationListeners == null || !enabledNotificationListeners.contains(packageName));
}
Can we change its status programmatically?
Related
I have an app that makes an http request via the localhost to a separate, third-party app which I do not control, and waits for a response from that call before continuing. The workflow goes like this:
User is inside my app
User presses a button, which launches and calls out to the third-party application
User interacts with the third-party application
When the third-party application finishes its work, my app picks up the completed http response, and pulls itself back to the forefront via MoveTaskToFront for the user to continue working.
This functions properly in Android 9 and below, but the last step does not work in Android 10, I believe due to the new restrictions on launching activities from the background.
I have no control over the third-party app, so I cannot modify it to close itself when finished working, or request that the calling app be returned to the foreground when appropriate. Does anyone know of a workaround for this?
Edit: as requested, I've added the code snippet with the call out. This is a Xamarin project, so it's written in C#, but this particular code section is Android-platform-specific, so I am able to make Android system calls.
First I have to bring up the third-party app:
Intent intent = CrossCurrentActivity.Current.AppContext.PackageManager.GetLaunchIntentForPackage("com.bbpos.android.tsys");
if (intent != null)
{
// We found the activity now start the activity
intent.AddFlags(ActivityFlags.ClearTask);
CrossCurrentActivity.Current.AppContext.StartActivity(intent);
}
Then I call into it via the localhost, process the response, and want to switch back to my app.
using (var client = new HttpClient())
{
// by calling .Result we're forcing synchronicity
var response = client.GetAsync("http://127.0.0.1:8080/v2/pos?TransportKey=" + pTransportKey + "&Format=JSON").Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
// as above, forcing synchronicity
string responseString = responseContent.ReadAsStringAsync().Result;
var result = JsonConvert.DeserializeObject<GeniusTransactionResponse>(responseString);
var manager = (ActivityManager)Application.Context.GetSystemService(Context.ActivityService);
var test = manager.AppTasks.First().TaskInfo.Id;
manager.AppTasks.First().MoveToFront();
//manager.MoveTaskToFront(CrossCurrentActivity.Current.Activity.TaskId, 0);
return result;
}
else
{
return null;
}
}
Quick update in case anyone else has this same issue: I was able to work around this by adding an Accessibility Service to the project. Simply having an Accessibility Service registered and enabled by the user allows MoveTaskToFront to function as it did in APIs <29; the actual service doesn't need to do anything.
I am using AccessibilityService to monitor notifications. I followed this and this. Finally, it works and I get to know about new notifications.
But, to Connect the AccessibilityService I need to ask user to enable it from the ACCESSIBILITY_SETTINGS, which I do this way:
Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivityForResult(intent, 0);
But, the problem is I want to check if the user has enabled it (AccessibilityService) or not. Also, I don't what to ask users again to enable it if they have already enabled it. So, is it possible to do this?
You can test whether the user has enabled your Accessibility Service by checking the secure settings. Settings.Secure.getString() will give you a : separated list of enabled services, and you can check whether yours is in there. Something like this:
ComponentName compName = new ComponentName(context, MyAccessibilityService.class);
String flatName = compName.flattenToString();
String enabledList = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
boolean isEnabled = enabledList != null && enabledList.contains(flatName);
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?
You can open the NotificationAccessSettingsActivity by using the following Intent, but I'm not sure about checking to see if they've already enabled your app.
startActivity(new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"));
Alternatively, for API 22+:
startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
Many Thanks to #adneal and #Waboodoo. I am posting this for an complete answer
Check permission granted or not using this method
private boolean isNotificationServiceRunning() {
ContentResolver contentResolver = getContentResolver();
String enabledNotificationListeners =
Settings.Secure.getString(contentResolver, "enabled_notification_listeners");
String packageName = getPackageName();
return enabledNotificationListeners != null && enabledNotificationListeners.contains(packageName);
}
Then show settings activity, if necessary
boolean isNotificationServiceRunning = isNotificationServiceRunning();
if(!isNotificationServiceRunning){
startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
}
You can always use the notification manager to check if notifications are enabled at the OS level:
NotificationManagerCompat.from(context).areNotificationsEnabled()
I am working at an OEM and would like to know how to deactivate the "Disable option" so that our device user can't remove pre loaded App, which is a security App. Is there an AndroidManifest Attribute in SDK 4.0. If so please let me know.
Thank you much.
No there is not a way to prevent the user from disabling pre-installed apps, and that is very much by design. The philosophy for this is that if disabling an app will not prevent the user from being able to get to settings and re-enable it, then they should be allowed to disable it.
I checked the sourcecode of the Settings app which contains the following function.
The SUPPORT_DISABLE_APPS is a systemwide flag. If you want to prevent any(!) app from beeing disabled, you can set this flag to false.
In short, the comment tells everything: The only apps which can not be disabled are:
(home screen-) launchers. These are identified by implementing a Intent with action ACTION_MAIN and category CATEGORY_HOME.
apps signed with the system cert. As you can modifiy and create this certificate during the build-process of the system image, it should be possible to sign your application with this key and thus prevent the disableing.
if (SUPPORT_DISABLE_APPS) {
try {
// Try to prevent the user from bricking their phone
// by not allowing disabling of apps signed with the
// system cert and any launcher app in the system.
PackageInfo sys = mPm.getPackageInfo("android",
PackageManager.GET_SIGNATURES);
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setPackage(mAppEntry.info.packageName);
List<ResolveInfo> homes = mPm.queryIntentActivities(intent, 0);
if ((homes != null && homes.size() > 0) ||
(mPackageInfo != null && mPackageInfo.signatures != null &&
sys.signatures[0].equals(mPackageInfo.signatures[0]))) {
// Disable button for core system applications.
mUninstallButton.setText(R.string.disable_text);
} else if (mAppEntry.info.enabled) {
mUninstallButton.setText(R.string.disable_text);
enabled = true;
} else {
mUninstallButton.setText(R.string.enable_text);
enabled = true;
}
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Unable to get package info", e);
}
There is nothing in the SDK for this. However, an app you put in the firmware cannot be uninstalled by the user, unless they root their device.
How can I check for GPS support in-App to add a feature for those with Location services enabled?
My concern is, I know I'd have to specify the tag in the manifest to declare that the app uses location services, but I still want the app to function for those without. I just want to check and, if the service is available, use it; otherwise just ignore that one feature.
Thanks.
You can check if any Location services are enabled by looking to see if any location providers are enabled. I'm using this function in my code right now:
public static boolean areProvidersEnabled(Context context) {
ContentResolver cr = context.getContentResolver();
String providersAllowed = Settings.Secure.getString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
return providersAllowed != null && providersAllowed.length() > 0;
}
Another neat thing is that you can send the user straight to the Location settings and ask them if they want to enable it. I'll leave it to you on how to ask the user, but the Intent to get to the settings is like this:
Intent intent = new Intent(Settings.ACTION_SECURITY_SETTINGS);
startActivity(intent);