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;
}
Related
I have a very specific issue - I am trying to write to external storage on an Asus Nexus 7, but it is writing to the emulated directory on the device.
Here is the code I am using:
public static void writeExternalMedia(Context context) {
if(isExternalStorageWritable()) {
String content = "hello world";
File filedir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/test");
filedir.mkdir();
File file;
FileOutputStream outputStream;
try {
file = new File(filedir, "test.txt");
if (!file.exists()) {
file.createNewFile();
}
outputStream = new FileOutputStream(file);
outputStream.write(content.getBytes());
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Whenever I restart the device, the directories appear under the device when plugged in, which is what I would expect to happen when the function above gets executed.
I have tried searching for a solution and cannot find the answer to my question.
I made two methods. One for creating a file and one for appending to it. I think the issue is that you're not calling createNewFile.
private File CreateFile(String fileName)
{
File file = new File(this.getFilesDir(), fileName);
try
{
if(!file.exists())
{
file.createNewFile();
}
}
catch (IOException e)
{
e.printStackTrace();
}
return file;
}
private void appendToFile(String file, String content)
{
try
{
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(this.openFileOutput(file, this.MODE_APPEND));
outputStreamWriter.append(content + "\n");
outputStreamWriter.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
Alright after much searching and testing I finally came across a solution, linked via one of the other answers.
https://stackoverflow.com/a/28448843/979220
The solution was to scan the media files, which causes the files to propagate to the external storage, rather than staying in the emulated storage.
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!!
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.
Greetings and a happy new year to all my fellow programmers.
My code downloads an apk file from a remote server. I need to initiate the installation procedure through code, without user having to explicitly install it. The catch is that i cannot use an SD card download the apk file.
I can navigate to the data/data/files folder and can see my file downloaded. The only problem is that i cannot get it installed. This is what i get
'/data/data/org.obs.testinstall.main/files/app.apk': Permission denied
I understand that Android does not give permission to access the data directory.
My question is how can i download and install an application(apk) without using a SD card. This application is not intended to be published in the market. I have tried using both the Internal Storage using
FileOutputStream fos = openFileOutput("app.apk", Context.MODE_PRIVATE);
and the cache directory
File file = getCacheDir();
File outputFile = new File(file, "app.apk");
Both give the same result .. "Permission denied"
When i change the code to incorporate an SD card the application works perfectly, but using an SD card is not an option.
Surely there must be a way to do this. It is hard to believe that such a handicap exist in the Android O/S.
Has anybody done this? Any workarounds? Any pointers would be helpful.
It it caused by android application can not read from
another application file if it is written using PRIVATE mode.
You can do this:
String fileName = "tmp.apk";
FileOutputStream fos = openFileOutput(fileName,
MODE_WORLD_READABLE | MODE_WORLD_WRITEABLE);
// write the .apk content here ... flush() and close()
// Now start the standard instalation window
File fileLocation = new File(context.getFilesDir(), fileName);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(fileLocation),
"application/vnd.android.package-archive");
context.startActivity(intent);
Be careful though, because that file is now world-visible,
and can be seen by any application in the same device,
if they know the file location.
No need to root.
You can just use linux command chmod to do it.
public static String exec(String[] args) {
String result = "";
ProcessBuilder processBuilder = new ProcessBuilder(args);
Process process = null;
InputStream errIs = null;
InputStream inIs = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int read = -1;
process = processBuilder.start();
errIs = process.getErrorStream();
while ((read = errIs.read()) != -1) {
baos.write(read);
}
baos.write('\n');
inIs = process.getInputStream();
while ((read = inIs.read()) != -1) {
baos.write(read);
}
byte[] data = baos.toByteArray();
result = new String(data);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (errIs != null) {
errIs.close();
}
if (inIs != null) {
inIs.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (process != null) {
process.destroy();
}
}
return result;
}
in your program,it can be invoked like this:
String[] args1 = { "chmod", "705", "/data/data/org.obs.testinstall.main/files/" };
exec(args1);
String[] args2 = { "chmod", "604", "/data/data/org.obs.testinstall.main/files/app.apk" };
exec(args2);
Then you can install the app.apk as wished.
Also you can use
downloadedFile.setReadable(true, false);
with
fileOutputStream = openFileOutput(fileName, Context.MODE_PRIVATE);
There are two setReadable method. The first has one parameter and the second one has two parameters.
setReadable(boolean readable)
setReadable(boolean readable, boolean ownerOnly)
Try rooting your device and then running the program from the device, instead of using an emulator.
For me I deleted the apk file right after the startActivity, which is asynchronous.
Too bad there is no better description of the parsing error (file not found, access denied, corrupted file in package,...)
when you send intent to install apk, you can use this function to change mode for apk directory.
private static boolean changeMode(String filePath, String prefixPath) {
if (TextUtils.isEmpty(prefixPath) || !filePath.startsWith(prefixPath)) {
return true;
}
try {
String[] args1 = { "chmod", "705", prefixPath};
Runtime.getRuntime().exec(args1);
} catch (IOException e) {
e.printStackTrace();
return false;
}
String subPath = filePath.split(prefixPath)[1];
String[] subArr = subPath.split(File.separator);
for (String path : subArr) {
if (!TextUtils.isEmpty(path)) {
prefixPath = prefixPath + File.separator + path;
try {
if (!prefixPath.endsWith(".apk")) {
String[] progArray1 = {"chmod", "705", prefixPath};
Runtime.getRuntime().exec(progArray1);
} else {
String[] progArray2 = {"chmod", "604", prefixPath};
Runtime.getRuntime().exec(progArray2);
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}
return true;
}
And before you send intent, check chmod is it alreay success.
boolean chmodRes = changeMode(filePath, context.getCacheDir().getAbsolutePath())
&& changeMode(filePath, context.getFilesDir().getAbsolutePath());
if (!chmodRes) {
return false;
}
I am trying to write some date data in a file with with function:
public void writeSettings(Context context, String data){
FileOutputStream fOut = null;
OutputStreamWriter osw = null;
try {
fOut = openFileOutput("settings.dat",MODE_PRIVATE);
osw = new OutputStreamWriter(fOut);
osw.write(data);
osw.flush();
Toast.makeText(context, "Settings saved",Toast.LENGTH_SHORT).show();
}
catch (Exception e) {
e.printStackTrace();
Toast.makeText(context, "Settings not saved",Toast.LENGTH_SHORT).show();
}
finally {
try {
osw.close();
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
In the blog where I found this code, it is said my file is stored in:
/data/data/PACKAGE_NAME/files/settings.dat
But I cannot find it on my phone! Where is this data folder?
In phone (Device) you don't have root privileges,so you can't see /data/data/ directory using eclipse->DDMS->File Explorer,
SO if you want to just see whether your file is created or not you can use ./adb shell command (for linux) adb shell (for windows)
Or try this on emulator and check with eclipse -> DDMS -> File Explorer...
You don not have access to /data folder in your phone unless you have root privileges.
You can test your app in emulator, data folder in emulator is accessable.
Have you tried to add permissions WRITE_SECURE_SETTINGS and/or WRITE_SETTINGS?
If you are using eclipse ide, find DDMS Window and click File Explorer. Search for /data/data/Package_Name/files