Writing to external SD card in Android 5.0 and above

The only downside is that the computer shows that it’s still syncing (hangs at 95%) and the phone says it’s out of sync. But it’s not, all files/changes are synced correctly. I don’t know, seems to just work.

A new (I think) proposal for using the Android SAF from go without having to do any cross-language calls. This is going to be a little odd, but as far as I can tell it will work. The ingredients in this insane plan are:

  1. UNIX domain sockets, to which both Android Java and Go have access (I think), and, in particular, the ability to pass file descriptors across UNIX domain sockets.

  2. Some code in the syncthing-android service which knows how to drive the SAF in response to commands received across a socket connection.

  3. Some code in syncthing itself to provide a synthetic mountpoint; a filesystem driver in parallel to basicfs which knows how to translate requests for files below the mountpoint into commands on the socket.

Does this seem like a reasonable plan? I’d be happy to start prototyping if so.

I think you should not. Instead, add your mind to New Android app "Syncthing Lite"

So this should work in theory if you can pull it off, but I couldn’t find the right syscalls in java exposed to be able to send descriptors around.

From a quick glance, it seems that Syncthing Lite, while interesting, is lacking a scanner and so is further away from my goal of “sync to SD card” than some mucking about with file descriptors and sockets in syncthing / syncthing-android? Could you expand on your comment?

I fished around a little more and, yeah, it looks like they’re not plumbed up into Java, but people have had success using JNI bindings on Android for the requisite sendmsg() call. See, for example, https://github.com/PeterCxy/SocksDroid/blob/d572359ac55757e7956ff4806fea3fda70e8887f/app/src/main/jni/system.cpp . Golang has them plumbed through, too; see /src/syscall/syscall_unix_test.go 's TestUnixRightsRoundtrip. (The one link per message thing is a drag, though I understand why.)

Yeah, that will most likely work, but I don’t expect it to be easy, as you have to devise an RPC for creating files as well as opening existing ones, make sure the pipe is always there, etc, which might require a separate service. How do you start that service from go, etc.

The idea is that a native java implementation of syncthing is potentially a better place to spend the effort.

I have never used unix sockets myself, so I’m not sure if those would work. Maybe an HTTP api could also be used instead?

And yes, syncthing-lite is only meant to be a client, without any functionality for synchronization. It might be possible to add that, but it would probably involve a lot of extra effort.

No, you pass file handles between processes you need to use special syscalls via a unix socket (or potentially a pipe).

not sure where everyone is at with this, but the on version 0.9.11 (4121) on Android I was able to get syncthing to sync one way to the external SD card on my LGV20 running 7.0 Nougat while running as root. the only problem was I couldn’t do it consistently in that after enabling root and restarting syncthing, I was able to get a complete sync once. after exiting syncthing any attempts to start it up again resulted in a failure to read the config. I’ve tried changing the ownership of all the files in /data/data/com.nutomic.syncthingadroid, but no dice leaving the only way to restore everything from a TitaniumBackup. even copying this folder’s contents elsewhere and restoring it after would not work for some reason. now on version 0.10.2 and all the versions in between, I can enable/disable root entering and exiting syncthing with no problems, however with root enabled it gets stuck at the “Loading” stage in the beginning never pulling up the list of directories I’ve set for sync. anyone have any suggestions?

@dimmok yes, root option is attributed experimental, because nobody found time to get it working properly yet.

Since you already rooted your device, you might have some success with ExtSD fix. v1.9b worked well for a couple of LineageOS installations here lately.

Is it able to access external card via Android NDK ?

It should be a simple task to implement go wrapper over C++ (NDK) code. I think porting syncthing to android was much more harder to do.

The issue talks about accessing internal storage which we don’t have problems accessing. It states that you only needs permissions to access external storage, which was perhaps true in 2012, but is no longer true.

Will not insist, as I’m not Android programmer, seems this restriction is done in Dalik/ARM virtual machine, not by Linux kernel/SELinux. At least, I can do “shell@E5333:/storage/sdcard1 $ echo > a” from shell. I belive, utilities like “echo” and even Dalvi/ARM are build with Adnoid NDK, and they have write ablity to external sd. It’s just an opinion, sorry if I’m wrong.

Thanks, it works! And I also found out the updates on the manifest file will only take effect after you re-install the app. 2015-06-16

Well, compile a Go binary and see if you can get a go binary to do that without root.

As with all things Android I expect there is variation between ROMs. Maybe yours doesn’t enforce this. I’m pretty sure other variants do, or this issue would have been a non issue. There’s also no indication the comment you quote relates to 5.0+. The rest of the post predates 5.0 by years.

Hi all, I read through the entire thing and wanted to add that I was also able to get it to sync to my SD card without rooting my device or adding the card as internal or adopted. Below will be to add my experience after following the steps of the post from AnnoyingDuck in December 2017. Also ran using the WebGui where possible as advised by Cooad in April 2017 on this thread.

My Phone: Moto G5S plus Running Android 7.1.1 Not Rooted SD card is formatted as external, haven’t done anything besides put it in my phone.

Followed Steps 1, 2 and 3 from AnnoyingDuck’s post with no problem. I opted to not have my phone and computer sync just yet though, and instead wanted to test making a folder on my external SD card via SyncThing. As Annoyingduck said you do want to use the Advanced Folder Picker option.

When I went add the folder Syncthing gave me the warning: Android version does not allow syncing to external SD card etc. but somehow after plugging that path in a couple times, it was suddenly an option in the list of possible paths when I backed out and tried to create a folder again.

I chose the SD card option, named the folder Music (which matched the Music folder I had set up to sync on my computer). Went back to my computer, told it to share the folder with my phone, received the request. I guess since the names of the files were both music it just recognized that was where it was supposed to go so it started syncing the computer to the folder I’d created.

In case you aren’t extremely technical and have no idea where to get your SD file path from, an app I had used in the past called OneSync (used to sync OneDrive) showed it. So I redownloaded that and wrote down my file path.

Sorry if that’s a lot, I’m not very technically savy, I just hoped this would help others like me who don’t know much beyond how to follow instructions found on the internet to a certain degree.

2 Likes

On my device Sony Xperia Z3 compact with Android 6.0.1 I test Syncthing Android v1.1.0 from Google Play Store.

If I use a path like /storage/0000-0000/Test/Syncthing, when I try to change “Folder Type” I receive this message “Your Android versiononly grants Syncthing readonly access to the selected folder”. But I see that Syncthing create the “.stfolder”, so it can write to the SD card to crate “.stfolder”.

I set up the the folder to sync to PC. I set up by web interface the folder as “Send&Receive”. When it try to sync reply, all file are in status “… acces denied”, and it can’t sync file.

I thing you may investigate on why “.stfolder” can create, but the other file and folder not.

Bye

The explanation is in there: