Android - create symbolic link in the app
Asked Answered
T

2

5

I want create programmatically symbolic link in my app. Is it possible in Android (4.4+)?

In Java we can use:

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);
}

from java.nio.file but what I should use in Android?

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

EDIT:

I tested using reflection/native code/OS.symlink() method and nothing work. I always get Operation not permitted (EPERM). I think you have to have root permission for create the symlink.

The problem can be with that /mnt/sdcard is a FUSE shim that wraps /data/media/xxx. So I started using /data/media/xxx but I always get Permission denied

I think it's a problem with root permissions.

Treytri answered 5/1, 2016 at 9:32 Comment(6)
#27726928Choker
I tried reflection but it's not working: android.system.ErrnoException: symlink failed: EPERM (Operation not permitted) . I will try the native code.Treytri
have you tried the other answer on #27726928 ?? Os.symlink(originalFilePath,symLinkFilePath); ?Footing
I need it also in Android 4.4 (API level 19).Treytri
I also tried Os.symlink(originalFilePath,symLinkFilePath); but I get again symlink failed: EPERM (Operation not permitted) on Samsung Galaxy S5Treytri
And native code returns for me -1 . But I don't know why. Do you have some tips?Treytri
B
3

Here's a solution that worked for me, which returns true iff succeeded :

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;
}

Or in Kotlin:

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
    }
}
Besmirch answered 13/5, 2019 at 7:1 Comment(0)
G
0

Now Android has system calls you can use. Here's android.system.Os.symlink

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

there is also the java.nio.file.Files.createSymbolicLink method

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...)

but I guess that one didn't really work for you

Genevagenevan answered 10/5, 2021 at 18:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.