Remove Permissions at runtime - android

I am trying to make a form where people can toggle notifications on and off. I figured the easiest way to do that would be set the permissions to allow or deny but I can't figure out how to remove the permission once it has been granted.
I am triggering the initial permission request by doing the following in android and not too sure what I will do with iOS as it requests the permissions somewhat automatically.
string rec = "android.c2dm.intent.RECEIVE";
string reg = "android.c2dm.intent.REGISTRATION";
ActivityCompat.RequestPermissions(Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity, new string[] { rec, reg },0);
I essentially would like a page that has a few Switch controls to enable/disable permissions.
any help would be greatly appreciated.
Thanks,

There's no built in method for you to toggle a permission (ie, allow, then disallow), but you could do it if your app can run an adb command.
To undo a permission:
adb shell pm revoke <package_name> <permission_name>
https://stackoverflow.com/a/32683390/6668797
To run an adb command within your app, a couple of variations, but all involve:
Process process = Runtime.getRuntime().exec("your command")
how to run adb shell commands from android code?
Is it possible to execute adb commands through my android app?

Related

Device owner not being cleared on Android M

I wrote a device owner kiosk app that I'd like to remove the device owner status on so I can uninstall it without having to factory reset the device. The following works on Nougat and Oreo, but not Marshmallow for Samsung tablets.
The specifics of how I'm coding the device owner stuff:
To set the app as device owner, I am running this adb shell command after installing the app:
adb shell dpm set-device-owner com.dps.myapp/.DeviceAdminReceiver
Then when I am trying to remove device owner status and uninstall the app, I am running these shell commands:
adb shell am force-stop com.dps.myapp
adb shell am start -n com.dps.myapp/.DeactivateDeviceOwnerActivity
adb shell pm uninstall com.dps.myapp
DeactivateDeviceOwnerActivity is an Activity in my app that contains the following code to clear the device owner status:
DevicePolicyManager mDevicePolicyManager = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
mDevicePolicyManager.clearDeviceOwnerApp(getApplicationContext().getPackageName());
if (mDevicePolicyManager.isDeviceOwnerApp(getApplicationContext().getPackageName())) {
Toast.makeText(getApplicationContext(),
"Failure! App is still device owner.",Toast.LENGTH_LONG)
.show();
}
else {
Toast.makeText(getApplicationContext(),
"Success!", Toast.LENGTH_LONG).show();
}
What is so weird is that my Activity is displaying the Toast that the clearDeviceOwnerApp call worked, but when I run the uninstall command immediately after, I get the "Failure [DELETE_FAILED_DEVICE_POLICY_MANAGER]" return from it, so obviously the device owner was not cleared for my app.
Does anyone know of any specific differences between Marshmallow and subsequent APIs, regarding device ownership or DevicePolicyManager that would cause this code, that works on Nougat and Oreo, to not work on Marshmallow? When I issue the start command to have DeactivateDeviceOwnerActivity clear the device owner, I'm looking in the system log and I'm not seeing anything that indicates any exceptions occurring. Any help would be appreciated.
I have not faced such an issue on Marshmallow.
This is strange, although I can't give an answer, I will suggest something
1) This might be a bug. So, you can factory reset device and try again.
2) It is very convenient to use the emulator for this type of testing as you can easily just delete and create a new one.
I hope it helps.

Getting battery stats of all apps in android

I am working on a battery monitoring app in which I have to show battery usage for all apps. After a lot of googling I found there a only way to do so is using command line
$ adb shell dumpsys batterystats --charged --checkin
The above command will provide all battery stats but I don't know how can I get this data in my code?
Please help!
Following code to show Summary of all apps battery usage, So you can try this.
Intent sample = new Intent("android.intent.action.POWER_USAGE_SUMMARY");
startActivity(sample);
You can grab dumpsys information on the device, but it does require permissions which are not granted to regular applications.
The shell-user has permission to run the command however - if you're running an on-device test using Instrumentation you can use Instrumentation.getUiAutomation().executeShellCommand(...) to execute the command as the shell user.

Android M: Programmatically revoke permissions

I am currently playing around with android m's new permission system.
What i am planning is to add a screen to my in-app settings where the user can grant or revoke permissions.
The screen would look like the regular system settings screen, but will have additional information why my app needs the specific permission. This settings screen would be an addition to the regular permission handling as suggested in the Documentation.
The workflow would be:
granting permission: open the systems dialog to grant/revoke (like suggested here)
revoking permission: revoke it programmatically
So my question is, can permissions be revoked programatically?
I searched a lot, but didn't manage to get some results.
You can't do anything (at least until now). In addition, there isn't any intent action to open the activity system settings for your app. My suggestion is to open a "feature request" on the developer preview issue tracker.
You can revoke permission from ADB Shell.
if you consider writing shell script and doing all this under programatically then YES, else NO
Grant and revoke permissions
You can use new ADB package manager (pm) commands to grant and revoke permissions to an installed app. This functionality can be useful for automated testing.
To grant a permission, use the package manager's grant command:
$ adb shell pm grant <package_name> <permission_name>
For example, to grant the com.example.myapp package permission to record audio, use this command:
$ adb shell pm grant com.example.myapp android.permission.RECORD_AUDIO
To revoke a permission, use the package manager's revoke command:
$ adb shell pm revoke <package_name> <permission_name>
Starting API 33 (Android 13) you can programmatically revoke previously granted runtime permissions via the revokeSelfPermissionOnKill APIs. E.g.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
context.revokeSelfPermissionOnKill(Manifest.permission.POST_NOTIFICATIONS)
}
Triggers the asynchronous revocation of a runtime permission. If the
permission is not currently granted, nothing happens (even if later
granted by the user).
There is also a function which takes a collection of multiple permissions to revoke.
Be sure to also put a version code guard around this as there currently doesn't seem to be a warning in the IDE. Unfortunately this hasn't been added to ContextCompat yet.
No Programmatically it is not possible in Android M Preview with new permissions Model.
But Manually you can do as given.
revoke permissions manually
for some special permission like SYSTEM_ALERT_WINDOW.
you need this :
adb shell appops set <package_name> SYSTEM_ALERT_WINDOW allow

Programmatically enable Mock Locations

Is there any possible way to enable mock locations on Android without having to do it through the settings app? I would like to try and turn on Mock Locations directly from my app. So I was wondering if there is an API for that or if there was some sort of Intent I could use.
Prior to Marshmallow, "allow mock locations" setting could be changed programmatically (but it requires root):
Settings.Secure.putInt(getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 1);
So, unfortunately, the best you can do is point the user to the actual screen where the mock location app is set using the code below:
startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS));
There is no way to do that "programmatically" unless the device is rooted.
Process proc = Runtime.getRuntime().exec(new String[]{"su","pm grant YOUR_APP_PACKAGE_NAME android.permission.WRITE_SECURE_SETTINGS", "settings put secure mock_location 1"});
proc.waitFor();
int value = Settings.Secure.getInt(getContentResolver(),
Settings.Secure.ALLOW_MOCK_LOCATION);
SOP.OUT("mock_location::::::::::::::::::::::::::::::::: " + value);
works only on rooted device
On Android 6+ you can run shell command appops to allow certain app to mock locations:
adb shell appops set <PACKAGE> android:mock_location allow
For example:
adb shell appops set ru.gavrikov.mocklocations android:mock_location allow
I'm not a developer and not sure that you can do this from within your app, but I guess running Runtime.getRuntime().exec(cmd) with root privelege would work.

Android regular user login loses group information when su to another user in an ssh session

What I'm doing:
I've built GNU emacs for native use on an phone.
I run emacs in daemon mode on the phone, so I connect to it anytime with emacsclient, to continue working with regular files, run processes, etc.
When logging in from the terminal on the phone, I'm currently user 10157, everything works:
$ id
uid=10157(10157) gid=10157(10157)
groups=10157(10157),1015(1015),1023(1023),1028(1028),3003(3003)
When I connect via ssh to the phone from a PC (I use DigiSSHd on the phone), it logs me in as a regular user 10282, everything works:
$ id
uid=10282 gid=10282 groups=1015(1015),1023(1023),1028(1028),3003(3003)
Emacs runs fine etc. However, this way I can't connect via emacsclient to the emacs process running under user 10157. This is desirable, since I don't want to start two emacs processes, since I want to continue working with files that I have open in emacs under user 10157.
Therefore:
$ su - 10157
Fine, I can run emacs etc. However, I cannot access the web.
$ ping -c1 google.com
You must have internet permissions to use ping. Aborting.
$ id
uid=10157(10157) gid=10157(10157) groups=10157(10157)
Thus I'm no longer in group 3003, necessary for internet access, besides other groups also.
Why does this group info get stripped, and how can I remedy this, so I can continue accessing the web when su as this user under ssh?
When i run the command:
busybox --list
I don't see su in the list.
su --help
shows Superuser.apk in the help text. It means su is provided by Superuser app.
I followed the steps described by you and i could su as another user and still have internet permission as shown below.
I have the following apps installed.
BusyBox v1.18.5-Stericson
Superuser v3.0.7
Terminal Emulator v1.0.45
SSHDroid v1.9.6
Suggestion:
I think the issue is with su on your device. You may try this one.
https://play.google.com/store/apps/details?id=com.noshufou.android.su
If i just use adb shell without running SSHDroid still i can su as another user with internet permission.
Note: The BusyBox id command doesn't show groups information always.
According to the standard man page for su (from a linux box)
When - is used, it must be specified as the last su option. The other forms (-l and --login) do not have this restriction.
Based on that, try
$ su 10157 -
I'm probably missing something here because this seems way too obvious but why not just 'sudo -u 10157' your emacs program?
you'd still have access to the net and your emacs would be working. or did I miss something important?
Permissions are not environment variables that can be inherited via su -.
Moreover, gid are are hard coded and their associations with each APP uid cannot be changed after installation.
10157 should be the uid of the DigiSSHd application, thus you could try to rebuild it after changing the AndroidManifest.xml to require the proper permission.
You can find something useful here and here.
The same should work for BusyBox (see here).
However, you could open some security hole by enabling NETWORK access through such applications.

Categories

Resources