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

Release 1.9.0 preparation #19

Merged
merged 7 commits into from
Oct 4, 2019
Merged
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
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


# RcloneExplorer
[![Packagist](https://img.shields.io/packagist/l/doctrine/orm.svg)](https://github.com/x0b/rcloneExplorer/blob/master/LICENSE) [![Github Releases](https://img.shields.io/github/downloads/x0b/rcloneExplorer/total.svg)](https://github.com/x0b/rcloneExplorer/master/releases) [![GitHub release](https://img.shields.io/github/release-pre/x0b/rcloneExplorer)](https://github.com/x0b/rcloneExplorer/releases/latest) [![GitHub release](https://img.shields.io/github/v/release/x0b/rcloneExplorer?include_prereleases)](https://github.com/x0b/rcloneExplorer/releases/latest)
[![license: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://github.com/x0b/rcloneExplorer/blob/master/LICENSE) [![Github Releases](https://img.shields.io/github/downloads/x0b/rcloneExplorer/total.svg)](https://github.com/x0b/rcloneExplorer/releases) [![GitHub release](https://img.shields.io/github/v/release/x0b/rcloneExplorer?include_prereleases)](https://github.com/x0b/rcloneExplorer/releases/latest)

rclone explorer for Android

Expand All @@ -26,33 +26,33 @@ Features
- Customizable primary and accent colors
- Configuration
- Import and export rclone configuration files
- Encrypted configurations
- Encrypted configurations (import only)
- Platform support
- Supports ARM and x86 devices
- Supports SDK 21+ (Lollipop 5.0)
- Supports Storage Access Framework (SAF) ([see docs](https://github.com/x0b/rcloneExplorer/wiki#adding-local-storage-saf))

Roadmap
------------
Note that these plans are subject to change and might not materialize completely or at all.

#### Current Version (1.8.2)
- Update to rclone 1.49.3
- Android 10: Streaming now works with third party players (MX Player, VLC)
- AndroidX migration
- AndroidTV improvements (launcher & intent integration)
- Support more external storage options when selecting files for upload
- Fixed crash when selecting inaccessible storage location
#### Current Version (1.9.0)
- Update rclone to 1.49.4
- Preview of Storage Access Layer for rclone (allows access to Storage Access Framework locations from rclone/rcloneExplorer)
- Added support for creating union remotes
- Fix: Crash when no compatible streaming app is installed
- Fix: Crash on LoadingDialog (#7)
- Fix: Crash on Android 5.1.1 for remotes with time zones (#10)
- Fix: Crash in hide remotes dialog (#13)

#### Next Version
- Preview of Storage Access Layer for rclone (allows access to Storage Access Framework locations from rclone/rcloneExplorer)
- New remotes
- New SAF implementation for much faster directory access
- Bug fixes

#### Next Month(s)
- Bug fixes
- Configuration dialogs for more remotes
- Android 10 target version updates
- AndroidTV improvements
- Virtual Content Provider (allows access to rclone remotes from other apps)

#### Next Year
- Reasonably regular updates of rclone
Expand All @@ -79,6 +79,10 @@ Known Issues
------------
- OneDrive remotes can no longer be configured in the app and must be imported. You can configure them in Termux, copy the configuration file to an accessible destination and import from there.

Contributing
------------
You can contribute by reporting any bugs and errors using the [issue tracker](https://github.com/x0b/rcloneExplorer/issues). Pull requests are welcome, but you have to accept a small CLA to ensure license compatibility.

Credits/Libraries
-----------------
- [rclone](https://github.com/rclone/rclone) - "rsync for cloud storage"
Expand Down
35 changes: 22 additions & 13 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ android {
applicationId 'ca.pkay.rcloneexplorer.x0b'
minSdkVersion 21
targetSdkVersion 29
versionCode 31
versionName '1.7.6'
versionCode 32
versionName '1.9.0'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
Expand All @@ -23,9 +23,6 @@ android {
}
}
sourceSets {
main {
jniLibs.srcDirs = ["lib/x86"]
}
x86 {
jniLibs.srcDirs = ["lib/x86"]
}
Expand Down Expand Up @@ -78,27 +75,39 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.core:core:1.2.0-alpha04'
implementation 'androidx.core:core:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.1.0-alpha10'
implementation 'androidx.browser:browser:1.2.0-alpha07'
implementation 'androidx.browser:browser:1.0.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta04'
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.leinardi.android:speed-dial:2.0.0'
implementation 'us.feras.mdv:markdownview:1.1.0'
implementation 'jp.wasabeef:recyclerview-animators:2.3.0'
implementation 'com.github.GrenderG:Toasty:1.3.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.github.bumptech.glide:glide:4.7.1'
// Firebase & Crashlytics
implementation 'com.google.firebase:firebase-core:17.2.0'
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
implementation 'com.google.firebase:firebase-messaging:20.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta04'
// Thumbnails
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
// REST Client
implementation 'com.squareup.okhttp3:okhttp:4.2.0'
debugImplementation 'com.squareup.okhttp3:logging-interceptor:4.2.0'
// JSON
implementation 'com.fasterxml.jackson.core:jackson-core:2.9.9'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.9.9'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.9'
// Timestmps
implementation 'com.github.x0b:rfc3339parser:2.0.0'
// SAF/WebDAV
implementation project(':safdav')
implementation 'org.nanohttpd:nanohttpd:2.3.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
// TEST
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.3.0-alpha02'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha02'
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta04'
}

apply plugin: 'com.google.gms.google-services'
11 changes: 11 additions & 0 deletions app/src/main/assets/changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
### 1.9.0
* **New:** Update to Rclone v1.49.4
* **New:** Preview of Storage Access Layer for rclone (allows access to Storage Access Framework locations from rclone/rcloneExplorer)
* **New:** Support for creating union remotes
* **Fix:** Crash when no compatible streaming app is installed
* **Fix:** Crash on LoadingDialog
* **Fix:** Crash on Android 5.1.1 for remotes with time zones
* **Fix:** Crash in hide remotes dialog

***

### 1.8.2
* **New:** Update to Rclone v1.49.3
* **New:** Improved Android 10 support: Streaming now works with third party players
Expand Down
23 changes: 20 additions & 3 deletions app/src/main/assets/contributors.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
### Maintainer Credit
### Intro
This application was created by [Patryk Kaczmarkiewicz](https://github.com/kaczmarkiewiczp). Your current build is maintained by [x0b](https://github.com/x0b).

### Github contributors
All these people have contributed towards making rcloneExplorer better:
Additionally, these people have contributed towards making rcloneExplorer better:

* [buywetwok](https://github.com/buywetwok)
* [davsinghm](https://github.com/davsinghm)

Join us now on Github.
[Join us now on Github.](https://github.com/x0b/rcloneExplorer)

## License

Copyright (C) 2018-2019 x0b <github.com/x0b>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
169 changes: 166 additions & 3 deletions app/src/main/java/ca/pkay/rcloneexplorer/AboutActivity.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,49 @@
package ca.pkay.rcloneexplorer;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;

import static ca.pkay.rcloneexplorer.StartActivity.tryStartActivity;


public class AboutActivity extends AppCompatActivity {

private static final String TAG = "AboutActivity";
private OkHttpClient client;
private Handler handler;
private Button serverVersionView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand All @@ -37,6 +60,7 @@ protected void onCreate(Bundle savedInstanceState) {
Rclone rclone = new Rclone(this);

((TextView)findViewById(R.id.version_number)).setText(BuildConfig.VERSION_NAME);
updateUpdateButton();
((TextView)findViewById(R.id.rclone_version)).setText(rclone.getRcloneVersion());

findViewById(R.id.changelog).setOnClickListener(new View.OnClickListener() {
Expand Down Expand Up @@ -75,6 +99,12 @@ public void onClick(View v) {
openAuthorGitHubLink();
}
});
findViewById(R.id.maintainer_github_link).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openMaintainerGithubLink();
}
});
}

private void applyTheme() {
Expand All @@ -96,6 +126,13 @@ private void applyTheme() {
setTaskDescription(taskDesc);
}

@Override
protected void onResume() {
super.onResume();
handler = new UpdateMessageHandler();
checkForUpdate(false);
}

@Override
public boolean onSupportNavigateUp() {
onBackPressed();
Expand Down Expand Up @@ -139,4 +176,130 @@ private void openAuthorGitHubLink() {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.github_author_url)));
tryStartActivity(this, browserIntent);
}

private void openMaintainerGithubLink() {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.github_maintainer_url)));
tryStartActivity(this, browserIntent);
}

private void openReleaseLink() {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.app_latest_release_url)));
tryStartActivity(this, browserIntent);
}

private void checkForUpdate(boolean force) {
Context context = this;
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
if(!force && !sharedPreferences.getBoolean(getString(R.string.pref_key_app_updates), true)){
Log.i(TAG, "checkForUpdate: Not checking, updates are disabled");
return;
}
client = new OkHttpClient();
long lastUpdateCheck = sharedPreferences.getLong(context.getString(R.string.pref_key_update_last_check), 0);

long now = System.currentTimeMillis();
if(lastUpdateCheck + 1000 * 60 * 60 * 12 > now){
Log.i(TAG, "checkForUpdate: recent check to new, not checking for updates");
return;
}

String url = context.getString(R.string.app_relase_api_url);
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new UpdateRequestResultHandler(
sharedPreferences, context.getString(R.string.pref_key_update_last_check),
context.getString(R.string.pref_key_update_release_version),
handler));
}

private static class UpdateRequestResultHandler implements Callback {

private SharedPreferences sharedPreferences;
private String lastUpdateKey;
private String serverVersionKey;
private Handler updateHandler;

public UpdateRequestResultHandler(SharedPreferences sharedPreferences, String lastUpdateKey, String serverVersionKey, Handler updateHandler) {
this.sharedPreferences = sharedPreferences;
this.lastUpdateKey = lastUpdateKey;
this.serverVersionKey = serverVersionKey;
this.updateHandler = updateHandler;
}

@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.w(TAG, "onFailure: Update check failed", e);
updateLastUpdateRequest();
}

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
updateLastUpdateRequest();
try {
JSONObject json = new JSONObject(response.body().string());
String tagName = json.getString("tag_name");
String currentVersion = BuildConfig.VERSION_NAME.split("-")[0];
if(tagName.contains(currentVersion)){
Log.i(TAG, "onResponse: App is up-to-date");
sharedPreferences.edit().putString(BuildConfig.VERSION_NAME, tagName).apply();
} else {
Log.i(TAG, "onResponse: App version != release");
sharedPreferences.edit().putString(serverVersionKey, tagName).apply();
updateHandler.sendMessage(new Message());
}
} catch (JSONException e) {
Log.e(TAG, "onResponse: Could not read release ", e);
}
}

private void updateLastUpdateRequest(){
long now = System.currentTimeMillis();
sharedPreferences.edit().putLong(lastUpdateKey, now).apply();

}
}

private void updateUpdateButton(){
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String serverVersion = preferences.getString(getString(R.string.pref_key_update_release_version), BuildConfig.VERSION_NAME);
serverVersionView = findViewById(R.id.server_version_number);
if(!BuildConfig.VERSION_NAME.equals(serverVersion)){
serverVersionView.setText("Update " + serverVersion);
serverVersionView.setVisibility(View.VISIBLE);
serverVersionView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
openReleaseLink();
}
});
} else {
serverVersionView.setText(getText(R.string.about_check_updates));
serverVersionView.setVisibility(View.VISIBLE);
serverVersionView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
checkForUpdate(true);
}
});
}

serverVersionView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
openReleaseLink();
}
});
}

@SuppressLint("HandlerLeak")
private class UpdateMessageHandler extends Handler {

public UpdateMessageHandler() {
super(Looper.getMainLooper());
}

@Override
public void handleMessage(@NonNull Message msg) {
updateUpdateButton();
}
}
}
Loading