Android - создайте символическую ссылку в приложении

Я хочу создать программно символическую ссылку в моем приложении. Возможно ли это в Android (4.4+)?

В Java мы можем использовать:

Path newLink = ...;
Path target = ...;
try {
    Files.createSymbolicLink(newLink, target);
} catch (IOException x) {
    System.err.println(x);
} catch (UnsupportedOperationException x) {
    // Some file systems do not support symbolic links.
    System.err.println(x);
}

от java.nio.file но что я должен использовать в Android?

https://docs.oracle.com/javase/tutorial/essential/io/links.html

РЕДАКТИРОВАТЬ:

Я тестировал используя reflection/native code/OS.symlink() method и ничего не работает. Я всегда получаю Операцию не разрешено (EPERM). Я думаю, что вы должны иметь права root для создания символической ссылки.

Проблема может быть с этим /mnt/sdcard это прокладка FUSE, которая оборачивает /data/media/xxx, Итак, я начал использовать /data/media/xxx но я всегда получаю Permission denied

Я думаю, что это проблема с рут правами.

2 ответа

Вот решение, которое сработало для меня, которое возвращает true, если успешно:

public static boolean createSymLink(String symLinkFilePath, String originalFilePath) {
    try {
        if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
            Os.symlink(originalFilePath, symLinkFilePath);
            return true;
        }
        final Class<?> libcore = Class.forName("libcore.io.Libcore");
        final java.lang.reflect.Field fOs = libcore.getDeclaredField("os");
        fOs.setAccessible(true);
        final Object os = fOs.get(null);
        final java.lang.reflect.Method method = os.getClass().getMethod("symlink", String.class, String.class);
        method.invoke(os, originalFilePath, symLinkFilePath);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

Или в Котлине:

companion object {
    @JvmStatic
    fun createSymLink(symLinkFilePath: String, originalFilePath: String): Boolean {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Os.symlink(originalFilePath, symLinkFilePath)
                return true
            }
            val libcore = Class.forName("libcore.io.Libcore")
            val fOs = libcore.getDeclaredField("os")
            fOs.isAccessible = true
            val os = fOs.get(null)
            val method = os.javaClass.getMethod("symlink", String::class.java, String::class.java)
            method.invoke(os, originalFilePath, symLinkFilePath)
            return true
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return false
    }
}

Теперь у Android есть системные вызовы, которые вы можете использовать. Вот android.system.Os.symlink

https://developer.android.com/reference/android/system/Os#symlink(java.lang.String,%20java.lang.String)

есть также java.nio.file.Files.createSymbolicLink метод

https://developer.android.com/reference/java/nio/file/Files#createSymbolicLink(java.nio.file.Path,%20java.nio.file.Path,%20java.nio.file.attribute.FileAttribute%3C?%3E...)

но я думаю, что это действительно не сработало для вас

Другие вопросы по тегам