Display snackbars when external storage permission isn't granted

This commit is contained in:
Shinokuni 2019-11-09 13:55:31 +01:00
parent 198e9ae299
commit 3bef12e7b5
4 changed files with 79 additions and 48 deletions

View File

@ -6,7 +6,6 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application <application

View File

@ -7,6 +7,7 @@ import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.provider.Settings;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
@ -25,6 +26,7 @@ import com.readrops.app.activities.ManageFeedsFoldersActivity;
import com.readrops.app.database.entities.account.Account; import com.readrops.app.database.entities.account.Account;
import com.readrops.app.database.entities.account.AccountType; import com.readrops.app.database.entities.account.AccountType;
import com.readrops.app.utils.OPMLMatcher; import com.readrops.app.utils.OPMLMatcher;
import com.readrops.app.utils.Utils;
import com.readrops.app.viewmodels.AccountViewModel; import com.readrops.app.viewmodels.AccountViewModel;
import com.readrops.readropslibrary.opml.OPMLParser; import com.readrops.readropslibrary.opml.OPMLParser;
import com.readrops.readropslibrary.opml.model.OPML; import com.readrops.readropslibrary.opml.model.OPML;
@ -157,6 +159,8 @@ public class AccountSettingsFragment extends PreferenceFragmentCompat {
.show(); .show();
} }
// region opml parsing
private void openOPMLFile() { private void openOPMLFile() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE); intent.addCategory(Intent.CATEGORY_OPENABLE);
@ -165,6 +169,48 @@ public class AccountSettingsFragment extends PreferenceFragmentCompat {
startActivityForResult(intent, OPEN_OPML_FILE_REQUEST); startActivityForResult(intent, OPEN_OPML_FILE_REQUEST);
} }
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == OPEN_OPML_FILE_REQUEST && resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
MaterialDialog dialog = new MaterialDialog.Builder(getActivity())
.title(R.string.opml_processing)
.content(R.string.operation_takes_time)
.progress(true, 100)
.cancelable(false)
.show();
parseOPMLFile(uri, dialog);
}
super.onActivityResult(requestCode, resultCode, data);
}
private void parseOPMLFile(Uri uri, MaterialDialog dialog) {
OPMLParser.parse(uri, getContext())
.flatMapCompletable(opml -> viewModel.insertOPMLFoldersAndFeeds(opml))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableCompletableObserver() {
@Override
public void onComplete() {
dialog.dismiss();
}
@Override
public void onError(Throwable e) {
dialog.dismiss();
displayErrorMessage();
}
});
}
//endregion
//region opml export
private void exportAsOPMLFile() { private void exportAsOPMLFile() {
try { try {
String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(); String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
@ -185,7 +231,8 @@ public class AccountSettingsFragment extends PreferenceFragmentCompat {
outputStream.close(); outputStream.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); Log.e(TAG, e.getMessage());
displayErrorMessage();
} }
}) })
.subscribe(new DisposableCompletableObserver() { .subscribe(new DisposableCompletableObserver() {
@ -196,78 +243,57 @@ public class AccountSettingsFragment extends PreferenceFragmentCompat {
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
Log.d(TAG, "onError: ");
} }
}); });
} catch (Exception e) { } catch (Exception e) {
Log.d(TAG, e.getMessage()); Log.e(TAG, e.getMessage());
displayErrorMessage();
} }
} }
private boolean isExternalStoragePermissionGranted() { private boolean isExternalStoragePermissionGranted() {
return ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && return ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
} }
private void requestExternalStoragePermission() { private void requestExternalStoragePermission() {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST); requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST);
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == OPEN_OPML_FILE_REQUEST && resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
MaterialDialog dialog = new MaterialDialog.Builder(getActivity())
.title(R.string.opml_processing)
.content(R.string.operation_takes_time)
.progress(true, 100)
.cancelable(false)
.show();
parseOPMLFile(uri, dialog);
}
super.onActivityResult(requestCode, resultCode, data);
} }
@Override @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == WRITE_EXTERNAL_STORAGE_REQUEST) { if (requestCode == WRITE_EXTERNAL_STORAGE_REQUEST) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) { if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
//if (shouldShowRequestPermissionRationale(permissions[0]))
if (shouldShowRequestPermissionRationale(permissions[0])) {
Utils.showSnackBarWithAction(getView(), getString(R.string.external_storage_opml_export),
getString(R.string.try_again), v -> requestExternalStoragePermission());
} else {
Utils.showSnackBarWithAction(getView(), getString(R.string.external_storage_opml_export),
getString(R.string.permissions), v -> {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", getContext().getPackageName(), null));
getContext().startActivity(intent);
});
}
} else { } else {
exportAsOPMLFile(); exportAsOPMLFile();
} }
} }
super.onRequestPermissionsResult(requestCode, permissions, grantResults); super.onRequestPermissionsResult(requestCode, permissions, grantResults);
} }
private void parseOPMLFile(Uri uri, MaterialDialog dialog) { //endregion
OPMLParser.parse(uri, getContext())
.flatMapCompletable(opml -> viewModel.insertOPMLFoldersAndFeeds(opml))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableCompletableObserver() {
@Override
public void onComplete() {
dialog.dismiss();
}
@Override
public void onError(Throwable e) {
dialog.dismiss();
private void displayErrorMessage() {
new MaterialDialog.Builder(getActivity()) new MaterialDialog.Builder(getActivity())
.title(R.string.processing_file_failed) .title(R.string.processing_file_failed)
.neutralText(R.string.cancel) .neutralText(R.string.cancel)
.iconRes(R.drawable.ic_error) .iconRes(R.drawable.ic_error)
.show(); .show();
} }
});
}
} }

View File

@ -99,5 +99,8 @@
<string name="processing_file_failed">Une erreur s\'est produite lors du traitement du fichier</string> <string name="processing_file_failed">Une erreur s\'est produite lors du traitement du fichier</string>
<string name="import_opml">Importer un fichier OPML</string> <string name="import_opml">Importer un fichier OPML</string>
<string name="export_feeds_folders_opml">Exporter les flux et les dossiers dans un fichier OPML</string> <string name="export_feeds_folders_opml">Exporter les flux et les dossiers dans un fichier OPML</string>
<string name="external_storage_opml_export">L\'export des soubscriptions nécessite l\'accès au stockage</string>
<string name="try_again">Réessayer</string>
<string name="permissions">Permissions</string>
</resources> </resources>

View File

@ -108,4 +108,7 @@
<string name="import_opml">Import OPML file</string> <string name="import_opml">Import OPML file</string>
<string name="export_feeds_folders_opml">Export feeds and folders to an OPML file</string> <string name="export_feeds_folders_opml">Export feeds and folders to an OPML file</string>
<string name="subscriptions" translatable="false">Subscriptions</string> <string name="subscriptions" translatable="false">Subscriptions</string>
<string name="external_storage_opml_export">Subscriptions export needs external storage permission</string>
<string name="try_again">Try again</string>
<string name="permissions">Permissions</string>
</resources> </resources>