Skip to content

Commit

Permalink
Request storage permission when saving image (fixes #297)
Browse files Browse the repository at this point in the history
  • Loading branch information
QuantumBadger committed Jun 24, 2016
1 parent ec2771a commit 375b452
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 60 deletions.
1 change: 1 addition & 0 deletions assets/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Material Design
Imgur upload support
Experimental Tor support (thanks to SpotComms)
Fixed image saving on Android Marshmallow

70/1.9.3.4
Fixed album swiping
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,21 @@
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import info.guardianproject.netcipher.proxy.OrbotHelper;
import org.quantumbadger.redreader.R;
import org.quantumbadger.redreader.cache.CacheDownload;
import org.quantumbadger.redreader.common.General;
import org.quantumbadger.redreader.common.PrefsUtility;
import org.quantumbadger.redreader.http.okhttp.OKHTTPBackend;
import info.guardianproject.netcipher.proxy.OrbotHelper;

import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class BaseActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {

Expand All @@ -37,6 +44,14 @@ public class BaseActivity extends AppCompatActivity implements SharedPreferences

private static boolean closingAll = false;

private final AtomicInteger mPermissionRequestIdGenerator = new AtomicInteger();
private final HashMap<Integer, PermissionCallback> mPermissionRequestCallbacks = new HashMap<>();

public interface PermissionCallback {
void onPermissionGranted();
void onPermissionDenied();
}

public void closeAllExceptMain() {
closingAll = true;
closeIfNecessary();
Expand Down Expand Up @@ -77,6 +92,49 @@ private void closeIfNecessary() {
}
}

public void requestPermissionWithCallback(
@NonNull final String permission,
@NonNull final PermissionCallback callback) {

General.checkThisIsUIThread();

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

if(checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) {
callback.onPermissionGranted();

} else {
final int requestCode = mPermissionRequestIdGenerator.incrementAndGet();
mPermissionRequestCallbacks.put(requestCode, callback);
requestPermissions(new String[]{permission}, requestCode);
}

} else {
callback.onPermissionGranted();
}
}

@Override
public void onRequestPermissionsResult(
final int requestCode,
@NonNull final String[] permissions,
@NonNull final int[] grantResults) {

final PermissionCallback callback = mPermissionRequestCallbacks.remove(requestCode);

if(callback != null) {
if(permissions.length != 1) {
throw new RuntimeException("Unexpected permission result");
}

if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
callback.onPermissionGranted();
} else {
callback.onPermissionDenied();
}
}
}

private void setOrientationFromPrefs() {
PrefsUtility.ScreenOrientation orientation = PrefsUtility.pref_behaviour_screen_orientation(this, sharedPreferences);
if (orientation == PrefsUtility.ScreenOrientation.AUTO)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package org.quantumbadger.redreader.reddit.prepared;

import android.Manifest;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
Expand All @@ -36,11 +37,11 @@
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;

import org.apache.commons.lang3.StringEscapeUtils;
import org.quantumbadger.redreader.R;
import org.quantumbadger.redreader.account.RedditAccount;
import org.quantumbadger.redreader.account.RedditAccountManager;
import org.quantumbadger.redreader.activities.BaseActivity;
import org.quantumbadger.redreader.activities.BugReportActivity;
import org.quantumbadger.redreader.activities.CommentReplyActivity;
import org.quantumbadger.redreader.activities.MainActivity;
Expand Down Expand Up @@ -333,89 +334,117 @@ public void onClick(DialogInterface dialog, int which) {

case SAVE_IMAGE: {

final RedditAccount anon = RedditAccountManager.getAnon();

LinkHandler.getImageInfo(activity, post.src.getUrl(), Constants.Priority.IMAGE_VIEW, 0, new GetImageInfoListener() {

@Override
public void onFailure(final @CacheRequest.RequestFailureType int type, final Throwable t, final Integer status, final String readableMessage) {
final RRError error = General.getGeneralErrorForFailure(activity, type, t, status, post.src.getUrl());
General.showResultDialog(activity, error);
}

((BaseActivity)activity).requestPermissionWithCallback(Manifest.permission.WRITE_EXTERNAL_STORAGE, new BaseActivity.PermissionCallback() {
@Override
public void onSuccess(final ImageInfo info) {

CacheManager.getInstance(activity).makeRequest(new CacheRequest(General.uriFromString(info.urlOriginal), anon, null,
Constants.Priority.IMAGE_VIEW, 0, CacheRequest.DOWNLOAD_IF_NECESSARY,
Constants.FileType.IMAGE, CacheRequest.DOWNLOAD_QUEUE_IMMEDIATE, false, false, activity) {

@Override
protected void onCallbackException(Throwable t) {
BugReportActivity.handleGlobalError(context, t);
}
public void onPermissionGranted() {

@Override
protected void onDownloadNecessary() {
General.quickToast(context, R.string.download_downloading);
}
final RedditAccount anon = RedditAccountManager.getAnon();

@Override
protected void onDownloadStarted() {
}
LinkHandler.getImageInfo(activity, post.src.getUrl(), Constants.Priority.IMAGE_VIEW, 0, new GetImageInfoListener() {

@Override
protected void onFailure(@CacheRequest.RequestFailureType int type, Throwable t, Integer status, String readableMessage) {
final RRError error = General.getGeneralErrorForFailure(context, type, t, status, url.toString());
public void onFailure(final @CacheRequest.RequestFailureType int type, final Throwable t, final Integer status, final String readableMessage) {
final RRError error = General.getGeneralErrorForFailure(activity, type, t, status, post.src.getUrl());
General.showResultDialog(activity, error);
}

@Override
protected void onProgress(boolean authorizationInProgress, long bytesRead, long totalBytes) {
}

@Override
protected void onSuccess(CacheManager.ReadableCacheFile cacheFile, long timestamp, UUID session, boolean fromCache, String mimetype) {
public void onSuccess(final ImageInfo info) {

File dst = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), General.uriFromString(info.urlOriginal).getPath());
CacheManager.getInstance(activity).makeRequest(new CacheRequest(General.uriFromString(info.urlOriginal), anon, null,
Constants.Priority.IMAGE_VIEW, 0, CacheRequest.DOWNLOAD_IF_NECESSARY,
Constants.FileType.IMAGE, CacheRequest.DOWNLOAD_QUEUE_IMMEDIATE, false, false, activity) {

if(dst.exists()) {
int count = 0;
@Override
protected void onCallbackException(Throwable t) {
BugReportActivity.handleGlobalError(context, t);
}

while(dst.exists()) {
count++;
dst = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), count + "_" + General.uriFromString(info.urlOriginal).getPath().substring(1));
@Override
protected void onDownloadNecessary() {
General.quickToast(context, R.string.download_downloading);
}
}

try {
final InputStream cacheFileInputStream = cacheFile.getInputStream();
@Override
protected void onDownloadStarted() {
}

if(cacheFileInputStream == null) {
notifyFailure(CacheRequest.REQUEST_FAILURE_CACHE_MISS, null, null, "Could not find cached image");
return;
@Override
protected void onFailure(
@CacheRequest.RequestFailureType int type,
Throwable t,
Integer status,
String readableMessage) {

final RRError error = General.getGeneralErrorForFailure(context, type, t, status, url.toString());
General.showResultDialog(activity, error);
}

General.copyFile(cacheFileInputStream, dst);
@Override
protected void onProgress(
boolean authorizationInProgress,
long bytesRead,
long totalBytes) {
}

} catch(IOException e) {
notifyFailure(CacheRequest.REQUEST_FAILURE_STORAGE, e, null, "Could not copy file");
return;
}
@Override
protected void onSuccess(
CacheManager.ReadableCacheFile cacheFile,
long timestamp,
UUID session,
boolean fromCache,
String mimetype) {

File dst = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
General.uriFromString(info.urlOriginal).getPath());

if(dst.exists()) {
int count = 0;

while(dst.exists()) {
count++;
dst = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
count + "_" + General.uriFromString(info.urlOriginal).getPath().substring(1));
}
}

try {
final InputStream cacheFileInputStream = cacheFile.getInputStream();

if(cacheFileInputStream == null) {
notifyFailure(CacheRequest.REQUEST_FAILURE_CACHE_MISS, null, null, "Could not find cached image");
return;
}

General.copyFile(cacheFileInputStream, dst);

} catch(IOException e) {
notifyFailure(CacheRequest.REQUEST_FAILURE_STORAGE, e, null, "Could not copy file");
return;
}

activity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.parse("file://" + dst.getAbsolutePath()))
);

General.quickToast(context, context.getString(R.string.action_save_image_success) + " " + dst.getAbsolutePath());
}
});

activity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.parse("file://" + dst.getAbsolutePath()))
);
}

General.quickToast(context, context.getString(R.string.action_save_image_success) + " " + dst.getAbsolutePath());
@Override
public void onNotAnImage() {
General.quickToast(activity, R.string.selected_link_is_not_image);
}
});

}

@Override
public void onNotAnImage() {
General.quickToast(activity, R.string.selected_link_is_not_image);
public void onPermissionDenied() {
General.quickToast(activity, R.string.save_image_permission_denied);
}
});

Expand Down
3 changes: 3 additions & 0 deletions src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -792,4 +792,7 @@
<string name="submit_post_self_text_hint">Self Text</string>
<string name="submit_post_url_hint">URL</string>

<!-- 2016-06-24 -->
<string name="save_image_permission_denied">Permission denied: could not save image.</string>

</resources>

0 comments on commit 375b452

Please sign in to comment.