Is there any way to write and read text files on rooted Android phone in root directories (ex. /data/)?
InputStream instream = openFileInput("/data/somefile");
doesn't work
You can only access to /data folder is you're root user.
Call to SU binary and write bytes (these bytes are the command) over SU binary via OutputStream and read command output via InputStream, it's easy:
Call to cat command to read files.
try {
Process process = Runtime.getRuntime().exec("su");
InputStream in = process.getInputStream();
OutputStream out = process.getOutputStream();
String cmd = "cat /data/someFile";
out.write(cmd.getBytes());
out.flush();
out.close();
byte[] buffer = new byte[1024 * 12]; //Able to read up to 12 KB (12288 bytes)
int length = in.read(buffer);
String content = new String(buffer, 0, length);
//Wait until reading finishes
process.waitFor();
//Do your stuff here with "content" string
//The "content" String has the content of /data/someFile
} catch (IOException e) {
Log.e(TAG, "IOException, " + e.getMessage());
} catch (InterruptedException e) {
Log.e(TAG, "InterruptedException, " + e.getMessage());
}
Don't use OutputStream for write files, OutputStream is used for execute commands inside SU binary, and InputStream is used for get output of command.
To be able to do what you are asking you must do all of the operations via the SU binary.
like...
try {
Process process = Runtime.getRuntime().exec("su");
process.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
Reading will be easier then writing, for writing easiest would be to write the file to some place where u have access using standard java api's and then move it to the new location using the su binary.
Related
I want to write a file on "/data" directory. I have rooted my device and setenforce 0. However, I am getting:
W/System.err: java.io.FileNotFoundException: data/MyDoople.txt
(Permission denied)
Here is my code (it works for sdcard):
String filename= "MyDoople.txt";
try
{
File f = new File("data/"+File.separator+filename);
FileOutputStream fOut = new FileOutputStream(f);
OutputStreamWriter myOutWriter = new OutputStreamWriter(
fOut);
myOutWriter.append("Mytest");
myOutWriter.close();
fOut.close();
}
catch(Exception e)
{
e.printStackTrace();
}
Do I have to add any policy to make it work?
Because the permission of the data directory is rwxrwx--x, user system, group system, and the running user of your app is a common user, not a system user, so the app unable to read and write the /data directory directly.
Two ways can be referred to:
1: If you have a platform certificate, declare android:sharedUserId="android.uid.system" in AndroidManifest.xml, and use the platform certificate to re-sign the app. In this way, the user running your app is the system user, who has read and write permissions to the /data partition.
2: obtain the root permission in the app, and then execute the relevant command, refer to:
public static boolean RootCommand(String command) {
Process process = null;
DataOutputStream os = null;
try {
process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());
os.writeBytes(command + "\n");
os.writeBytes("exit\n");
os.flush();
process.waitFor();
} catch (Exception e) {
Log.d("*** DEBUG ***", "ROOT REE" + e.getMessage());
return false;
} finally {
try {
if (os != null) {
os.close();
}
process.destroy();
} catch (Exception e) {
}
}
Log.d("*** DEBUG ***", "Root SUC ");
return true;
}
I'm trying to send PNG file from my android server to my python client.
The PNG image I try to send is a screenshot, around 4mb tops, usually under 2mb.
android code (sending):
File myFile = new File(imagePath);
FileInputStream fis = null;
try {
fis = new FileInputStream(myFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
BufferedInputStream bis = new BufferedInputStream(fis);
Log.i("service", "sending file len");
try {
out.write("" +myFile.length());
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
Log.i("service:", "waiteing for ok");
try {
msg = in.readLine();
} catch (Exception e) {
e.printStackTrace();
}
Log.i("service", "sending file");
byte[] outBuffer = new byte[(int) myFile.length()];
try {
bis.read(outBuffer, 0, outBuffer.length);
os = client.getOutputStream();
os.write(outBuffer, 0, outBuffer.length);
} catch (IOException e) {
e.printStackTrace();
}
python code (receiving):
print "waiting for responce's length"
MSGLEN = int(sock.recv(bufferLen))
print MSGLEN
sock.sendall("ok" +"\n")
chunks = []
bytes_recd = 0
while bytes_recd < MSGLEN:
chunk = sock.recv(min(MSGLEN - bytes_recd, bufferLen))
chunks.append(chunk)
bytes_recd = bytes_recd + len(chunk)
dataRecived = ''.join(chunks)
print 'data receieved'
print 'writing data to file'
fileout = open("D:\shots.png", 'w')
fileout.write(dataRecived)
fileout.close()
The file transfers from the android to my PC, but the file is corrupted.
When I compare it with the original image, almost everything is identical
except some empty lines here and there (not missing information, just empty line like someone added \n) and 1 or 2 big chunks of lines (15 lines or so) are missing.
Here you can see comparison between the tho files (left-original, right-file after sending).
I don't know why the file transfers corrupted, please help me.
Try coding it as Base64 and sending a simple string. Those missing lines are also part of image data - remember that those are binary.
Base64 or Bytestream is what u need
I'm new to android app development and have a question. I need to mount the system as rw, copy a file in /system/etc (back up the file which I have done) then open the original file, (it's an xml file) parse through it and then add an element. I haven't written the part yet to parse the file but I'm just trying to see if I can write to the file. I figured before I even write the xml parsing code I should see if I can at least write to the file but canWrite returns false. Anyone have any ideas? Thanks in advance
code in onCreate:
try {
RunProcess= Runtime.getRuntime().exec("su");
} catch (IOException e) {
e.printStackTrace();
}
code in button click:
try {
DataOutputStream os;
File file2 = new File("/system/etc/permissions/platform.xml");
os = new DataOutputStream(RunProcess.getOutputStream());
os.writeBytes("mount -o rw,remount /system\n");
Log.d("MOUNT RW?", " RW WRITABLE? " + file2.canWrite());
os.writeBytes("exit\n");
os.flush();
RunProcess.waitFor();
Toast.makeText(getApplicationContext(), "Backed up original file", Toast.LENGTH_SHORT).show();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
I would change the name of the model programmatically and I have root permissions, but my code does not work well and do not understand the problem.
The second toast give me this message "Error2:File/system/build.prop/ro.product.model open failed: ENOTDIR (Not a directory)"
code:
try {
process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());
os.writeBytes("mount -o remount rw /system/\n");
os.writeBytes("exit\n");
os.flush();
process.waitFor();
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "Error1: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
File file=new File("/system/build.prop/ro.product.model");
try {
fis = new FileInputStream(file);
String content = "xx";
byte[] input = new byte[fis.available()];
while (fis.read(input) != -1) {}
content += new String(input);
DataOutputStream outstream= new DataOutputStream(new FileOutputStream(file,false));
String body = content;
outstream.write(body.getBytes());
outstream.close();
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "Error2: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
Replace the line FileInputStream fis = openFileInput("/system/build.prop/ro.product.model"); by:
FileInputStream fis = FileInputStream(file);
for security reasons openFileInput is not allowed to accept seperators in the file name. But you can create a File with seperators in the path and create a FileImputStream from the file.
There is another problem in your porgram, the model name is not located in a file called "/system/build.prop/ro.product.model", but is defined by the line "ro.product.model=" in the file "/system/build.prop".. Be careful when editing this file!!
I need to download by program an .apk file then launching its activity.
The code I am using is the following
private String downloadFile(String sourceURL, String destinationPath)
{
try {
URL url = new URL(sourceURL);
URLConnection connection = url.openConnection();
connection.connect();
// download the file
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(destinationPath);
byte data[] = new byte[1024];
int count;
while ((count = input.read(data)) > 0) {
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
// EDITED here: Make the file rw, otherwise the apk file will not be installed
Runtime.getRuntime().exec("chmod 666 " + destinationPath);
message = "OK";
}
catch (MalformedURLException e) {
message = "Malformed URL error: " + e.getMessage();
}
catch (ProtocolException e) {
message = "Protocol exception error: " + e.getMessage();
}
catch (FileNotFoundException e) {
message = "File not found error: " + e.getMessage();
}
catch (IOException e) {
e.printStackTrace();
message = "Failed to download the file : " + e.getMessage();
}
return message;
}
I mention that I call the method first for a text file, then for an apk file. Each time I process the files locally, therefore, somehow I know what's going wrong or not. In this way I know that the text file is downloaded correctly. But the .apk file is corrupted. Because I develop locally, with access to DDMS and localhost (the IP: 10.0.2.2) I can firmly state that the culprit is the code above. When I artificially replace the 'downloaded' file, through DDMS, with the original .apk file, all processing that follows is Ok. In addition, I have byes difference when I compare the original and the downloaded .apk files.
What am I doing wrong?
Thanks
PS: Searching, I realized that, while is a popular issue, there is no consistent answer to it. In my case I identified it as purely a download method issue.
Please see above the answer under the EDITED line. Implemented, works fine, that may help others