Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement SAF provider. #76

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,26 @@ on:

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: set up JDK 1.8
- name: set up JDK
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Set up Go 1.14
- name: Set up Go
uses: actions/setup-go@v1
with:
go-version: 1.14
id: go
# https://github.com/actions/virtual-environments/issues/578
- name: Fix missing NDK dependency
run: echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;20.0.5594570"
- name: Build rclone
run: ./gradlew buildNative -p rclone
- name: Configure Android SDK
run: |
BUILD_TOOLS_VERSION="$(grep -E "^io\.github\.x0b\.rcx\.buildToolsVersion=" gradle.properties | cut -d'=' -f2)"
NDK_VERSION="$(grep -E "^io\.github\.x0b\.rcx\.ndkVersion=" gradle.properties | cut -d'=' -f2)"

yes | sudo "${ANDROID_HOME}/tools/bin/sdkmanager" --licenses
sudo "${ANDROID_HOME}/tools/bin/sdkmanager" "build-tools;${BUILD_TOOLS_VERSION}" "ndk;${NDK_VERSION}"
- name: Build app
run: ./gradlew assembleOssDebug
- name: Upload APK
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
*.apk
*.ap_

# Built libraries
*.so

# Files for the ART/Dalvik VM
*.dex

Expand Down
36 changes: 29 additions & 7 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
apply plugin: 'com.android.application'
if (!getGradle().getStartParameter().getTaskRequests().toString().toLowerCase().contains("oss")) {
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'

for (String taskName : getGradle().getStartParameter().getTaskNames()) {
if (taskName.endsWith('RcxDebug') || taskName.endsWith('RcxRelease')) {
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
break
}
}

tasks.whenTaskAdded { task ->
// We defer the build of rclone just before the assemble stage of the
// main app, so that Android Studio displays a convenient clickable
// error message that allows to install the proper NDK version
// directly from the SDK manager.
if (task.name.startsWith('assemble')) {
task.dependsOn(':rclone:buildNative')
}
}

android {
buildToolsVersion project.properties['io.github.x0b.rcx.buildToolsVersion']
ndkVersion project.properties['io.github.x0b.rcx.ndkVersion']

signingConfigs {
github_x0b {
keyAlias 'github_x0b'
Expand All @@ -18,6 +35,10 @@ android {
versionCode 170 // last digit is reserved for ABI, only ever end on 0!
versionName '1.11.4'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

def documentsAuthority = applicationId + '.documents'
manifestPlaceholders = [documentsAuthority: documentsAuthority]
buildConfigField "String", "DOCUMENTS_AUTHORITY", "\"${documentsAuthority}\""
}

buildTypes {
Expand Down Expand Up @@ -63,10 +84,11 @@ android {
}

project.ext.versionCodes = [
'armeabi-v7a': 6,
'arm64-v8a': 7,
'x86': 8,
'x86_64': 9]
'armeabi-v7a': 6,
'arm64-v8a': 7,
'x86': 8,
'x86_64': 9
]

android.applicationVariants.all { variant ->
variant.outputs.each { output ->
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@
android:resource="@xml/file_provider_paths" />
</provider>

<provider
android:name=".SAFProvider.SAFProvider"
android:authorities="${documentsAuthority}"
android:grantUriPermissions="true"
android:exported="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>

<activity
android:name=".AboutActivity"
android:label="@string/title_activity_about"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ public static void populateAppShortcuts(Context context, List<RemoteItem> remote
Set<String> shortcutSet = new HashSet<>();
List<ShortcutInfo> shortcutInfoList = new ArrayList<>();

RemoteItem.prepareDisplay(context, remotes);
for (RemoteItem remoteItem : remotes) {
String id = getUniqueIdFromString(remoteItem.getName());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ protected void onPreExecute() {
@Override
protected List<FileItem> doInBackground(Void... voids) {
List<FileItem> fileItemList;
fileItemList = rclone.getDirectoryContent(remote, directoryObject.getCurrentPath(), startAtRoot);
fileItemList = rclone.ls(remote, directoryObject.getCurrentPath(), startAtRoot);
return fileItemList;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
Expand Down Expand Up @@ -86,7 +85,6 @@
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.URL;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -1659,7 +1657,7 @@ protected void onPreExecute() {
@Override
protected List<FileItem> doInBackground(Void... voids) {
List<FileItem> fileItemList;
fileItemList = rclone.getDirectoryContent(remote, directoryObject.getCurrentPath(), startAtRoot);
fileItemList = rclone.ls(remote, directoryObject.getCurrentPath(), startAtRoot);
return fileItemList;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
Expand All @@ -25,6 +26,7 @@
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import ca.pkay.rcloneexplorer.AppShortcutsHelper;
import ca.pkay.rcloneexplorer.BuildConfig;
import ca.pkay.rcloneexplorer.Dialogs.RemotePropertiesDialog;
import ca.pkay.rcloneexplorer.Items.RemoteItem;
import ca.pkay.rcloneexplorer.MainActivity;
Expand All @@ -33,7 +35,6 @@
import ca.pkay.rcloneexplorer.RecyclerViewAdapters.RemotesRecyclerViewAdapter;
import ca.pkay.rcloneexplorer.RemoteConfig.RemoteConfig;
import com.leinardi.android.speeddial.SpeedDialView;
import java9.util.stream.StreamSupport;
import jp.wasabeef.recyclerview.animators.LandingAnimator;

import java.util.ArrayList;
Expand Down Expand Up @@ -298,12 +299,17 @@ private void refreshRemotes() {
if (null != recyclerViewAdapter) {
recyclerViewAdapter.newData(remotes);
}
refreshSAFRoots();
}

private void refreshSAFRoots() {
Uri rootsUri = DocumentsContract.buildRootsUri(BuildConfig.DOCUMENTS_AUTHORITY);
context.getContentResolver().notifyChange(rootsUri, null);
}

private List<RemoteItem> filterRemotes() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
Set<String> hiddenRemotes = sharedPreferences.getStringSet(getString(R.string.shared_preferences_hidden_remotes), new HashSet<>());
Set<String> renamedRemotes = sharedPreferences.getStringSet(getString(R.string.pref_key_renamed_remotes), new HashSet<>());
remotes = rclone.getRemotes();
if (hiddenRemotes != null && !hiddenRemotes.isEmpty()) {
ArrayList<RemoteItem> toBeHidden = new ArrayList<>();
Expand All @@ -315,13 +321,6 @@ private List<RemoteItem> filterRemotes() {
remotes.removeAll(toBeHidden);
}
Collections.sort(remotes);
for(RemoteItem item : remotes) {
if(renamedRemotes.contains(item.getName())) {
String displayName = sharedPreferences.getString(
getString(R.string.pref_key_renamed_remote_prefix, item.getName()), item.getName());
item.setDisplayName(displayName);
}
}
return remotes;
}

Expand Down Expand Up @@ -470,21 +469,14 @@ private void renameRemote(final RemoteItem remoteItem) {
builder = new AlertDialog.Builder(context);
}

final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
final EditText remoteNameEdit = new EditText(context);
String initialText = remoteItem.getDisplayName();
remoteNameEdit.setText(initialText);
builder.setView(remoteNameEdit);
builder.setNegativeButton(R.string.cancel, null);
builder.setPositiveButton(R.string.select, (dialog, which) -> {
String displayName = remoteNameEdit.getText().toString();
Set<String> renamedRemotes = pref.getStringSet(getString(R.string.pref_key_renamed_remotes), new HashSet<>());
renamedRemotes.add(remoteItem.getName());
pref.edit()
.putString(getString(R.string.pref_key_renamed_remote_prefix, remoteItem.getName()), displayName)
.putStringSet(getString(R.string.pref_key_renamed_remotes), renamedRemotes)
.apply();
remoteItem.setDisplayName(displayName);
String newName = remoteNameEdit.getText().toString();
rclone.renameRemote(remoteItem.getName(), newName);
refreshRemotes();
});
builder.setTitle(R.string.rename_remote);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
breadcrumbView = ((FragmentActivity)context).findViewById(R.id.breadcrumb_view);
breadcrumbView.setOnClickListener(this);
breadcrumbView.setVisibility(View.VISIBLE);
breadcrumbView.addCrumb(remote.getName(), "//" + remote.getName());
breadcrumbView.addCrumb(remote.getDisplayName(), "//" + remote.getName());

final TypedValue accentColorValue = new TypedValue ();
context.getTheme().resolveAttribute (R.attr.colorAccent, accentColorValue, true);
Expand Down Expand Up @@ -513,7 +513,7 @@ protected void onPreExecute() {
@Override
protected List<FileItem> doInBackground(Void... voids) {
List<FileItem> fileItemList;
fileItemList = rclone.getDirectoryContent(remote, directoryObject.getCurrentPath(), startAtRoot);
fileItemList = rclone.ls(remote, directoryObject.getCurrentPath(), startAtRoot);
return fileItemList;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
((FragmentActivity) context).setTitle(getString(R.string.remotes_toolbar_title));
Rclone rclone = new Rclone(getContext());
remotes = rclone.getRemotes();
RemoteItem.prepareDisplay(getContext(), remotes);
Collections.sort(remotes);
}

Expand Down
31 changes: 8 additions & 23 deletions app/src/main/java/ca/pkay/rcloneexplorer/Items/RemoteItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ public class RemoteItem implements Comparable<RemoteItem>, Parcelable {
private boolean isDrawerPinned;
private String displayName;

public RemoteItem(String name, String type) {
public RemoteItem(String name, String displayName, String type) {
this.name = name;
this.displayName = displayName;
this.typeReadable = type;
this.type = getTypeFromString(type);
}
Expand Down Expand Up @@ -169,6 +170,8 @@ public String getName() {
return name;
}

public String getDisplayName() { return displayName; }

public int getType() {
return type;
}
Expand Down Expand Up @@ -249,27 +252,6 @@ public boolean isRemoteType(int ...remotes) {
return isSameType;
}

public String getDisplayName() {
return displayName != null ? displayName : name;
}

public void setDisplayName(String displayName) {
this.displayName = displayName;
}

public static List<RemoteItem> prepareDisplay(Context context, List<RemoteItem> items) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
Set<String> renamedRemotes = pref.getStringSet(context.getString(R.string.pref_key_renamed_remotes), new HashSet<>());
for(RemoteItem item : items) {
if(renamedRemotes.contains(item.name)) {
String displayName = pref.getString(
context.getString(R.string.pref_key_renamed_remote_prefix, item.name), item.name);
item.displayName = displayName;
}
}
return items;
}

private int getTypeFromString(String type) {
switch (type) {
case SafConstants.SAF_REMOTE_NAME:
Expand Down Expand Up @@ -407,7 +389,10 @@ public int compareTo(@NonNull RemoteItem remoteItem) {
} else if (!this.isPinned && remoteItem.isPinned) {
return 1;
}
return getDisplayName().toLowerCase().compareTo(remoteItem.getDisplayName().toLowerCase());

String self = getDisplayName().toLowerCase();
String other = remoteItem.getDisplayName().toLowerCase();
return self.compareTo(other);
}

@Override
Expand Down
Loading