4

I can't seem to find a solid answer for this specific question.

I'm trying to create a symbolic link programmatically of a directory in my assets folder in another location within the same application's asset directory. Essentially, I'm looking to do the same thing as what the createSymbolicLink method of Java.nio.Files would do.

Is there an available way of doing this with the Android SDK? If not, is it possible in the NDK?

SBerg413
  • 14,515
  • 6
  • 62
  • 88
  • 1
    Are you referring to your "assets folder" on your development machine? Or are you referring to the assets when used at runtime? Please bear in mind that the assets packaged in your APK remain in the APK and are not unpacked, but are merely read out of the APK itself. Also note that an APK file is a ZIP archive, and AFAIK there is no symlink construct in ZIP archives. – CommonsWare Dec 31 '14 at 21:28

2 Answers2

8

For Android API 21 and above, just use:

Os.symlink(originalFilePath,symLinkFilePath);
android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • 2
    For lower versions `Runtime.getRuntime().exec("ln -s /path/to/file /path/to/symlink")` from [source](http://stackoverflow.com/a/41384476/3124150). – EmmanuelMess Mar 18 '17 at 22:53
3

There is no public API to do this. You can however use some dirty reflection to create your symbolic link. I just tested the following code and it worked for me:

// static factory method to transfer a file from assets to package files directory
AssetUtils.transferAsset(this, "test.png");

// The file that was transferred
File file = new File(getFilesDir(), "test.png");
// The file that I want as my symlink
File symlink = new File(getFilesDir(), "symlink.png");

// do some dirty reflection to create the symbolic link
try {
    final Class<?> libcore = Class.forName("libcore.io.Libcore");
    final Field fOs = libcore.getDeclaredField("os");
    fOs.setAccessible(true);
    final Object os = fOs.get(null);
    final Method method = os.getClass().getMethod("symlink", String.class, String.class);
    method.invoke(os, file.getAbsolutePath(), symlink.getAbsolutePath());
} catch (Exception e) {
    // TODO handle the exception
}

A quick Google search showed this answer if you don't want to use reflection: http://androidwarzone.blogspot.com/2012/03/creating-symbolic-links-on-android-from.html

Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
  • Somehow I missed that link in my google searches. I'm already using some native code in this particular project, so that may serve my needs. Thanks. – SBerg413 Jan 01 '15 at 13:24
  • This may be interesting for other purposes, but it doesn't actually address the question which was asked. Once you are copying the file from assets into an actual file-system file, what's the point of making a symlink rather than just giving the copy the desired name? – Chris Stratton Apr 19 '15 at 20:21
  • How come it accepts using only "getFilesDir" path for the symlinks files? I can't put it anywhere else but there. Not even in a sub-folder inside it (well it can create the file there, but it's not accessible for any other app). – android developer Apr 19 '15 at 22:22
  • @androiddeveloper It is like any other unix-like system. The files you create have the same UID as your app. Other apps cannot access those files unless they have a shared UID. Also, creating symlinks on external storage is not permitted on Android. – Jared Rummler Apr 20 '15 at 19:53
  • @JaredRummler The only path it works for both creating the symlink and sharing it is in the exact path of "getFilesDir". Why doesn't it work for other paths that are within this path (subfolders) ? Also, can I assume this method of creating symlinks work on all Android devices ? I've tested and it works on Android emulators since ICS (4.0.x) . Is there a more official way to do it? Would using the JNI option be safer? Sadly I never succeeded creating a library/project that uses JNI on Android-Studio. – android developer Apr 21 '15 at 05:26