Android "permanent" superuser permission for an app? - android

To clarify, I use this code to get superuser permission for my app so I can access root and whatnot:
public String runProcess(String[] functs) {
DataOutputStream dos;
DataInputStream dis;
StringBuffer contents = new StringBuffer("");
String tempInput;
Process process;
try {
process = Runtime.getRuntime().exec(functs);
dos = new DataOutputStream(process.getOutputStream());
dis = new DataInputStream(process.getInputStream());
for (String command : functs) {
dos.writeBytes(command + "\n");
dos.flush();
while ((tempInput = dis.readLine()) != null)
contents.append(tempInput + "\n");
}
dos.writeBytes("exit\n");
dos.flush();
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
return contents.toString();
}
And although it works just fine, whenever I call runProcess(new String[] { "su", "-c", "some other command" }); it always asks for superuser permission. I see a lot of root apps on the market who just have to gain superuser permission once at each startup of the app, but I don't think I'd need to ask the user for superuser permission every single time the app calls an function that requires SU. So my question would be, how would I prompt the user to give me SU permission once at the startup of an app without having to continually ask for it for every SU-related action?
EDIT: I know I could run my method/the Runtime.getRuntime().exec() method without typing "su" in it every time but that only works with non-su related actions (i.e. exec("ps") or exec("ls"). Any ideas?

You can use my Library which does this.
https://code.google.com/p/roottools/
Also, if you don't want to use the library the source is available so you can just rip out my code and use it in your application.
Here is a link to the source:
https://code.google.com/p/roottools/source/browse/#svn%2Ftrunk%2FStable%2FRootTools-sdk3-generic%2Fsrc%2Fcom%2Fstericson%2FRootTools

If you are just looking for the permission from a "superUser" app which is already running in your device, you just need the following code in your main java file.
try {
process p= Runtime.getRuntime().exec(su);
}
catch (IOException e) {
e.printStackTrace();
}
Yes, no need to mention that the device has to be already rooted!!!

Every time you open a console asking for root access, i.e. start it with su, the corresponding super user app will either prompt you or allow/deny it, if you checked something like "Don't ask me again" on the previous prompt.
If you only want to have ask (the super user app) once, you will have to keep your root console open, by not calling dos.writeBytes("exit\n");.
Then keep this session in a background thread and use it when necessary.
So either make sure the user checks "Don't ask me again" on the first prompt or keep the session open.

Related

Android app update automatic and silently?

I develop an app and want update itself and want following fetures, device have been rooted :
1 automatic check can update every start (I can do)
2 download the apk file to local (I can do)
3 update with custom dialog, or update silently (I dont know )
edit:
My app run on TV with remote, the default dialog which can control but perfect , so I want use my dialog if there must a dialog.Its best if need not a dialog.
First declare this variables, then call function wherever you want. Then grant superuser, on your superuser application, check the option to always grant, for non user interaction.
#Override
public void onCreate() {
super.onCreate();
//some code...
final String libs = "LD_LIBRARY_PATH=/vendor/lib:/system/lib ";
final String commands = libs + "pm install -r " + "your apk directory"+ "app.apk";
instalarApk(commands);
}
private void instalarApk( String commands ) {
try {
Process p = Runtime.getRuntime().exec( "su" );
InputStream es = p.getErrorStream();
DataOutputStream os = new DataOutputStream(p.getOutputStream());
os.writeBytes(commands + "\n");
os.writeBytes("exit\n");
os.flush();
int read;
byte[] buffer = new byte[4096];
String output = new String();
while ((read = es.read(buffer)) > 0) {
output += new String(buffer, 0, read);
}
p.waitFor();
} catch (IOException e) {
Log.v(Debug.TAG, e.toString());
} catch (InterruptedException e) {
Log.v(Debug.TAG, e.toString());
}
}
The regular way (without root and a default installer dialog) is described in another question, and should be used in most cases imho, as I dislike requesting root privileges for a update feature.
There is no difference in providing a custom dialog and installing an apk silently, as both technically are silent installs (e.g. not made by the install activity). With root privileges, you could use a root shell and either replace the apk (as in the open-source keybord manager app) or invoke the package manager from shell. I'd suggest you go for the second way, I linked the keybord manager app source mainly for the root shell creation stuff.
The Android Framework make it defficult to update silently, on custom devices you must call system install service for your apk file, and it will show the install dialog for the user, but if the device is rooted, I think you can make that silently.

Power off Android device with system signed application

I am developing an Android application and we need to power off the device under certain circumstances.
I have read in many places that you need a rooted phone in order to do so. Then, you can issue the "reboot" command by using Java's API:
try {
Process proc = Runtime.getRuntime()
.exec(new String[]{ "su", "-c", "reboot -p" });
proc.waitFor();
} catch (Exception ex) {
ex.printStackTrace();
}
I have actually tried this in a Cyanogenmod 10 device (Samsung Galaxy S3), and it works. However, we do not want a rooted device in order to power it off, since the end user will then be able to do unintended things which are not allowed by our company.
On the other hand, our application is signed by the manufacturer's certificate, in this case Cyanogen's. I have read that by signing your application with the manufacturer's certificate, you should be able to issue privileged commands (as if root). However, even if I install my app as a system app signed with the manufacturer's certificate, the above code does not work:
If I leave the "su" part of the command, the "Superuser Request" screen is displayed, but that's something we are trying to avoid.
If I remove the "su" part (just leaving "reboot -p"), the command is silently ignored.
As a result, we are not being able to poweroff our device with our system app, which is signed with the manifacturer's certificate. So my question is, how am I supposed to do that?
EDITED
And, by the way, just in case someone is not sure about it: the application is properly signed and installed as a system application, because we can actually access some restricted APIs, such as PowerManager.goToSleep()
If you want the device to reboot (power off and on), then try PowerManager.reboot()
PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
powerManager.reboot(null);
android.os.PowerManager:
/**
* Reboot the device. Will not return if the reboot is successful.
* <p>
* Requires the {#link android.Manifest.permission#REBOOT} permission.
* </p>
*
* #param reason code to pass to the kernel (e.g., "recovery") to
* request special boot modes, or null.
*/
public void reboot(String reason) {
try {
mService.reboot(false, reason, true);
} catch (RemoteException e) {
}
}
UPDATE
If you want the device to completely turn off, use PowerManagerService.shutdown():
IPowerManager powerManager = IPowerManager.Stub.asInterface(
ServiceManager.getService(Context.POWER_SERVICE));
try {
powerManager.shutdown(false, false);
} catch (RemoteException e) {
}
com.android.server.power.PowerManagerService:
/**
* Shuts down the device.
*
* #param confirm If true, shows a shutdown confirmation dialog.
* #param wait If true, this call waits for the shutdown to complete and does not return.
*/
#Override // Binder call
public void shutdown(boolean confirm, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(true, confirm, null, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
This was working fine for me:
startActivity(new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN"));
you need this permission ( depends on being system-app ):
<uses-permission android:name="android.permission.SHUTDOWN"/>
source:
https://github.com/sas101/shutdown-android-app/wiki
OK, my mistake.
As I performed some tests, I did not realize that I had removed "android:sharedUserId="android.uid.system" from the manifest.
Once the sharedUserId is included, the following code works without prompting the user to confirm root access:
try {
Process proc = Runtime.getRuntime()
.exec(new String[]{ "su", "-c", "reboot -p" });
proc.waitFor();
} catch (Exception ex) {
ex.printStackTrace();
}
I tried to remove "su" (because the system may not provide such a command), but in that case it does not work. Surprisingly, the file system is remounted in read-only mode, so I must remount it again with write permissions.
this is for kotlin
(requireContext().getSystemService(Context.POWER_SERVICE) as PowerManager)
.reboot("reason")

Android executing SU commands in background?

I'm writing an android app that sets the max frequency, governor etc.. when the screen turns off. To do it i have a service running that receives screen on/off broadcast intents. When the screen off event fires, I read from the shared preferences and set whatever is set by the user with this function
public static void writeFile(String file, String content) {
try {
Process suProcess = Runtime.getRuntime().exec("su");
DataOutputStream out = new DataOutputStream(suProcess.getOutputStream());
out.writeBytes("echo '" + content + "' > '" + file + "'");
out.flush();
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
Then when the screen turns back on, i revert the system to its previous state by rewriting the files. Everything is working nicely, working as intended.
The problem is i'm noticing some lag when turning the screen on/off. Also when i turn the screen on, i see the toast message from SuperUser "App was granted su access", and it pops up once for every command. Is there a way to hide that toast message? I haven't found any way to hide a toast message from another activity. I know they can be disabled in the superuser app, but that's not ideal. I read you can write your own superuser binary but that sounds alot more complicated than simple java programming... also sounds like it could lead to security problems.
Basically i'm asking what's the best way to do this, so that it's as non-invasive to the user as possible?
I haven't used su, but I think if you don't close the stream every time it should only display toast once.

Is it possible to call getevent from an Android service?

Is is possible to run getevent from an Android service and get output similar to what you see when running adb to call getevent from a command prompt on a development machine? When I try something like:
ProcessBuilder builder = new ProcessBuilder()
.command("getevent")
.redirectErrorStream(true)
.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(builder.getInputStream()));
...
the output I get for each device looks like:
could not open /dev/input/event[n], Permission denied
Is it just not possible to access low level information like this because of Android's security protections? Would it be possible on a "rooted" device?
Why I am trying to do this:
I would like to record a user's actions (touch and gesture events) on an Android device for the purpose of usability testing. An accessibility service seems to be the way to go, but the information is not detailed enough. For a swipe gesture, for example, I cannot get the screen coordinates of where the user swiped. I was thinking that getting the low-level input from the touch screen might let me get more detailed information. Maybe there is a better way to do this?
(I'm a newbie in the Android world. This kind of thing is easy on Windows.)
You can do like this.
th = new Thread(new Runnable(){
private Process exec;
#Override
public void run() {
try {
exec = Runtime.getRuntime().exec(new String[]{"su","-c","getevent -t " + device});
InputStreamReader is = new InputStreamReader(
exec.getInputStream());
String s;
BufferedReader br = new BufferedReader(is);
while(((s = br.readLine()) != null) && run){
...
}
is.close();
exec.destroy();
} catch (IOException e) {
e.printStackTrace();
}
}
You must use 'su' to get the root permission, but by this way you can't get the real time event, because there is a buffer size of 4k, you could get data only after contained 4k data.
Search for UIAutomator. This does what you want to do.
Your phone must be rooted to execute getevent/sendevent command.
One way is to install any terminal emulator from play store like Qute: Command Console & Terminal Emulator.
In terminal enter following:
1) su (it'll gain the root access required for getevent)
2) getevent (or getevent -c 8 to output only 8 lines else it would flood the terminal)

Working with capacitive buttons in Android

I was curious if there is any library to work with the capacitive buttons of Samsung phones??
I mean to light them up when an event occurs, or blink them, stuffs like that...
Thanks,
rohitkg
There is nothing in the Android SDK for this, as there is no assumption that such buttons exist, have backlights, etc. You are welcome to contact device manufacturers to see if they have a documented and supported means of doing this for their specific devices.
Here's a code snippet I grabbed from samsung-moment-notifications.
Process process = null;
DataOutputStream os = null;
try {
// get root
process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());
// write the command
os.writeBytes("echo 100 > /sys/class/leds/button-backlight/brightness\n");
os.writeBytes("exit\n");
// clear the buffer
os.flush();
Toast.makeText(NotificationLights.this, "Lights are on", Toast.LENGTH_SHORT).show();
// wait for complete
process.waitFor();
// won't catch an error with root, but it has to have an exception catcher to execute
} catch (Exception e) {
Toast.makeText(NotificationLights.this, "Couldn't get SU, are you rooted?", Toast.LENGTH_SHORT).show();
return;
}
1- You must have a rooted device.
2- You must know the location of the script which turns the lights on/off for each device.
/sys/class/leds/button-backlight/brightness is specific to the Samsung Moment.
If you were to try it on another device it wouldn't work.

Categories

Resources