How to check if "Multiple users" is enabled - android

Is there a system setting table or API I can check to see if the "Multiple users" setting is turned on in Settings -> System -> Advanced -> Multiple users?
Thanks!

After a few hours of searching, I found the answer by browsing /data/system/users/0 and looking through settings_system.xml, settings_secure.xml, and settings_global.xml. It turns out what I'm looking for is "user_switcher_enabled" in settings_global.xml.
Here's my code:
public static boolean isMultipleUsersEnabled(Context context) {
try {
int pref = Settings.Global.getInt(context.getContentResolver(), "user_switcher_enabled");
return pref == 1 && (Build.VERSION.SDK_INT < Build.VERSION_CODES.N || UserManager.supportsMultipleUsers());
} catch (Settings.SettingNotFoundException e) {
Utils.logError(TAG, "user_switcher_enabled setting not found: " + e.toString());
return false;
}
}
The check for UserManager.supportsMultipleUsers() is probably not needed, but just in case the preference is somehow bogus on devices that don't actually support multiple users.
If there's anything you want to add to this answer, please comment below.

For API level 24 and above, you can use the method UserManager.supportsMultipleUsers(), which returns whether the device supports multiple users in boolean.
Before API level 24, there are no methods to check this without system permissions. There can be a workaround, like getting the count of users using the method getUserCount(). Again this also needs android.permission.MANAGE_USERS permission.

Related

Settings.Secure.ALLOW_MOCK_LOCATION always returns 1 even mock setting is Off

I'm developing an app where a user will not be able to use it if mock location setting is enabled using this piece of code
if (Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.ALLOW_MOCK_LOCATION).equals("0"))
return false;
else
return true;
well it was working fine in most of my test devices from KitKat to Marshmallow systems, until I tried my app on this single device with Marshmallow OS, the mock setting is clearly OFF, but that code above keeps telling me that the mock setting is ON, is this a bug? or am i missing something here?
Checking out this answer from here.
boolean isMock = false;
if (android.os.Build.VERSION.SDK_INT >= 18) {
isMock = location.isFromMockProvider();
} else {
isMock = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
}
This might help you
According to the android developer reference: https://developer.android.com/reference/android/provider/Settings.Secure.html ALLOW_MOCK_LOCATION is now deprecated in SDK 23.
The default value you will get will always be 1 in marshmallow.

Android 5.0 (L) - Check data Roaming Setting

I have a problem identifying the data roaming setting in Android L. In previous versions of Android, I was able to access either Settings.Secure or Settings.Global (depending on the Android version), and get the setting.
But now, on Android L, this no longer works. Whether data roaming is on or off, the return from the Settings.Global is always 0.
Android L supports multi SIM out of the box, so, a new manager was created to handle this: SubscriptionManager. This subscription manager, handles the several settings of the several SIM cards in the form of SubInfoRecord classes. I can retrieve the settings per SIM card.
However, the dataRoaming filed inside that class is always 0 as well.
Does anyone know how can this be achieved on the new API?
My app is a system app that comes embedded in the phones from factory so, I should be able to access all the APIs available.
However, I've spent a long time looking in the source code but I found nothing. In the Settings.Global class there's no indication that that setting no longer works on Android.
Does anyone have a clue on where this setting was moved to?
Thanks in advance!
Check this DevicePolicyManager.setGlobalSetting
as from documentation this can only be called by device owner app.
Is your app is installed as device owner ?
If not you can check the following links
Create device owner without root
Create device owner with root
Do something like this
DevicePolicyManager manager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
manager.setGlobalSetting(<Admin_Component>, Settings.Global.DATA_ROAMING, <value>);
Admin_Component: Component instance
Value: "0" for disable or "1" for enable
Since android 5.0, android supports multiple SIM cards, use the following code to check for data roaming.
public static boolean isDataRoamingEnabled(Context context) {
SubscriptionManager subMngr = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
int id = SubscriptionManager.getDefaultDataSubscriptionId();
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
return false;
}
SubscriptionInfo ino = subMngr.getActiveSubscriptionInfo(id);
if (ino == null)
return false;
return ino.getDataRoaming() == 1;
}

Android PreInstall detection

My android application will be preinstalled. And I want to keep tracking of preinstalled apps.
For this purpose I need somehow to save a key or a flag (which means that app is preinstalled). I will add this key to each request to my back-end and will analyze it.
I have an issue with that. An issue is about update from Google Play.
The standart workflow is the following:
1) I give to a manufacturer a special version of my application, which saves a key somehow (in Shared Prefs for example).
2) Manufacturer sell device with the app (special, modified).
3) When User get it, there definetly be next version of the app (standart, without special code) in the Google Play, so user perhaps update it without any launching (the worst case).
4) I lost my tracking possibility. (new apk fully removing never launched old one which was special)
To solve it I was listening a system broadcast ON_BOOT_COMPLETE, but its not working properly on Android 3.1+.
Have you any ideas how can I do that?
Can you install an additional .apk that only has a service? Then that service can have the key, etc. and it can listen for when your app starts and send the tracking info. Then it won't matter if your app gets upgraded; the service will still be the same.
There are some ways to know if application is system application or not. Like by checking installed directory of application or check FLAG_SYSTEM for the application.
Method 1 : -
Check location of application
public static boolean applicationIsSystemApp(Context mContext, String packageName) {
try {
ApplicationInfo applicationInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0);
String appLocation = applicationInfo.publicSourceDir;
// OR String appLocation = applicationInfo.sourceDir;
// Both returns the same
// if package is pre-installed then output will be /system/app/application_name.apk
// if package is installed by user then output will be /data/app/application_name.apk
// Check if package is system app
if (appLocation != null && appLocation.startsWith("/system/app/")) {
return true;
}
} catch (NameNotFoundException e) {
e.printStackTrace(); // TODO Can handle as your logic
}
return false;
}
Method 2 : -
Check FLAG_SYSTEM of application
public static boolean applicationIsSystemApp(Context mContext, String packageName) {
try {
ApplicationInfo applicationInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0);
// FLAG_SYSTEM is only set to system applications,
// this will work even if application is installed in external storage
// Check if package is system app
if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
return true;
}
} catch (NameNotFoundException e) {
e.printStackTrace(); // TODO Can handle as your logic
}
return false;
}
And call this method as
if (applicationIsSystemApp(getApplicationContext(), "com.example.mysystemapp")) {
// Application is system app
} else {
// Application has been installed as 3rd Party app
}
There is a property sourceDir in ApplicationInfo class. You can use it to distinguish the system app version and the upgraded one.
System app will start with "/system/app" and upgraded app will start with "/data/app"
Try something like this
try {
ApplicationInfo appInfo = this.getPackageManager().getApplicationInfo("com.example.san", 0);
boolean isSystemApp = false;
if(appInfo.sourceDir.startsWith("/system/app")){ // You can use "contains" too
isSystemApp = true;
}
} catch (Exception e) {
e.printStackTrace();
}
Note: I didnt test it.. Hope it works
One proven solution is to pre-install an APK that on have the permission: RECEIVE_BOOT_COMPLETED
Then on the very first boot - you make a quick notation that you are a PREINSTALLED to whatever persistent storage you use, preferably add a token file.
You look for this token file on all your later APK versions to determine if the running copy originates from a device which had it pre-installed or not.
This solves the mayor issues:
1) Then its OK if the user updates you APK to the latest version, you can still read this token.
2) You don't have to maintain a separate APK on google play for the pre-installed community
3) You don't have to hustle with the OEM to install multiple APK when you actually only have one App.

Is there a way for testing Permissions in Android Eclipse?

Hi there I am making my app and I am worried that I might have left some permissions out and can really never be sure I have used the right permissions can you put in any sort of code to see what my app is actually using? or something like that as it is always a guessing game for me when selecting my permissions as I can never be sure.
Heres an example I make a "Check for Updates" Button. From that I launch an Intent to go to my app in the market is that using the internet connection ? or am I just using an Intent because some people will not have a working data connection so would I have to write access full network or something like that? Its just really confusing me
I think u have to check it during testing phase of apps.if there is not proper permissions given by u then the apps give error and u can add proper permission according to error.
Here is an example to walk through permissions:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PackageManager pm = getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo("<INTERESTING PACKAGE NAME>", PackageManager.GET_PERMISSIONS);
if ((null == pi.requestedPermissions) ||
(pi.requestedPermissions.length == 0)) {
Log.d("NOTE", "Package has NO permissions!");
return;
}
for (int i = 0; i < pi.requestedPermissions.length; ++i) {
Log.d("NOTE", pi.requestedPermissions[i] + " " + checkCallingOrSelfPermission(pi.requestedPermissions[i]));
}
} catch (NameNotFoundException e) {
Log.d("ERR", "Package name is wrong!");
}
}
Edit: your question seems to ask what permissions your app is using; this code tells your app what permissions you've requested. If you want to know what is being used, you need to strip all permissions from your app (which will cause runtime errors if you actually need any of them), and then through reading error logs and/or incrementally adding permissions until things work correctly, determine by hand what is actually needed.

Where can I get a list of more Android permissions? (other than ...)

I'm trying to get a list of valid Android permissions. I know the 'official' ones at http://developer.android.com/reference/android/Manifest.permission.html but it seems there are more out there.
Please do not answer by just repeating that link.
For example
android.permission.READ_SETTINGS
android.permission.ACCESS_LOCATION
android.permission.ACCESS_GPS
com.android.vending.CHECK_LICENSE
com.android.browser.permission.READ_HISTORY_BOOKMARKS
com.android.browser.permission.WRITE_HISTORY_BOOKMARKS
com.google.android.googleapps.permission.GOOGLE_AUTH
com.google.android.googleapps.permission.GOOGLE_AUTH.OTHER_SERVICES
com.google.android.c2dm.permission.RECEIVE
Where can I get such a list? Where do I get a description for these permissions?
adb shell pm list permissions -s
This might be what you're looking for.
There is no such thing as a comprehensive "list" for all permissions. New permissions can be defined by any application that wants to enforce its own: https://developer.android.com/guide/topics/security/security.html#declaring.
The Manifest.permission class lists the "system" permissions, and you're already aware of those. The other things you've listed aren't system permissions, but rather are specific to certain apps, and or are old names (ACCESS_LOCATION and ACCESS_GPS were pre 1.0 names, for example).
A grep for something like <permission android:name= in the source would reveal all the included app permissions (for the open source apps), but in general you should stick to the documented permission names.
Use the following snippet to get all the permissions declared on your device:
Context context = this;
PackageManager pm = context.getPackageManager();
CharSequence csPermissionGroupLabel;
CharSequence csPermissionLabel;
List<PermissionGroupInfo> lstGroups = pm.getAllPermissionGroups(0);
for (PermissionGroupInfo pgi : lstGroups) {
csPermissionGroupLabel = pgi.loadLabel(pm);
Log.e("perm", pgi.name + ": " + csPermissionGroupLabel.toString());
try {
List<PermissionInfo> lstPermissions = pm.queryPermissionsByGroup(pgi.name, 0);
for (PermissionInfo pi : lstPermissions) {
csPermissionLabel = pi.loadLabel(pm);
Log.e("perm", " " + pi.name + ": " + csPermissionLabel.toString());
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
To list all permissions on your phone
adb shell pm list permissions -g
The -s argument is a short summary
Where can I get such a list?
You can't.
Where do I get a description for these permissions?
Wherever those permissions are documented. In many cases, they are undocumented and therefore should not be used.
For example, your first three were removed from Android a couple of years ago, IIRC. The last one is documented in the C2DM documentation.
There are definitely "more permissions out there". The reference you've linked is just the "official list" – and even for that, it's quite incomplete. I've researched for existing permissions, what they are for, and what impacts they have on the end-user, for about a year now – and really wonder how developers find what they need. Good guessing seems to be part of it, as for many permissions a Google search just yielded content of several apps' Manifest files ("uses …").
Added to that, next to the "official permissions" (or rather "Android core permissions"), each developer can define its own for his app (as Charlie Collins already pointed out in his answer).
During my research, I've setup a list with my findings from several sources (which I listed along) – adding any explanations I could find. This list is rather focused on the end-user, but still might prove helpful to developers. You can find it at my site: Android Permissions explained – bi-lingual (English and German). The list includes the "core permission" as well as some selected app-specific ones (mostly those one encounters more frequently: declared by Google apps, or popular apps like Tasker and K-9 Mail). Again, this of course is far from being complete – a "complete list" being as likely as a unicorn (the day published it most likely would be outdated already).
Edit:
As it was asked for in another comment: If you installed a package with a new permission not yet covered by any list, and you want to know the "technical name" of that new permission, you can retrieve that information from your device via ADB:
adb shell dumpsys package com.foo.bar
(of course replace com.foo.bar with the name of the package in question). In the output, skip down to the line grantedPermissions:. Below that come the permissions in "full notation", e.g. android.permission.INTERNET, one per line. To make that easier:
adb shell dumpsys package com.foo.bar |egrep -A99999 "grantedPermissions:"
You can get all permissions on a device using the following code:
public static List<PermissionInfo> getAllPermissions(Context context) {
PackageManager pm = context.getPackageManager();
List<PermissionInfo> permissions = new ArrayList<>();
List<PermissionGroupInfo> groupList = pm.getAllPermissionGroups(0);
groupList.add(null); // ungrouped permissions
for (PermissionGroupInfo permissionGroup : groupList) {
String name = permissionGroup == null ? null : permissionGroup.name;
try {
permissions.addAll(pm.queryPermissionsByGroup(name, 0));
} catch (PackageManager.NameNotFoundException ignored) {
}
}
return permissions;
}
I know this is a late post, but this is more of a reference for people in the future who have the same question.
Here is a list of every single built-in permission in Android 7.0 (Nougat). However, it is possible to create your own permissions, so that list doesn't contain all of them out there.
Hope that helps :)
It depends on the Android version. The reason is that starting from some Android version, Google noticed (or just allowed) that OEMs would be able to change which permission belongs to which permission group. This occurs at least for some Chinese OEMs (not the first time they break behavior, as shown here), according to what I was told by Google on the issue tracker. They can even change it between simple updates to the OS.
So, here's what you have today:
Starting from Android 12 (API 31), you can use the new getPlatformPermissionsForGroup function.
On Android versions older than Android 10 (API 29 and below), you could use queryPermissionsByGroup.
On Android 10-11 (API 29-30), here are the methods:
The normal API (and the adb command of ./adb shell pm list permissions -s) won't work properly. It will put plenty of permissions
into "UNDEFINED" group. The reason is that Google said it might be
different across devices and OEMs
You can check on Android source code of these versions and hope that most devices use what's there. It used to be here, but the link is
dead now. I think this one can give you the same information
though (but you need to check on which Android version it's used
for).
Another way to handle this is to make your own sample POC to check for each permission - which permission group it belongs to. You will do it by having all permissions declared in the manifest (get from the code below), and then request a bunch of permissions. If you get a single dialog, it means that what you've chosen belong to a single group, and you can continue testing more permissions into it and see if they belong too. If not, at least one of them belong to another group.
To filter by the permissions that are only in the system and/or of Android itself, you could use a condition that the package name of the permission has to start with "android" or that the permission group name should start with "android.permission-group." or that the protection level of the permission is PermissionInfo.PROTECTION_SIGNATURE . It depends on what you wish to filter by.
So, a simple function to list them for all Android versions:
enum class PermissionGroup constructor(#param:Permission #field:Permission val permissions: Array<String>) {
//based on https://developer.android.com/reference/android/Manifest.permission_group.html, https://developer.android.com/guide/topics/permissions/requesting.html https://developer.android.com/reference/android/Manifest.permission
// get all permissions and groups here: https://stackoverflow.com/a/51156191/878126 https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
CALENDAR(arrayOf(permission.READ_CALENDAR, permission.WRITE_CALENDAR)),
CAMERA(arrayOf(permission.CAMERA)),
CONTACTS(arrayOf(permission.READ_CONTACTS, permission.WRITE_CONTACTS, permission.GET_ACCOUNTS)),
LOCATION(sequenceOf(permission.ACCESS_COARSE_LOCATION, permission.ACCESS_FINE_LOCATION, if (VERSION.SDK_INT >= VERSION_CODES.Q) permission.ACCESS_BACKGROUND_LOCATION else null)
.filterNotNull().asIterable().toList().toTypedArray()),
MICROPHONE(arrayOf(permission.RECORD_AUDIO, "android.permission.RECORD_BACKGROUND_AUDIO")),
PHONE(sequenceOf(permission.READ_PHONE_STATE, if (VERSION.SDK_INT >= VERSION_CODES.P) permission.ACCEPT_HANDOVER else null,
permission.CALL_PHONE, permission.ADD_VOICEMAIL, permission.USE_SIP,
if (VERSION.SDK_INT >= VERSION_CODES.O) permission.ANSWER_PHONE_CALLS else null, if (VERSION.SDK_INT < VERSION_CODES.P) permission.READ_CALL_LOG else null,
if (VERSION.SDK_INT < VERSION_CODES.P) permission.WRITE_CALL_LOG else null, if (VERSION.SDK_INT < VERSION_CODES.P) permission.PROCESS_OUTGOING_CALLS else null,
if (VERSION.SDK_INT >= VERSION_CODES.O) permission.READ_PHONE_NUMBERS else null).filterNotNull().asIterable().toList().toTypedArray()),
SENSORS(sequenceOf(if (VERSION.SDK_INT >= VERSION_CODES.KITKAT_WATCH) permission.BODY_SENSORS else null,
if (VERSION.SDK_INT >= VERSION_CODES.M && VERSION.SDK_INT < VERSION_CODES.P) permission.USE_FINGERPRINT else null, if (VERSION.SDK_INT >= VERSION_CODES.P) permission.USE_BIOMETRIC else null)
.filterNotNull().asIterable().toList().toTypedArray()),
SMS(sequenceOf(permission.SEND_SMS, permission.RECEIVE_SMS, permission.READ_SMS, permission.RECEIVE_WAP_PUSH, permission.RECEIVE_MMS,"android.permission.READ_CELL_BROADCASTS")
.filterNotNull().asIterable().toList().toTypedArray()),
STORAGE(sequenceOf(permission.READ_EXTERNAL_STORAGE, permission.WRITE_EXTERNAL_STORAGE, if (VERSION.SDK_INT >= VERSION_CODES.Q) permission.ACCESS_MEDIA_LOCATION else null)
.filterNotNull().asIterable().toList().toTypedArray()),
CALL_LOG(if (VERSION.SDK_INT >= VERSION_CODES.P)
arrayOf(permission.READ_CALL_LOG, permission.WRITE_CALL_LOG, permission.PROCESS_OUTGOING_CALLS)
else emptyArray()),
ACTIVITY_RECOGNITION(if (VERSION.SDK_INT >= VERSION_CODES.Q) arrayOf(permission.ACTIVITY_RECOGNITION) else emptyArray()),
NEARBY_DEVICES(if (VERSION.SDK_INT >= VERSION_CODES.S) arrayOf(permission.BLUETOOTH_CONNECT, permission.BLUETOOTH_ADVERTISE, permission.UWB_RANGING, permission.BLUETOOTH_SCAN) else emptyArray())
;
#TargetApi(VERSION_CODES.S)
#StringDef(permission.READ_CALENDAR, permission.WRITE_CALENDAR, permission.CAMERA, permission.READ_CONTACTS, permission.WRITE_CONTACTS,
permission.GET_ACCOUNTS, permission.ACCEPT_HANDOVER, permission.ACCESS_COARSE_LOCATION, permission.ACCESS_FINE_LOCATION, permission.RECORD_AUDIO,
permission.USE_BIOMETRIC, permission.READ_PHONE_STATE, permission.CALL_PHONE, permission.READ_CALL_LOG, permission.WRITE_CALL_LOG, permission.ADD_VOICEMAIL,
permission.USE_SIP, permission.PROCESS_OUTGOING_CALLS, permission.BODY_SENSORS, permission.SEND_SMS, permission.RECEIVE_SMS, permission.READ_SMS, permission.RECEIVE_WAP_PUSH,
permission.RECEIVE_MMS, permission.READ_EXTERNAL_STORAGE, permission.WRITE_EXTERNAL_STORAGE, permission.ANSWER_PHONE_CALLS, permission.ACTIVITY_RECOGNITION,
permission.ACCESS_BACKGROUND_LOCATION, permission.ACCESS_MEDIA_LOCATION, "android.permission.RECORD_BACKGROUND_AUDIO",
permission.BLUETOOTH_CONNECT, permission.BLUETOOTH_ADVERTISE, permission.UWB_RANGING, permission.BLUETOOTH_SCAN,"android.permission.READ_CELL_BROADCASTS"
)
#Retention(AnnotationRetention.SOURCE)
annotation class Permission
}
And finding them:
fun checkPermissions() {
var permissionsCount = 0
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val permissionGroups = packageManager.getAllPermissionGroups(0)
var permissionsGroupsLeft = permissionGroups.size
permissionGroups.forEach { permissionGroup: PermissionGroupInfo ->
val permissionGroupName = permissionGroup.name
if (!permissionGroupName.startsWith("android.permission-group.")) {
if (--permissionsGroupsLeft == 0) {
Log.d("AppLog", "total permissions (of all permissions groups) count:$permissionsCount")
}
return#forEach
}
packageManager.getPlatformPermissionsForGroup(permissionGroupName, mainExecutor) { groupPermissions ->
if (groupPermissions.isNotEmpty()) {
Log.d("AppLog", "permissionGroup:$permissionGroupName")
groupPermissions.forEach { permissionName ->
Log.d("AppLog", "\t\t$permissionName")
++permissionsCount
}
}
if (--permissionsGroupsLeft == 0) {
Log.d("AppLog", "total permissions (of all permissions groups) count:$permissionsCount")
}
}
}
return
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
Log.d("AppLog", "cannot use API to query permissions, so guessing it is similar to what we have found about it:")
PermissionGroup.values().forEach { permissionGroup ->
val permissions = permissionGroup.permissions
if (permissions.isEmpty())
return#forEach
Log.d("AppLog", "permissionGroup:${permissionGroup.name}")
permissions.forEach { permissionName ->
Log.d("AppLog", "\t\t${permissionName}")
++permissionsCount
}
}
}
else -> {
val allPermissionGroups = packageManager.getAllPermissionGroups(0)
allPermissionGroups.forEach { permissionGroup ->
val permissionGroupName = permissionGroup.name
if (!permissionGroupName.startsWith("android.permission-group."))
return#forEach
val groupPermissions = packageManager.queryPermissionsByGroup(permissionGroupName, 0)
if (groupPermissions.isEmpty())
return#forEach
Log.d("AppLog", "permissionGroup:$permissionGroupName")
for (permission in groupPermissions) {
val permissionName = permission.name
Log.d("AppLog", "\t\t${permissionName}")
++permissionsCount
}
}
}
}
Log.d("AppLog", "total permissions (of all permissions groups) count:$permissionsCount")
}
A short answer without going in detail to get all permissions:
adb shell pm list permissions lists permissions that comes with
installed apps (false or true)
adb shell cmd appops get <package> lists permissions on
user level per app (allow, deny, ignore)
adb shell dumpsys <package> lists permissions per app on system
level (grant and revoke)

Categories

Resources