Commit f52fadfa authored by Geoffrey Métais's avatar Geoffrey Métais

Get write storage access on Oreo

(cherry picked from commit 0b7880a4)
parent 4cdbe110
......@@ -186,4 +186,10 @@ public class ContentActivity extends AudioPlayerContainerActivity implements Sea
((Filterable) current).restoreList();
}
}
public Runnable deleteAction;
public void onWriteAccessGranted() {
if (deleteAction != null) mActivityHandler.postDelayed(deleteAction, 500);
deleteAction = null;
}
}
......@@ -239,23 +239,21 @@ public class AudioBrowserFragment extends BaseAudioBrowser implements SwipeRefre
final MediaLibraryItem mediaItem = adapter.getItem(position);
if (id == R.id.audio_list_browser_delete) {
final MediaLibraryItem mediaLibraryItem = adapter.getItem(position);
final MediaLibraryItem previous = position > 0 ? adapter.getItem(position-1) : null;
final MediaLibraryItem next = position < adapter.getItemCount()-1 ? adapter.getItem(position+1) : null;
String message;
Runnable action;
final String message;
final Runnable action;
final MediaLibraryItem separator = previous != null && previous.getItemType() == MediaLibraryItem.TYPE_DUMMY &&
(next == null || next.getItemType() == MediaLibraryItem.TYPE_DUMMY) ? previous : null;
adapter.remove(mediaLibraryItem);
if (separator != null)
adapter.remove(separator);
adapter.remove(mediaItem);
if (separator != null) adapter.remove(separator);
if (mode == MODE_PLAYLIST) {
message = getString(R.string.playlist_deleted);
action = new Runnable() {
@Override
public void run() {
deletePlaylist((Playlist) mediaLibraryItem);
deletePlaylist((Playlist) mediaItem);
}
};
} else if (mode == MODE_SONG) {
......@@ -265,15 +263,21 @@ public class AudioBrowserFragment extends BaseAudioBrowser implements SwipeRefre
public void run() {
if (separator != null)
adapter.addItem(position-1, separator);
adapter.addItem(position, mediaLibraryItem);
adapter.addItem(position, mediaItem);
}
};
action = new Runnable() {
@Override
public void run() {
deleteMedia(mediaLibraryItem, true, cancel);
deleteMedia(mediaItem, true, cancel);
}
};
if (!checkWritePermission((MediaWrapper) mediaItem, new Runnable() {
@Override
public void run() {
UiTools.snackerWithCancel(getView(), message, action, cancel);
}
})) return false;
} else
return false;
UiTools.snackerWithCancel(getView(), message, action);
......
......@@ -46,12 +46,15 @@ import org.videolan.medialibrary.media.MediaWrapper;
import org.videolan.vlc.MediaParsingService;
import org.videolan.vlc.R;
import org.videolan.vlc.VLCApplication;
import org.videolan.vlc.gui.ContentActivity;
import org.videolan.vlc.gui.InfoActivity;
import org.videolan.vlc.gui.PlaybackServiceFragment;
import org.videolan.vlc.gui.helpers.UiTools;
import org.videolan.vlc.gui.view.ContextMenuRecyclerView;
import org.videolan.vlc.gui.view.SwipeRefreshLayout;
import org.videolan.vlc.util.AndroidDevices;
import org.videolan.vlc.util.FileUtils;
import org.videolan.vlc.util.Permissions;
import java.util.LinkedList;
......@@ -166,10 +169,8 @@ public abstract class MediaBrowserFragment extends PlaybackServiceFragment imple
@Override
public boolean onContextItemSelected(MenuItem menu) {
if(!getUserVisibleHint())
return false;
ContextMenuRecyclerView.RecyclerContextMenuInfo info = (ContextMenuRecyclerView.RecyclerContextMenuInfo) menu.getMenuInfo();
if(!getUserVisibleHint()) return false;
final ContextMenuRecyclerView.RecyclerContextMenuInfo info = (ContextMenuRecyclerView.RecyclerContextMenuInfo) menu.getMenuInfo();
return info != null && handleContextItemSelected(menu, info.position);
}
......@@ -197,8 +198,7 @@ public abstract class MediaBrowserFragment extends PlaybackServiceFragment imple
return;
}
if (mService != null)
for (String path : mediaPaths)
mService.removeLocation(path);
for (String path : mediaPaths) mService.removeLocation(path);
if (refresh) onRefresh();
}
});
......@@ -207,6 +207,15 @@ public abstract class MediaBrowserFragment extends PlaybackServiceFragment imple
});
}
protected boolean checkWritePermission(MediaWrapper media, Runnable callback) {
if (media.getUri().getPath().startsWith(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY) && !Permissions.canWriteStorage()) {
final ContentActivity activity = (ContentActivity) getActivity();
activity.deleteAction = callback;
Permissions.askWriteStoragePermission(getActivity(), false);
return false;
}
return true;
}
private void onDeleteFailed(MediaWrapper media) {
final View v = getView();
if (v != null && isAdded()) UiTools.snacker(v, getString(R.string.msg_delete_failed, media.getTitle()));
......
......@@ -40,9 +40,9 @@ import org.videolan.libvlc.util.AndroidUtil;
import org.videolan.vlc.MediaParsingService;
import org.videolan.vlc.StartActivity;
import org.videolan.vlc.VLCApplication;
import org.videolan.vlc.gui.ContentActivity;
import org.videolan.vlc.util.Permissions;
import static org.videolan.vlc.util.Permissions.PERMISSION_STORAGE_TAG;
import static org.videolan.vlc.util.Permissions.canReadStorage;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
......@@ -54,7 +54,7 @@ public class StoragePermissionsDelegate extends BaseHeadlessFragment {
public final static String TAG = "VLC/StorageHF";
private boolean mFirstRun, mUpgrade;
private boolean mFirstRun, mUpgrade, mWrite;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
......@@ -65,23 +65,29 @@ public class StoragePermissionsDelegate extends BaseHeadlessFragment {
intent.removeExtra(StartActivity.EXTRA_UPGRADE);
intent.removeExtra(StartActivity.EXTRA_FIRST_RUN);
}
mWrite = getArguments().getBoolean("write");
if (AndroidUtil.isMarshMallowOrLater && !canReadStorage(getActivity())) {
if (shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE))
Permissions.showStoragePermissionDialog(mActivity, false);
Permissions.showStoragePermissionDialog(mActivity, false, false);
else
requestStorageAccess();
requestStorageAccess(false);
} else if (mWrite) {
if (shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE))
Permissions.showStoragePermissionDialog(mActivity, false, true);
else
requestStorageAccess(true);
}
}
private void requestStorageAccess() {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
Permissions.PERMISSION_STORAGE_TAG);
private void requestStorageAccess(boolean write) {
requestPermissions(new String[]{write ? Manifest.permission.WRITE_EXTERNAL_STORAGE : Manifest.permission.READ_EXTERNAL_STORAGE},
write ? Permissions.PERMISSION_WRITE_STORAGE_TAG : Permissions.PERMISSION_STORAGE_TAG);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_STORAGE_TAG:
case Permissions.PERMISSION_STORAGE_TAG:
// If request is cancelled, the result arrays are empty.
final Context ctx = VLCApplication.getAppContext();
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
......@@ -95,21 +101,29 @@ public class StoragePermissionsDelegate extends BaseHeadlessFragment {
}
exit();
} else if (mActivity != null) {
Permissions.showStoragePermissionDialog(mActivity, false);
Permissions.showStoragePermissionDialog(mActivity, false, mWrite);
if (!shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE))
exit();
}
break;
case Permissions.PERMISSION_WRITE_STORAGE_TAG:
if (mActivity instanceof ContentActivity) ((ContentActivity) mActivity).onWriteAccessGranted();
break;
}
}
public static void askStoragePermission(@NonNull FragmentActivity activity) {
public static void askStoragePermission(@NonNull FragmentActivity activity, boolean write) {
if (activity.isFinishing()) return;
final FragmentManager fm = activity.getSupportFragmentManager();
final Fragment fragment = fm.findFragmentByTag(TAG);
if (fragment == null)
fm.beginTransaction().add(new StoragePermissionsDelegate(), TAG).commitAllowingStateLoss();
else
((StoragePermissionsDelegate)fragment).requestStorageAccess();
Fragment fragment = fm.findFragmentByTag(TAG);
if (fragment == null) {
final Bundle args = new Bundle();
args.putBoolean("write", write);
fragment = new StoragePermissionsDelegate();
fragment.setArguments(args);
fm.beginTransaction().add(fragment, TAG).commitAllowingStateLoss();
} else
((StoragePermissionsDelegate)fragment).requestStorageAccess(write);
}
}
......@@ -253,8 +253,7 @@ public class VideoGridFragment extends SortableFragment<VideoListAdapter> implem
}
protected boolean handleContextItemSelected(MenuItem menu, final int position) {
if (position >= mAdapter.getItemCount())
return false;
if (position >= mAdapter.getItemCount()) return false;
final MediaWrapper media = mAdapter.getItem(position);
if (media == null)
return false;
......@@ -292,6 +291,12 @@ public class VideoGridFragment extends SortableFragment<VideoListAdapter> implem
}
private void removeVideo(final MediaWrapper media) {
if (!checkWritePermission(media, new Runnable() {
@Override
public void run() {
removeVideo(media);
}
})) return;
final int position = mAdapter.remove(media);
final View view = getView();
if (position != -1 && view != null) {
......
......@@ -51,6 +51,7 @@ public class Permissions {
public static final int PERMISSION_STORAGE_TAG = 255;
public static final int PERMISSION_SETTINGS_TAG = 254;
public static final int PERMISSION_WRITE_STORAGE_TAG = 253;
public static final int PERMISSION_SYSTEM_RINGTONE = 42;
......@@ -84,18 +85,35 @@ public class Permissions {
Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
public static boolean canWriteStorage() {
return canWriteStorage(VLCApplication.getAppContext());
}
public static boolean canWriteStorage(Context context) {
return ContextCompat.checkSelfPermission(context,
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
public static boolean checkReadStoragePermission(FragmentActivity activity, boolean exit) {
if (AndroidUtil.isMarshMallowOrLater && !canReadStorage(activity)) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
Manifest.permission.READ_EXTERNAL_STORAGE)) {
showStoragePermissionDialog(activity, exit);
showStoragePermissionDialog(activity, exit, false);
} else
requestStoragePermission(activity);
requestStoragePermission(activity, false);
return false;
}
return true;
}
public static void askWriteStoragePermission(FragmentActivity activity, boolean exit) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
showStoragePermissionDialog(activity, exit, true);
} else
requestStoragePermission(activity, true);
}
public static void checkDrawOverlaysPermission(FragmentActivity activity) {
if (AndroidUtil.isMarshMallowOrLater && !canDrawOverlays(activity)) {
showSettingsPermissionDialog(activity, PERMISSION_SYSTEM_DRAW_OVRLAYS);
......@@ -103,29 +121,23 @@ public class Permissions {
}
public static void checkWriteSettingsPermission(FragmentActivity activity, int mode) {
if (!canWriteSettings(activity)) {
showSettingsPermissionDialog(activity, mode);
}
if (!canWriteSettings(activity)) showSettingsPermissionDialog(activity, mode);
}
private static Dialog sAlertDialog;
public static void showSettingsPermissionDialog(final FragmentActivity activity, int mode) {
if (activity.isFinishing() || (sAlertDialog != null && sAlertDialog.isShowing()))
return;
private static void showSettingsPermissionDialog(final FragmentActivity activity, int mode) {
if (activity.isFinishing() || (sAlertDialog != null && sAlertDialog.isShowing())) return;
sAlertDialog = createSettingsDialogCompat(activity, mode);
}
public static void showStoragePermissionDialog(final FragmentActivity activity, boolean exit) {
if (activity.isFinishing() || (sAlertDialog != null && sAlertDialog.isShowing()))
return;
if (activity instanceof AppCompatActivity)
sAlertDialog = createDialogCompat(activity, exit);
else
sAlertDialog = createDialog(activity, exit);
public static void showStoragePermissionDialog(final FragmentActivity activity, boolean exit, boolean write) {
if (activity.isFinishing() || (sAlertDialog != null && sAlertDialog.isShowing())) return;
if (activity instanceof AppCompatActivity) sAlertDialog = createDialogCompat(activity, exit, write);
else sAlertDialog = createDialog(activity, exit, write);
}
private static Dialog createDialog(final FragmentActivity activity, boolean exit) {
private static Dialog createDialog(final FragmentActivity activity, boolean exit, boolean write) {
android.app.AlertDialog.Builder dialogBuilder = new android.app.AlertDialog.Builder(activity)
.setTitle(activity.getString(R.string.allow_storage_access_title))
.setMessage(activity.getString(R.string.allow_storage_access_description))
......@@ -133,9 +145,9 @@ public class Permissions {
.setPositiveButton(activity.getString(R.string.permission_ask_again), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(activity);
final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(activity);
if (!settings.getBoolean("user_declined_storage_access", false))
requestStoragePermission(activity);
requestStoragePermission(activity, false);
else {
final Intent i = new Intent("android.settings.APPLICATION_DETAILS_SETTINGS");
i.addCategory(Intent.CATEGORY_DEFAULT);
......@@ -145,9 +157,9 @@ public class Permissions {
activity.startActivity(i);
} catch (Exception ignored) {}
}
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("user_declined_storage_access", true);
editor.apply();
settings.edit()
.putBoolean("user_declined_storage_access", true)
.apply();
}
});
if (exit) {
......@@ -162,7 +174,7 @@ public class Permissions {
return dialogBuilder.show();
}
private static Dialog createDialogCompat(final FragmentActivity activity, boolean exit) {
private static Dialog createDialogCompat(final FragmentActivity activity, boolean exit, boolean write) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(activity)
.setTitle(activity.getString(R.string.allow_storage_access_title))
.setMessage(activity.getString(R.string.allow_storage_access_description))
......@@ -170,9 +182,9 @@ public class Permissions {
.setPositiveButton(activity.getString(R.string.permission_ask_again), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(activity);
final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(activity);
if (!settings.getBoolean("user_declined_storage_access", false))
requestStoragePermission(activity);
requestStoragePermission(activity, false);
else {
Intent i = new Intent();
i.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
......@@ -183,9 +195,9 @@ public class Permissions {
activity.startActivity(i);
} catch (Exception ignored) {}
}
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("user_declined_storage_access", true);
editor.apply();
settings.edit()
.putBoolean("user_declined_storage_access", true)
.apply();
}
});
if (exit) {
......@@ -240,8 +252,7 @@ public class Permissions {
return dialogBuilder.show();
}
private static void requestStoragePermission(FragmentActivity activity) {
if (activity != null)
StoragePermissionsDelegate.askStoragePermission(activity);
private static void requestStoragePermission(FragmentActivity activity, boolean write) {
if (activity != null) StoragePermissionsDelegate.askStoragePermission(activity, write);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment