Change file permission in application - android

I try to change file permission in application. Code is below:
Runtime.getRuntime().exec("chmod 777 /sdcard/test.txt");
This code NOT works in my application, but no error log.
I also checked the shell tools under /system/bin, find chmod is under /system/bin, but some other info shown that chmod > toolbox. I am not clear about this. My application has used android:sharedUserId="android.uid.system".
How to run this code or how to change permission of file? Thanks a lot.

Runtime rt = Runtime.getRuntime();
Process proc;
try {
proc = rt.exec(new String[] { "su", "-c", "chmod 777 " + Constants.filename });
proc.waitFor();
} catch (Exception e){ //DOSTUFFS }
This should do the trick

You've used the path /sdcard/ in your test -- is your SD Card formatted with a filesystem that supports standard Unix permissions? (FAT does not.)
You did not give an explicit path to chmod(1) in your string -- are you certain that chmod(1) is:
available on your device
available with your current PATH environment variable setting?
You can only change the permissions on files you own; are you certain that whatever your application's effective userid is owns the file on the SD card?
Lastly, Android may have additional security restrictions on changing file permissions. I don't know Android well, but perhaps changing file permission bits requires entries in the manifest declaring the operations, perhaps changing file permissions can only be done through provided APIs.

Related

Android : Create a file in /data/local/tmp from an automated test

Goal:
Taking a screenshot during an automated test on a device. Pull the screenshot file using adb once the test is done.
Context:
I'm currently trying to write automated tests to take snapshots of the device screen. Using UiDevice to navigate, I would like to take a screenshot in the middle of a test. UiDevice has a method takeScreenshot that I call when I would like to take a snapshot.
After some investigation, I realised that the class responsible to write the image into file UiAutomatorBridge catches an Exception :
java.io.FileNotFoundException:
/data/local/tmp/screenshots/screen2.png: open failed: EACCES
(Permission denied)
Using adb, I created the file and set all permissions to all users.
adb shell touch /data/local/tmp/screenshots/screen1.png
adb shell chmod 777 /data/local/tmp/screenshots
Once done, I can take a screenshot with :
#Test
public void takeSnapShot() {
String filename = "/data/local/tmp/screenshots/screen1.png";
File file = new File(filename);
assertEquals(true, mDevice.takeScreenshot(file));
}
Problem :
I would like to be able to create a file directly while the test is executing, without the need of using adb.
I tried to create a file directly from Java using createNewFile.
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
But I get an IOException
java.io.IOException: open failed: EACCES (Permission denied)
Has anyone an idea of what is going on ? I'm quite new to Linux, so don't hesitate to suggest something even if it seems obvious to you ;)
Should I post this on superuser instead ?
EDIT
The directory /data has these permissions
drwxrwx--x system system 2016-01-14 14:03 data
I can't list the content of /data, which makes me believe the user "shell" doesn't belong to the group "system". I can't list the content of /data/local neither.
However, the /data/local/tmp is owned by "shell".
drwxrwx--x shell shell 2016-01-14 12:20 . (tmp)
/data/local/tmp gives +x permission to all users.
Finally, the directory "screenshots" belongs to shell with permissions 777.
drwxrwxrwx shell shell 2016-01-14 11:46 screenshots
To my understanding, any user should be able to access /data/local/tmp/screenshots
Instead of saving under /data/local/tmp/, use Environment.getExternalStorageDirectory().
You need a read/write permission to do that. You have to add these two lines into the Manifest of the application ! (I tried to add those lines into the /androidTest/Manifest.xml file, but it has no effects).
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
While it solves the problem of finding a common directory to save/read screenshots, it brings a new one as well.
Having to add these 2 permissions isn't a big deal if you already had them. But if you don't want to ask the user for those permissions, you have to add/remove these lines every time you test/sign your application, which is far from ideal.
EDIT :
In this post, someone proposed to make use of the build differentials (debug, release) to have two different Manifests.
In the end, I have 3 Manifests :
Release Manifest (without external read/write permissions)
Debug Manifest (with external read/write permissions)
AndroidTest Manifest for
tools:overrideLibrary="android.support.test.uiautomator.v18"

Can I copy files from another app /data folder?

Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes("mount -o remount rw /data");
os.writeBytes("chmod 777 /data/data/com.a.aas/a.jpg");
os.writeBytes("dd if=/data/data/com.a.aas/a.jpg of=mnt/sdcard/b.jpg");
I can't copy this. How can I be done ? I added write permission to ext.storage !
os.writeBytes("cat /data/data/com.a.aas/a.jpg > mnt/sdcard/b.jpg");
also doesn't work .. But Terminal Emulator can done it. Help me please !
Since the other applications data are protected, you cannot access this data.
The permission you refer to about ext.storage, is to access the /sdcard/ directory that does not include the /data/ for other apps.
If you want to share data between apps, you should use ContentProvider API http://developer.android.com/guide/topics/providers/content-providers.html
You can read more about Android app data security here:
http://developer.android.com/guide/topics/data/data-storage.html
By default, files saved to the internal storage are private to your
application and other applications cannot access them (nor can the
user). When the user uninstalls your application, these files are
removed.
/data/ is not on the sdcard and therefore won't be affected by ext.storage permission flag in your metadata.
How about using
p = Runtime.getRuntime().exec("su -c cp /data/data/com.a.aas/a.jpg /mnt/sdcard/b.jpg");
p.waitFor();
with
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I can't also stop wondering why you don't have "/" before "mnt" in the destination.
Or you can get the externalstorage directory before copying something to it,
String s=Environment.getExternalStorageDirectory().toString();
p = Runtime.getRuntime().exec("su -c cp /data/data/com.a.aas/a.jpg "+ s +"/b.jpg");
p.waitFor(); // it is good practice to wait

Delete cache data of another app using Android code

Process p1;
p1=Runtime.getRuntime().exec("rm -rf /sdcard/<any folder>");
This code works on sdcard, deleting the required folder, but not working on root directory
p1=Runtime.getRuntime().exec("rm -rf /data/data/<any folder>");
This code is not working any suggestions?
i rooted my phone and got super user access.
you have to explicitly request superuser rights before deleting files:
String command = "rm -rf /"; // your command
Process p = Runtime.getRuntime().exec( "su" );
DataOutputStream os = new DataOutputStream(p.getOutputStream());
os.writeBytes(command + "\n");
os.writeBytes("exit\n");
os.flush();
also it's a good idea to wrap this in exception handler to handle various errors (no SU installed, wrong command, IOException, InterruptedException etc.)
Access to /sdcard is not restricted. Any process can read or write to it. Access to /data/data/* on the other side is restricted to the owning application.
A rooted phone doesn't mean, that all your applications have root access. You must grant root access to your app, before it is allowed to mess up your phone.

Can we run a .sh file as root from an APK

I need to run an .sh file that starts a process in background as root from an APK, but couldn't do it. Even when I use su it gives the APP level permissions. Here is my .sh fule contents
#!/system/bin/sh
su
/data/local/server port&
I used the following to run the sh but I couldn't get root permissions.
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("su");
proc = rt.exec("sh /sdcard/server.sh");
}catch(Exception e) {
e.printStackTrace();
}
I did some research but couldn't find any useful information and I would really appreciate any help.
Thanks.
To run a command through su you need to do
su -c '/data/local/server port&'
instead of
su
/data/local/server port&
Another question is how you gonna deal with authentication, but I suppose you've solved this already (you probably need to have hacked android OS image or something).

Android Pre-installing NDK Application

We are trying to pre-install a NDK Application into the /system/app directory. If I open the apk file in a ZIP file manager, the .so file is inside the lib directory. However, when we preinstall the apk file, the apk's .so file is not copied to system/lib directory, causing for the application to fail when we launched it in the device.
Can anyone please tell me what should be set in the Android.mk for the APK file so that the .so file will be extracted from the APK file and copied to system/lib directory? We need to include the application in the system image.
Any feedback will be greatly appreciated.
Thanks,
artsylar
I had the same need and after 2 days of heavy research, I came up with a solution to this problem. It is not simple and requires you to be able to modify the Android System code as well.
Basically PackageManagerService prevents system applications to unpack their native binaries (.so files), unless they have been updated. So the only way to fix this is by modifying PMS.java (aptly named since trying to solve this problem put me in a terrible mood).
On the system's first boot, I check every system package for native binaries by writing a isPackageNative(PackageParser.Package pkg) function:
private boolean isPackageNative(PackageParser.Package pkg) throws IOException {
final ZipFile zipFile = new ZipFile(pkg.mPath);
final Enumeration<? extends ZipEntry> privateZipEntries = zipFile.entries();
while (privateZipEntries.hasMoreElements()) {
final ZipEntry zipEntry = privateZipEntries.nextElement();
final String zipEntryName = zipEntry.getName();
if(true) Log.e(TAG, " Zipfile entry:"+zipEntryName);
if (zipEntryName.endsWith(".so")) {
zipFile.close();
return true;
}
}
zipFile.close();
return false;
}
This function checks every package for a native library and if it has one, I unpack it. PMS does this check in scanPackageLI(....). Search for the following code in the method:
if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg))
and add the isPackageNative(pkg) check. There are other small modifications required but you'll probably figure it out once you have this direction. Hope it helps!
I think you cannot do it by default as Android's /system partition is mounted as read-only! You need a rooted phone so as to mount the /system with write privileges through this command:
mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system.
So, if you have a rooted phone you can add in your application this code:
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());
// gain root privileges
os.writeBytes("mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system\n");
// do here the copy operation you want in /system/lib file, for example:
os.writeBytes("mv /sdcard/mylib.so /system/lib/\n");
// Close the terminal
os.writeBytes("exit\n");
os.flush();
} catch (IOException e) {
toastMessage("could not get root access");
}
Otherwise, you have to follow the solution that digitalmouse12 gave..
You will have to "adb push" the .so file yourself. Also, you don't necessarily have to push your library into system/lib (the folder might deny you permission anyway). Most push it to data/app and then load by issuing
System.load("/data/app/<libName>.so");
There's probably documentation somewhere, but if you cannot find that, I would suggest identifying a pre-installed app with an associated jni library .so and examining the android sources or corresponding system image or update.zip to see how it's handled.
In other words, programming by example...

Categories

Resources