1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2024-11-26 06:11:19 +00:00

Workaround cleanup of the folder marker by Huawei, Xiaomi firmware (fixes #131) (#363)

* WIP - preCreateFolderMarker

* Revert "WIP - preCreateFolderMarker"

This reverts commit 2a4db47f869334a0b4c7aab3073360e43cfbc218.

* Revert accidential syncthing upstream ref change

* Create .stfolder and DO_NOT_DELETE.txt within it (fixes #131)

* Refactor folder marker creation code into FolderActivity#preCreateFolderMarker (fixes #131)
This commit is contained in:
Catfriend1 2019-03-11 15:41:57 +01:00 committed by GitHub
parent dde8d24e0c
commit 7a12674a88
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -46,6 +46,8 @@ import com.nutomic.syncthingandroid.util.TextWatcherAdapter;
import com.nutomic.syncthingandroid.util.Util; import com.nutomic.syncthingandroid.util.Util;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.Map; import java.util.Map;
@ -85,9 +87,6 @@ public class FolderActivity extends SyncthingActivity {
private static final int FOLDER_TYPE_DIALOG_REQUEST =3456; private static final int FOLDER_TYPE_DIALOG_REQUEST =3456;
private static final int CHOOSE_FOLDER_REQUEST = 3459; private static final int CHOOSE_FOLDER_REQUEST = 3459;
private static final String FOLDER_MARKER_NAME = ".stfolder";
// private static final String IGNORE_FILE_NAME = ".stignore";
private ConfigRouter mConfig; private ConfigRouter mConfig;
private Folder mFolder; private Folder mFolder;
// Contains SAF readwrite access URI on API level >= Build.VERSION_CODES.LOLLIPOP (21) // Contains SAF readwrite access URI on API level >= Build.VERSION_CODES.LOLLIPOP (21)
@ -736,21 +735,7 @@ public class FolderActivity extends SyncthingActivity {
if (mIsCreateMode) { if (mIsCreateMode) {
Log.v(TAG, "onSave: Adding folder with ID = \'" + mFolder.id + "\'"); Log.v(TAG, "onSave: Adding folder with ID = \'" + mFolder.id + "\'");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && preCreateFolderMarker(mFolderUri, mFolder.path);
mFolderUri != null &&
mFolder.type.equals(Constants.FOLDER_TYPE_SEND_ONLY)) {
/**
* Normally, syncthing takes care of creating the ".stfolder" marker.
* This fails on newer android versions if the syncthing binary only has
* readonly access on the path and the user tries to configure a
* sendonly folder. To fix this, we'll precreate the marker using java code.
*/
DocumentFile dfFolder = DocumentFile.fromTreeUri(this, mFolderUri);
if (dfFolder != null) {
Log.v(TAG, "onSave: Creating new directory " + mFolder.path + File.separator + FOLDER_MARKER_NAME);
dfFolder.createDirectory(FOLDER_MARKER_NAME);
}
}
mConfig.addFolder(getApi(), mFolder); mConfig.addFolder(getApi(), mFolder);
finish(); finish();
return; return;
@ -786,6 +771,77 @@ public class FolderActivity extends SyncthingActivity {
return; return;
} }
private void preCreateFolderMarker(Uri uriFolderRoot, String absolutePath) {
/**
* Normally, syncthing takes care of creating the ".stfolder" marker.
* This fails on Android 5+ if the syncthing binary only has
* readonly access on the path and the user tries to configure a
* sendOnly folder. To fix this, we'll precreate the marker using java code.
*/
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
if (uriFolderRoot == null) {
Log.w(TAG, "preCreateFolderMarker: uriFolderRoot == null");
return;
}
// Derive DocumentFile handle from SAF tree Uri where we have write access.
DocumentFile dfFolder = DocumentFile.fromTreeUri(this, uriFolderRoot);
if (dfFolder == null) {
Log.w(TAG, "preCreateFolderMarker: dfFolder == null");
return;
}
// Marker directory name and full path.
final String FOLDER_MARKER_DIR_NAME = new Folder().markerName;
String strFolderMarkerDir = absolutePath + File.separator + FOLDER_MARKER_DIR_NAME;
// Create marker directory.
DocumentFile dfFolderMarkerDir = dfFolder.createDirectory(FOLDER_MARKER_DIR_NAME);
if (dfFolderMarkerDir == null) {
Log.w(TAG, "preCreateFolderMarker: Failed to create directory '" + strFolderMarkerDir + "'");
return;
}
Log.v(TAG, "preCreateFolderMarker: Created directory '" + strFolderMarkerDir + "'");
/**
* Name of the dummy file created within the marker directory.
* Creating the file is a workaround for issue #131 where manufacturer
* specific cleaning routines silently wipe out empty directories like
* the marker directory.
*/
final String DO_NOT_DELETE_FILE_NAME = "DO_NOT_DELETE";
String strDoNotDeleteFile = strFolderMarkerDir + File.separator + DO_NOT_DELETE_FILE_NAME;
// Create "DO_NOT_DELETE" file.
DocumentFile dfDoNotDeleteFile = dfFolderMarkerDir.createFile("text/plain", DO_NOT_DELETE_FILE_NAME);
if (dfDoNotDeleteFile == null) {
Log.w(TAG, "preCreateFolderMarker: Failed to create file '" + strDoNotDeleteFile + "' #1");
return;
}
Log.v(TAG, "preCreateFolderMarker: Created file '" + strDoNotDeleteFile + "'");
// Write "DO_NOT_DELETE" text content.
OutputStream outputStream = null;
try {
outputStream = getContentResolver().openOutputStream(dfDoNotDeleteFile.getUri());
outputStream.write(DO_NOT_DELETE_FILE_NAME.getBytes("ISO-8859-1"));
outputStream.flush();
} catch (IOException e) {
Log.e(TAG, "preCreateFolderMarker: Failed to create file '" + strDoNotDeleteFile + "' #2", e);
} finally {
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
Log.e(TAG, "preCreateFolderMarker: Failed to create file '" + strDoNotDeleteFile + "' #3", e);
}
}
}
private void showDiscardDialog(){ private void showDiscardDialog(){
mDiscardDialog = new AlertDialog.Builder(this) mDiscardDialog = new AlertDialog.Builder(this)
.setMessage(R.string.dialog_discard_changes) .setMessage(R.string.dialog_discard_changes)