Android Write file to a different application folder - java

My device is rooted
The target audience (if app is shared) will be rooted devices only
I'm trying to customize another app slightly by modifying some image files. So objective is to simply overwrite tiny jpg files (one at a time as required)
/data/data/com.otherapp/files/somefile.jpg for example needs to be overwritten
p = Runtime.getRuntime().exec("su"); is already run before I tried the write method.
I also added Runtime.getRuntime().exec("chmod 077 " +myFile.getAbsolutePath()); before the write code as suggested on a similar question
I'm getting permission denied.
java.io.FileNotFoundException: /data/data/com......jpg: open failed: EACCES (Permission denied)
The write code I have is:
//myDir is /data/data/com.......
File myFile = new File (myDir.getAbsolutePath(), fname);
try {
//myFile.createNewFile();//tried with and without this
FileOutputStream out = new FileOutputStream(myFile);
btbmp.compress(Bitmap.CompressFormat.JPEG, 60, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
How can I do this?

Okay it's taken all day but I've achieved the desired result thus:
Create file on SD card
Then copy file to root destination
src_file = "somefile/on/sdcard.jpg"
dest_file = "/data/data/com.anotherapp/files/abcde.jpg" got path using context
try {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes("rm "+dest_file + "\n"); //removes destination file -might not be required - haven't tested
os.flush();
os.writeBytes("cat "+src_file+" > "+dest_file + "\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
// Waits for the command to finish.
process.waitFor();
}
catch (IOException e) {
e.printStackTrace();
}
catch (InterruptedException e) {
e.printStackTrace();
}
Note In some cases I had to chmod the root folder 777 for it to work. I'm sure this isn't good practice and doing so will mean the app that uses that folder might not be able to access it. In my case that's what happened until I rectified it using ES Explorer

Related

access denied to access to /etc/hosts

i can't access to hosts file of windows with java (just write) :
java.io.FileNotFoundException: C:\Windows\system32\drivers\etc\hosts (Access is denied)
at java.io.FileOutputStream.open(Native Method)
when i want append my text to hosts file get above error ...
this is my code :
BufferedWriter bw = null;
try {
// APPEND MODE SET HERE
bw = new BufferedWriter(new FileWriter(file,true));
bw.write(text);
bw.newLine();
bw.flush();
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally { try {
// always close the file
bw.close();
} catch (IOException ex) {
Logger.getLogger(FileWrite.class.getName()).log(Level.SEVERE, null, ex);
}
}
} // end test()
this code work for simple files in other location of windows .. (just get error on c:\windows\ ...
and :
i use microsoft manifest to set administration access [not work]
set full access to hosts file [not work]
please help ..
tnx
Check if your java is really running as administrator (i.e. write to a new file in the same folder). There is obviously access problem and to solve it you need to understand who you are (user/service of your app) and what are permissions of resource (file) you are trying to access.
here are two ways how you can try and debug it:
1) You don't have permissions to write the file (can you read it?)
2) You don't have permissions to enter the folder (can you list files in it)

Attempting to overwrite files results in blank files

In the app I am working on right now, part of the functionality is to write data saved on the device to a flash drive connected via a USB-OTG adapter. Specifically, the device is a rooted Motorola Xoom running 4.2.2. I can successfully write files to the drive and read them on my computer. That part works fine. However, when I try to replace existing files with new information, the resulting files come out empty. I even delete the existing files before writing new data. What's weird is that after copying the contents of my internal file to the flash drive, I log the length of the resulting file. It always matches the input file and is always a non-0 number, yet the file still shows up as blank on my computer. Can anyone help with this problem? Relevant code from the AsyncTask that I have doing this work is below.
#Override
protected Void doInBackground(Void... params) {
File[] files = context.getFilesDir().listFiles();
for (File file : files) {
if (file.isFile()) {
List<String> nameSegments = Arrays.asList(file.getName().split(
"_"));
Log.d("source file", "size: " + file.length());
String destinationPath = "/storage/usbdisk0/"
+ nameSegments.get(0) + "/" + nameSegments.get(1) + "/";
File destinationPathFile = new File(destinationPath);
if (!destinationPathFile.mkdirs()) {
destinationPathFile.mkdirs();
}
File destinationFile = new File(destinationPathFile,
nameSegments.get(2));
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader(file);
fw = new FileWriter(destinationFile, false);
int c = fr.read();
while (c != -1) {
fw.write(c);
c = fr.read();
}
fw.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fr.close();
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Log.d("destination file", "size: " + new File(destinationFile.getPath()).length());
}
}
return null;
}
EDIT:
Per #Simon's suggestion, I added output.flush() to my code. This does not change the result.
EDIT #2:
I did some further testing with this and found something interesting. If I go to Settings->Storage->Unmount USB Storage after writing to the flash drive but before removing it from the OTG adapter, everything works perfectly. However, failing to eject the drive after writing results in the data not being written. What's strange is that the folder structure and file itself are created on the drive, but the file is always empty. One more thing: if I go to a file manager application and open up the file prior to removing the drive, the files all exist as they should. However, even removing the device, plugging it straight back in to the tablet and opening any of the files results in the file looking empty. I can't make heads or tails of this, and this is incredibly frustrating. Can anyone help with this?
EDIT #3:
I also changed to using FileReaders and FileWriters just to wee what would happen. I don't care about efficiency at this point, I simply want file writing to work reliably. This change did not affect the issue. Updated code is posted above.
Try using FileReader.ready() method before your FileReader.read() call,
and ensure if your FileReader really has some bytes in it.
Try this , Used buffered reader for writing
try
{
fw = new FileWriter(destinationFile);
BufferedWriter writer=new BufferedWriter(fw);
writer.append(yourText); // Append can be changed to write or something if you want to overwrite
writer.close();
}
catch (Exception e) {
throw new RuntimeException(e);
}
finally {
if (fw != null) {
try {
fw.flush();
fw.close();
}
catch (IOException e) {
}
I found the solution to my problem. It appears that the Android system buffers some files off of the SD card/flash drive, and then writes them to the flash drive upon eject. The following code after my file operations synchronizes the buffer with the filesystem and allows the flash drive to be immediately removed from the device without data loss. It's worth noting that this DOES require root access; it will not work on a non-rooted device.
try {
Process p = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(p.getOutputStream());
os.writeBytes("sync; sync\n");
os.writeBytes("exit\n");
os.flush();
} catch (Exception e) {
e.printStackTrace();
}
Source of my solution: Android 2.1 programatically unmount SDCard
It sounds like the filesystem is caching your changes, but not actually writing them to the flash drive until you eject it. I don't think there's a way to flush the filesystem cache, so the best solution seems to be just to unmount and then remount the flash drive.

Android SU permissions IOException

if (DownloadManager.STATUS_SUCCESSFUL == c
.getInt(columnIndex)) {
mProgress.setProgress(70);
mStatus.setText(R.string.status_backup);
File dl_path = new File(DownloadManager.COLUMN_LOCAL_URI);
File og_path = new File("/system/app/app.apk");
String bu_path = "/sdcard/asdfgsd/backup/app.apk";
Process p;
try {
// Preform su to get root privledges
p = Runtime.getRuntime().exec("su");
// Attempt to write a file to a root-only
DataOutputStream os = new DataOutputStream(p.getOutputStream());
os.writeBytes("echo \"Do I have root?\" >/system/sd/temporary.txt\n");
// Close the terminal
os.writeBytes("exit\n");
os.flush();
try {
p.waitFor();
if (p.exitValue() != 255) {
// Trying to remount system partition in read-write mode
p.getOutputStream().write("mount -o r,remount -t yaffs2 /dev/block/mtdblock3 /system".getBytes());
if (og_path.renameTo(new File(bu_path))) {
mProgress.setProgress(90);
mStatus.setText(R.string.status_install);
dl_path.renameTo(og_path); } else {
mStatus.setText(R.string.status_error_1);
}
}
} catch (InterruptedException e) {
mStatus.setText(R.string.status_error_2);
}
} catch (IOException e) {
mStatus.setText(R.string.status_error_3);
}
}
So this is a piece of code that should replace an app from /system/app to backup folder and then it should replace a copy downloaded via DM API to /system/app. Everything works perfect until app starts asking for SU permissions. As you can see, I put some error strings in case of exceptions to make debug easier, and it seems like it got an IO exception (status_error_3). What's wrong with my code?
UPD: SU successfully asks for granting permissions to my app, so it should work but it doesn't.
Thanks in advance!

FileNotFoundException (The system cannot find the path specified)

I get this exception:
java.io.FileNotFoundException: C:\...\filename.xml (The system cannot find the path specified)
using this code:
FileWriter fileWriter = new FileWriter(new File(path + date + time "filename.xml"));
BufferedWriter writer = new BufferedWriter(fileWriter);
writer.write("data");
Path exists but directories for 'date' and 'time' need to be created. Application has full permissions on the directory.
Any ideas?
The problem is because I'm creating a subdirectory in which to write the files. So I currently have C:\example\ and want to write my files in C:\example\<date>\<time>\<files>
You need to call File#mkdirs() before writing.
File file = new File("C:/example/newdir/newdir/filename.ext");
file.mkdirs();
// ...
Do assume that the computer is right and you are wrong.
And, in that scenario, the directory to which you want to write does not exit (or does not have permissions to do so).
check the current working dir System.getProperty("user.dir")
debug from there
Code works for me. (Need to add a writer.close() for text to show up in the file.)
What worked for me: The folder where my project was present had a space in the name. I replacedthe space with a hyphen(-). Now, the relative path of the file does not have a space (%20). This change worked for me. Hope it helps someone.
You also need to convert newly created file and folder paths to string.
File folder = new File("src\\main\\json\\", idNumber);
folder.mkdir();
if (!folder.exists()) {
try {
folder.createNewFile();
} catch (IOException ex) {
Logger.getLogger(JsonGeneration.class.getName()).log(Level.SEVERE, null, ex);
}
}
...
...
FileOutputStream output = null;
File file;
String content = data.toString();
try {
String folder_location = folder.toString() + "\\";
String filename = "CurrentInfo";
file = new File(folder_location + filename.toString() + ".json");
output = new FileOutputStream(file);
if (!file.exists()) {
file.createNewFile();
}
byte[] content_in_bytes = content.getBytes();
output.write(content_in_bytes);
output.flush();
output.close();
} catch (IOException ex) {
Logger.getLogger(JsonGeneration.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (output != null) {
output.close();
}
} catch (IOException e) {
Logger.getLogger(JsonGeneration.class.getName()).log(Level.SEVERE, null, e);
}
}
}

Writing to file from within a servlet(Deployer:Tomcat)

I am using the following code to write to a file from a servlet in Tomcat container. I don't worry if the file gets overwritten during each deploy.
BufferedWriter xml_out = null;
try {
xml_out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(getServletContext().getRealPath("/")
+ File.separator + "WEB-INF" + File.separator
+ "XML.xml"), "UTF8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
xml_out.write(xml);
xml_out.flush();
xml_out.close();
} catch (IOException e) {
e.printStackTrace();
}
However, the file writing is not successful (it doesn't get written in the hard disk). Also, there isn't any exception that gets caught! Is there some security thing in Tomcat that is preventing the file from being written ?
Your code has both "/" and the windows file separator at the start of the filename passed to getRealPath(), Java interprets slashes in filenames according to the current OS.
Not using the file separators might give a better result:
String filename = getServletContext().getRealPath("/WEB-INF/XML.xml");
log.debug("Using XML file: " + filename);
xml_out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename),"UTF8"));
Using a separate variable for the filename lets you log it so you can see unexpected results early in de development process.
I has the same issue.
this link helped me to understand where the file was in the hard disk.
Specifically for me, it put the file in the location that is returned by this line:
System.getProperty("user.dir");
In my case the location was: C:\Users\Myself\programming\eclipse for java

Categories