Is there a way for my android app to retrieve and set extended user attributes of files? Is there a way to use java.nio.file.Files
on android? Is there any way to use setfattr
and getfattr
from my dalvik app? I know that android use the ext4 file system, so i guess it should be possible. Any suggestions?

- 1,846
- 1
- 18
- 28

- 151
- 1
- 5
1 Answers
The Android Java library and the bionic C library do not support it. So you have to use native code with Linux syscalls for that.
Here is some sample code to get you started, tested on Android 4.2 and Android 4.4.
XAttrNative.java
package com.appfour.example;
import java.io.IOException;
public class XAttrNative {
static {
System.loadLibrary("xattr");
}
public static native void setxattr(String path, String key, String value) throws IOException;
}
xattr.c
#include <string.h>
#include <jni.h>
#include <asm/unistd.h>
#include <errno.h>
void Java_com_appfour_example_XAttrNative_setxattr(JNIEnv* env, jclass clazz,
jstring path, jstring key, jstring value) {
char* pathChars = (*env)->GetStringUTFChars(env, path, NULL);
char* keyChars = (*env)->GetStringUTFChars(env, key, NULL);
char* valueChars = (*env)->GetStringUTFChars(env, value, NULL);
int res = syscall(__NR_setxattr, pathChars, keyChars, valueChars,
strlen(valueChars), 0);
if (res != 0) {
jclass exClass = (*env)->FindClass(env, "java/io/IOException");
(*env)->ThrowNew(env, exClass, strerror(errno));
}
(*env)->ReleaseStringUTFChars(env, path, pathChars);
(*env)->ReleaseStringUTFChars(env, key, keyChars);
(*env)->ReleaseStringUTFChars(env, value, valueChars);
}
This works fine on internal storage but not on (emulated) external storage which uses the sdcardfs filesystem or other kernel functions to disable features not supported by the FAT filesystem such as symlinks and extended attributes. Arguably they do this because external storage can be accessed by connecting the device to a PC and the users expects that copying files back and forth preserves all information.
So this works:
File dataFile = new File(getFilesDir(),"test");
dataFile.createNewFile();
XAttrNative.setxattr(dataFile.getPath(), "user.testkey", "testvalue");
while this throws IOException
with the error message: "Operation not supported on transport endpoint":
File externalStorageFile = new File(getExternalFilesDir(null),"test");
externalStorageFile.createNewFile();
XAttrNative.setxattr(externalStorageFile.getPath(), "user.testkey", "testvalue");

- 4,852
- 1
- 23
- 40
-
why the second one throws an exception? – Blackbelt Jun 24 '14 at 13:54
-
Because Google does not want any functionality which goes beyond that supported by FAT to work on external storage - emulated or not. That includes symlinks, extended attributes, ... They enforce this with sdcardfs and other kernel functionality. Arguably they do this because external storage can be accessed by connecting the device to a PC and the users expects that copying files back and forth preserves all information. – HHK Jun 24 '14 at 14:07
-
well actually this should be part of your answer – Blackbelt Jun 24 '14 at 14:08
-
Wow nice answer. So just to verify, it generally isn't possible to use extended attributes on external storage, it will only work via this native code for "local" files? – cottonBallPaws Jun 24 '14 at 15:44
-
@cottonBallPaws Yes, it will only work for files on "internal storage". Here is an [overview](http://developer.android.com/guide/topics/data/data-storage.html) over the storage options. – HHK Jun 24 '14 at 16:09
-
@HansKratz : just one point, all of this require root, isn’t it ? – user2284570 Apr 13 '16 at 00:30
-
@user2284570 Nope, that works fine without root (at least on Android 4.4). – HHK May 10 '16 at 13:14