How do I get the build.prop values that are found in /system/build.prop without root access? How do I edit them?
You can probably consider using SystemProperties.get("someKey") as suggested by #kangear in your application using reflection like:
public String getSystemProperty(String key) {
String value = null;
try {
value = (String) Class.forName("android.os.SystemProperties")
.getMethod("get", String.class).invoke(null, key);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
And then you can use it any where like:
getSystemProperty("someKey");
Try This
static String GetFromBuildProp(String PropKey) {
Process p;
String propvalue = "";
try {
p = new ProcessBuilder("/system/bin/getprop", PropKey).redirectErrorStream(true).start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
propvalue = line;
}
p.destroy();
} catch (IOException e) {
e.printStackTrace();
}
return propvalue;
}
Does System.getProperty() help? As an alternative, you can execute getprop in a Process and retrieve its output.
Such as:
SystemProperties.get("ro.rksdk.version")
use android.os.Build class, see http://developer.android.com/reference/android/os/Build.html, but you can not edit it without root access.
I have checked multiple devices including some Samsung and LG devices as well as a Nexus 4, latest one was the Nvidia Shield Tablet with Android 6.0.
On all devices ll on /system/build.prop gave me this result(of course with varying size and date of build.prop):
-rw-r--r-- root root 3069 2015-10-13 21:48 build.prop
This means that anyone and any app without any permissions can read the file. Root would only be required for writing the non "ro."-values. You could just create a new BufferedReader(new FileReader("/system/build.prop")) and read all lines.
Advantages of this approach:
no need for reflection (SystemProperties.get)
no need to spawn a Process and executing getprop
Disadvantages:
does not contain all system properties (some values e.g. are set at boot only available at runtime)
not handy for getting a specific value compared to SystemProperties.get
On the setting page of your file manager, set home as /system, then you could browse system folders and copy build.prop and paste to sdcard. I'm still trying to root my phone but I have no problem tweaking on the way (no pun).
To read properties using reflection on the hidden API :
static public String getprop(String key){
try { Class c = Class.forName("android.os.SystemProperties");
try { Method method = c.getDeclaredMethod("get", String.class);
try { return (String) method.invoke(null, key);
} catch (IllegalAccessException e) {e.printStackTrace();}
catch (InvocationTargetException e) {e.printStackTrace();}
} catch (NoSuchMethodException e) {e.printStackTrace();}
} catch (ClassNotFoundException e) {e.printStackTrace();}
return null;
}
To edit them (Root required) manually, you should extract them with adb :
adb pull /system/build.prop
Edit them on the computer, then "install" the new build.prop :
adb push build.prop /sdcard/
adb shell
mount -o rw,remount -t rootfs /system
cp /sdcard/build.prop /system/
chmod 644 /system/build.prop
Would be safer to keep an original build.prop copy.
Related
I want to put global time zone programatically in Android. The ADB way is like this:
adb shell settings put global time_zone Europe/Stockholm
When I get the time zone it works fine:
adb shell settings get global time_zone
The problem is when I want to do this in Android Studio:
public void setTimeZone(){
try {
Runtime.getRuntime().exec("settings put global time_zone Europe/Stockholm");
}catch (IOException e) {
e.printStackTrace();
}
}
There is no error but the time zone is not set.
Any suggestions please? Thank you.
Why are you trying to change it via adb shell? Try this:
AlarmManager am = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
am.setTimeZone("Europe/Stockholm");
You will need to add this permission to your Androidmanifest.xml
<uses-permission android:name="android.permission.SET_TIME_ZONE"/>
I hope this helps you.
With a rooted phone you can try this:
try {
Process su = Runtime.getRuntime().exec("su");
DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());
outputStream.writeBytes("settings put global time_zone Europe/Stockholm\n");
outputStream.flush();
outputStream.writeBytes("exit\n");
outputStream.flush();
su.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
UPDATE There are a number of other posts asking how to get a Screenshot in android but none seemed to have a full answer of how to do so. Originally I posted this as a question due to a particular issue I was running into while attempting to open a stream to the Frame Buffer. Now I've swapped over to dumping the Frame Buffer to a file so I've updated my post to show how I got there. For reference (and acknowledgement), I found the command to send the FrameBuffer to a file from this post (unfortunately he didn't provide how he got to that point). I'm just missing how to turn the raw data I pulled from the Frame Buffer into an actual image file.
My intention was to take a full dump of the actual screen on an Android Device. The only way I could find to do so without using the adb bridge was to directly access the Frame Buffer of the system. Obviously this approach will require root privileges on the device and for the app running it! Fortunately for my purposes I have control over how the Device is set up and having the device rooted with root privileges provided to my application is feasible. My testing is currently being done on an old Droid running 2.2.3.
I found my first hints of how to approach it from https://stackoverflow.com/a/6970338/1446554. After a bit more research I found another article that describes how to properly run shell commands as root. They were using it to execute a reboot, I use it to send the current frame buffer to an actual file. My current testing has only gotten as far as doing this via ADB and in a basic Activity (each being provided root). I will be doing further testing from a Service running in the background, updates to come! Here is my entire test activity that can export the current screen to a file:
public class ScreenshotterActivity extends Activity {
public static final String TAG = "ScreenShotter";
private Button _SSButton;
private PullScreenAsyncTask _Puller;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
_SSButton = (Button)findViewById(R.id.main_screenshotButton);
_SSButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (_Puller != null)
return;
//TODO: Verify that external storage is available! Could always use internal instead...
_Puller = new PullScreenAsyncTask();
_Puller.execute((Void[])null);
}
});
}
private void runSuShellCommand(String cmd) {
Runtime runtime = Runtime.getRuntime();
Process proc = null;
OutputStreamWriter osw = null;
StringBuilder sbstdOut = new StringBuilder();
StringBuilder sbstdErr = new StringBuilder();
try { // Run Script
proc = runtime.exec("su");
osw = new OutputStreamWriter(proc.getOutputStream());
osw.write(cmd);
osw.flush();
osw.close();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (osw != null) {
try {
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
try {
if (proc != null)
proc.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
sbstdOut.append(readBufferedReader(new InputStreamReader(proc.getInputStream())));
sbstdErr.append(readBufferedReader(new InputStreamReader(proc.getErrorStream())));
}
private String readBufferedReader(InputStreamReader input) {
BufferedReader reader = new BufferedReader(input);
StringBuilder found = new StringBuilder();
String currLine = null;
String sep = System.getProperty("line.separator");
try {
// Read it all in, line by line.
while ((currLine = reader.readLine()) != null) {
found.append(currLine);
found.append(sep);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
class PullScreenAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
File ssDir = new File(Environment.getExternalStorageDirectory(), "/screenshots");
if (ssDir.exists() == false) {
Log.i(TAG, "Screenshot directory doesn't already exist, creating...");
if (ssDir.mkdirs() == false) {
//TODO: We're kinda screwed... what can be done?
Log.w(TAG, "Failed to create directory structure necessary to work with screenshots!");
return null;
}
}
File ss = new File(ssDir, "ss.raw");
if (ss.exists() == true) {
ss.delete();
Log.i(TAG, "Deleted old Screenshot file.");
}
String cmd = "/system/bin/cat /dev/graphics/fb0 > "+ ss.getAbsolutePath();
runSuShellCommand(cmd);
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
_Puller = null;
}
}
}
This also requires adding the android.permission.WRITE_EXTERNAL_STORAGE permission to the Manifest. As suggested in this post. Otherwise it runs, doesn't complain, doesn't create the directories nor the file.
Originally I couldn't get usable data from the Frame Buffer due to not understanding how to properly run shell commands. Now that I've swapped to using the streams for executing commands I can use '>' to send the Frame Buffer's current data to an actual file...
Programmatically you can run "adb shell /system/bin/screencap -p /sdcard/img.png" as below :
Process sh = Runtime.getRuntime().exec("su", null,null);
OutputStream os = sh.getOutputStream();
os.write(("/system/bin/screencap -p " + "/sdcard/img.png").getBytes("ASCII"));
os.flush();
os.close();
sh.waitFor();
An easy solution for ICS devices is to use the following from the command line
adb shell /system/bin/screencap -p /sdcard/screenshot.png
adb pull /sdcard/screenshot.png screenshot.png
This'll save the screenshot.png file in the current directory.
Tested on a Samsung Galaxy SII running 4.0.3.
That would be different for different phones. It depends on the underlying graphics format of your device. You can poll what the graphics format is using system calls. If you are only going to run this on devices that you know the graphics format of you can write a converter that turns it into a known format.
You can have a look at the following project: http://code.google.com/p/android-fb2png/
If you look at the source code for fb2png.c you can see that they poll FBIOGET_VSCREENINFO which contains info about how the device stores the screen image in memory. Once you know that, you should be able to convert it into a format you can use.
I hope this helps.
I want to display application logs.
On terminal I used this command: adb logcat -s brief *:V|grep "pid"
It's display My Application logs.
pid means application pid which is display in logcat table.
public static String logProc()
{
String value = "";
try
{
String cmd[] = {"logcat","-s","brief","*:V","|","grep",
android.os.Process.myPid()+""};
Process p = Runtime.getRuntime().exec(cmd,null, null);
BufferedReader reader = new BufferedReader(new
InputStreamReader(p.getInputStream()));
String line = reader.readLine();
while (line != null)
{
value += line + "\n";
line = reader.readLine();
}
p.waitFor();
}
catch (IOException e1)
{
e1.printStackTrace();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return value;
}
Most official Android builds do not come with grep (Edit: more recent releases now do)
You can install busybox if you want extra commands - without root you would have to put it in an alternate location.
You have the additional problem that you are trying to exec() a shell command to connect two programs via pipes, which isn't going to work unless you exec a shell interpreter and give it that command. Or you could set up the pipe yourself and exec both programs.
But since you are writing a program, it would probably be simpler to do your pattern matching in the java code.
For the purposes of monitoring Battery usage etc. I have code that executes a few dumpsys calls, reads and parses the output to extract data that I am interested in.
dumpsys battery, dumpsys statusbar, and dumpsys power all give me an error message for output like "Permission Denial: can't dump Battery service from pid..."
Also, when the application is launched there is an item in the log tagged with "PackageManager" statingNot granting permission android.permissionDUMP to package.... (protectionLevel = 3 ...)"
However, dumpsys cpuinfo and dumpsys netstat work and give me the correct output, which seems to be inconsistent.
I am able to generate dumpsys battery and the like from the adb shell, but when I try to call it programmatically it does not work.
I have tried running this on a HTC Nexus One phone as well as the emulator and get the same results for each. The weird thing is that this code worked on my Nexus One a day ago (before I upgraded from 2.2 to 2.3), and now it does not. Is this because of the upgrade?
An example of the code I am trying to run is as follows:
String command = "dumpsys battery";
try {
String s = null;
Process process = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(process.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(process.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
How do I get the dumpsys to give me the correct output programmatically and how to I get the dump permission to be granted?
*The Nexus One is not rooted and I would like to get this working without having to root it for the purposes of my project
Thank you for your help
Regular applications cannot get the DUMP permission. It is reserved to system applications.
android.permission.Dump is protected by system, signature, and development permission protection levels. Line 1993 of the source shows you this. If your APK is signed with the framework cert, is in the priv-app directory, or debuggable (see below) you can use the pm service to grant the permission, but otherwise the code specifically prevents what you're asking for (line 2624 of source).
Debuggable APKs can be created through setting the debuggable attribute on a buildType via build.gradle. Sample Android DSL:
android {
...
buildTypes {
debug {
debuggable true
...
}
quality_assurance {
debuggable true
}
...
}
If your handset had been rooted, 'dumpsys activity' will work on Android2.3:
private static void dumpIT0(String sCmd) {
try {
String s = null;
String command = "su -c " + sCmd;
Process process = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(
process.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(
process.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (IOException e) {
Log.e(TAG, "IOException: " + e);
}
}
sCmd = "dumpsys activity";
try {
Runtime rt = Runtime.getRuntime();
Process pcs = rt.exec("ls -l /data");
BufferedReader br = new BufferedReader(new InputStreamReader(pcs
.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
Log.e("line","line="+line);
}
br.close();
pcs.waitFor();
int ret = pcs.exitValue();
Log.e("ret","ret="+ret);
} catch (Exception e) {
Log.e("Exception", "Exception", e);
}
only print "ret=0",How to print the correct path?
Android protects it's internal directories. You can only access your directory under /data/data/your_package. I believe that the normal user does not have Read privileges for the /data directory on a normal device.
data folder is inaccessible on a device except by system processes. You cannot access data folder of a unrooted phone through adb. You can access data folder of emulator or rooted phones.
Did you try doing it with your own app, and not by spawning another process (e.g. Runtime.exec())
File dataDir = new File("/data");
String[] files = dataDir.list();
for (int i = 0 ; i < files.length ; i++ ) {
Log.d(TAG, "File: "+files[i]);
}
Also, I'd look at the different read permissions, maybe there's another way to get to the data you're looking for via ContentProviders.
If you'll want to access /data folder not from java code, but from your PC console - you can use a adb shell command. it has no restrictions.
remember to have an emulator running, or connect your phone via USB before running that