mirror of
https://github.com/ultrasonic/ultrasonic
synced 2025-02-17 04:00:39 +01:00
Migrate PermissionUtil to Kotlin
- Set min SDK to 16 (was 14), because READ_EXTERNAL_STORAGE is minimum 16 - Add new shortcut to Settings.kt class - Use showDialog util function
This commit is contained in:
parent
ec4f57b5b6
commit
b892b7b8d3
@ -1,5 +1,5 @@
|
||||
ext.versions = [
|
||||
minSdk : 14,
|
||||
minSdk : 16,
|
||||
targetSdk : 29,
|
||||
compileSdk : 29,
|
||||
// You need to run ./gradlew wrapper after updating the version
|
||||
|
@ -224,8 +224,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
}
|
||||
|
||||
private void setupCacheLocationPreference() {
|
||||
cacheLocation.setSummary(settings.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION,
|
||||
FileUtil.getDefaultMusicDirectory().getPath()));
|
||||
cacheLocation.setSummary(Settings.getCacheLocation());
|
||||
|
||||
cacheLocation.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
@ -431,8 +430,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
sharingDefaultExpiration.setSummary(sharingDefaultExpiration.getText());
|
||||
sharingDefaultDescription.setSummary(sharingDefaultDescription.getText());
|
||||
sharingDefaultGreeting.setSummary(sharingDefaultGreeting.getText());
|
||||
cacheLocation.setSummary(settings.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION,
|
||||
FileUtil.getDefaultMusicDirectory().getPath()));
|
||||
cacheLocation.setSummary(Settings.getCacheLocation());
|
||||
|
||||
if (!mediaButtonsEnabled.isChecked()) {
|
||||
lockScreenEnabled.setChecked(false);
|
||||
|
@ -1,237 +0,0 @@
|
||||
package org.moire.ultrasonic.util;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.PermissionChecker;
|
||||
|
||||
import com.karumi.dexter.Dexter;
|
||||
import com.karumi.dexter.MultiplePermissionsReport;
|
||||
import com.karumi.dexter.PermissionToken;
|
||||
import com.karumi.dexter.listener.DexterError;
|
||||
import com.karumi.dexter.listener.PermissionRequest;
|
||||
import com.karumi.dexter.listener.PermissionRequestErrorListener;
|
||||
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
|
||||
|
||||
import org.moire.ultrasonic.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import static androidx.core.content.PermissionChecker.PERMISSION_DENIED;
|
||||
|
||||
|
||||
/**
|
||||
* Contains static functions for Permission handling
|
||||
*/
|
||||
public class PermissionUtil {
|
||||
|
||||
private Context activityContext;
|
||||
private final Context applicationContext;
|
||||
|
||||
public PermissionUtil(Context context) {
|
||||
applicationContext = context;
|
||||
}
|
||||
|
||||
public interface PermissionRequestFinishedCallback {
|
||||
void onPermissionRequestFinished(boolean hasPermission);
|
||||
}
|
||||
|
||||
public void ForegroundApplicationStarted(Context context) {
|
||||
this.activityContext = context;
|
||||
}
|
||||
|
||||
public void ForegroundApplicationStopped() {
|
||||
activityContext = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function can be used to handle file access permission failures.
|
||||
*
|
||||
* It will check if the failure is because the necessary permissions aren't available,
|
||||
* and it will request them, if necessary.
|
||||
*
|
||||
* @param callback callback function to execute after the permission request is finished
|
||||
*/
|
||||
public void handlePermissionFailed(@Nullable final PermissionRequestFinishedCallback callback) {
|
||||
String currentCachePath = Settings.getPreferences().getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, FileUtil.getDefaultMusicDirectory().getPath());
|
||||
String defaultCachePath = FileUtil.getDefaultMusicDirectory().getPath();
|
||||
|
||||
// Ultrasonic can do nothing about this error when the Music Directory is already set to the default.
|
||||
if (currentCachePath.compareTo(defaultCachePath) == 0) return;
|
||||
|
||||
if ((PermissionChecker.checkSelfPermission(applicationContext, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PERMISSION_DENIED) ||
|
||||
(PermissionChecker.checkSelfPermission(applicationContext, Manifest.permission.READ_EXTERNAL_STORAGE) == PERMISSION_DENIED)) {
|
||||
// While we request permission, the Music Directory is temporarily reset to its default location
|
||||
setCacheLocation(applicationContext, FileUtil.getDefaultMusicDirectory().getPath());
|
||||
// If the application is not running, we can't notify the user
|
||||
if (activityContext == null) return;
|
||||
requestFailedPermission(activityContext, currentCachePath, callback);
|
||||
} else {
|
||||
setCacheLocation(applicationContext, FileUtil.getDefaultMusicDirectory().getPath());
|
||||
// If the application is not running, we can't notify the user
|
||||
if (activityContext != null) {
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showWarning(activityContext, activityContext.getString(R.string.permissions_message_box_title), activityContext.getString(R.string.permissions_access_error), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (callback != null) {
|
||||
callback.onPermissionRequestFinished(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function requests permission to access the filesystem.
|
||||
* It can be used to request the permission initially, e.g. when the user decides to use a non-default folder for the cache
|
||||
* @param context context for the operation
|
||||
* @param callback callback function to execute after the permission request is finished
|
||||
*/
|
||||
public static void requestInitialPermission(final Context context, final PermissionRequestFinishedCallback callback) {
|
||||
Dexter.withContext(context)
|
||||
.withPermissions(
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
.withListener(new MultiplePermissionsListener() {
|
||||
@Override
|
||||
public void onPermissionsChecked(MultiplePermissionsReport report) {
|
||||
if (report.areAllPermissionsGranted()) {
|
||||
Timber.i("Permission granted to read / write external storage");
|
||||
if (callback != null) callback.onPermissionRequestFinished(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (report.isAnyPermissionPermanentlyDenied()) {
|
||||
Timber.i("Found permanently denied permission to read / write external storage, offering settings");
|
||||
showSettingsDialog(context);
|
||||
if (callback != null) callback.onPermissionRequestFinished(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Timber.i("At least one permission is missing to read / write external storage");
|
||||
showWarning(context, context.getString(R.string.permissions_message_box_title),
|
||||
context.getString(R.string.permissions_rationale_description_initial), null);
|
||||
if (callback != null) callback.onPermissionRequestFinished(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
|
||||
showWarning(context, context.getString(R.string.permissions_rationale_title),
|
||||
context.getString(R.string.permissions_rationale_description_initial), token);
|
||||
}
|
||||
}).withErrorListener(new PermissionRequestErrorListener() {
|
||||
@Override
|
||||
public void onError(DexterError error) {
|
||||
Timber.e("An error has occurred during checking permissions with Dexter: %s", error.toString());
|
||||
}
|
||||
})
|
||||
.check();
|
||||
}
|
||||
|
||||
private static void setCacheLocation(Context context, String cacheLocation) {
|
||||
Settings.getPreferences().edit()
|
||||
.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, cacheLocation)
|
||||
.apply();
|
||||
}
|
||||
|
||||
private static void requestFailedPermission(final Context context, final String cacheLocation, final PermissionRequestFinishedCallback callback) {
|
||||
Dexter.withContext(context)
|
||||
.withPermissions(
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
.withListener(new MultiplePermissionsListener() {
|
||||
@Override
|
||||
public void onPermissionsChecked(MultiplePermissionsReport report) {
|
||||
if (report.areAllPermissionsGranted()) {
|
||||
Timber.i("Permission granted to use cache directory %s", cacheLocation);
|
||||
setCacheLocation(context, cacheLocation);
|
||||
if (callback != null) callback.onPermissionRequestFinished(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (report.isAnyPermissionPermanentlyDenied()) {
|
||||
Timber.i("Found permanently denied permission to use cache directory %s, offering settings", cacheLocation);
|
||||
showSettingsDialog(context);
|
||||
if (callback != null) callback.onPermissionRequestFinished(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Timber.i("At least one permission is missing to use directory %s ", cacheLocation);
|
||||
setCacheLocation(context, FileUtil.getDefaultMusicDirectory().getPath());
|
||||
showWarning(context, context.getString(R.string.permissions_message_box_title),
|
||||
context.getString(R.string.permissions_permission_missing), null);
|
||||
if (callback != null) callback.onPermissionRequestFinished(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
|
||||
showWarning(context, context.getString(R.string.permissions_rationale_title),
|
||||
context.getString(R.string.permissions_rationale_description_failed), token);
|
||||
}
|
||||
}).withErrorListener(new PermissionRequestErrorListener() {
|
||||
@Override
|
||||
public void onError(DexterError error) {
|
||||
Timber.e("An error has occurred during checking permissions with Dexter: %s", error.toString());
|
||||
}
|
||||
})
|
||||
.check();
|
||||
}
|
||||
|
||||
private static void showSettingsDialog(final Context context) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.Theme_AppCompat_Dialog);
|
||||
builder.setIcon(android.R.drawable.ic_dialog_alert);
|
||||
builder.setTitle(context.getString(R.string.permissions_permanent_denial_title));
|
||||
builder.setMessage(context.getString(R.string.permissions_permanent_denial_description));
|
||||
|
||||
builder.setPositiveButton(context.getString(R.string.permissions_open_settings), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.cancel();
|
||||
openSettings(context);
|
||||
}
|
||||
});
|
||||
|
||||
builder.setNegativeButton(context.getString(R.string.common_cancel), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
setCacheLocation(context, FileUtil.getDefaultMusicDirectory().getPath());
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private static void openSettings(Context context) {
|
||||
Intent i = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
i.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
i.setData(Uri.parse("package:" + context.getPackageName()));
|
||||
context.startActivity(i);
|
||||
}
|
||||
|
||||
private static void showWarning(Context context, String title, String text, final PermissionToken token) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.Theme_AppCompat_Dialog);
|
||||
builder.setIcon(android.R.drawable.ic_dialog_alert);
|
||||
builder.setTitle(title);
|
||||
builder.setMessage(text);
|
||||
builder.setPositiveButton(context.getString(R.string.common_ok), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.cancel();
|
||||
if (token != null) token.continuePermissionRequest();
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
}
|
@ -83,7 +83,7 @@ class NavigationActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setUncaughtExceptionHandler()
|
||||
permissionUtil.ForegroundApplicationStarted(this)
|
||||
permissionUtil.onForegroundApplicationStarted(this)
|
||||
Util.applyTheme(this)
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -198,7 +198,7 @@ class NavigationActivity : AppCompatActivity() {
|
||||
nowPlayingEventDistributor.unsubscribe(nowPlayingEventListener)
|
||||
themeChangedEventDistributor.unsubscribe(themeChangedEventListener)
|
||||
imageLoaderProvider.clearImageLoader()
|
||||
permissionUtil.ForegroundApplicationStopped()
|
||||
permissionUtil.onForegroundApplicationStopped()
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
@ -304,12 +304,7 @@ class NavigationActivity : AppCompatActivity() {
|
||||
PreferenceManager.setDefaultValues(this, R.xml.settings, false)
|
||||
val preferences = Settings.preferences
|
||||
if (!preferences.contains(Constants.PREFERENCES_KEY_CACHE_LOCATION)) {
|
||||
val editor = preferences.edit()
|
||||
editor.putString(
|
||||
Constants.PREFERENCES_KEY_CACHE_LOCATION,
|
||||
FileUtil.defaultMusicDirectory.path
|
||||
)
|
||||
editor.apply()
|
||||
Settings.cacheLocation = FileUtil.defaultMusicDirectory.path
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -415,10 +415,9 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
|
||||
}
|
||||
|
||||
Util.showDialog(
|
||||
activity,
|
||||
android.R.drawable.ic_dialog_info,
|
||||
R.string.settings_testing_ok,
|
||||
dialogText
|
||||
context = requireActivity(),
|
||||
titleId = R.string.settings_testing_ok,
|
||||
message = dialogText
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -253,9 +253,8 @@ object FileUtil {
|
||||
@JvmStatic
|
||||
val musicDirectory: File
|
||||
get() {
|
||||
val path = Settings.preferences
|
||||
.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, defaultMusicDirectory.path)
|
||||
val dir = File(path!!)
|
||||
val path = Settings.cacheLocation
|
||||
val dir = File(path)
|
||||
val hasAccess = ensureDirectoryExistsAndIsReadWritable(dir)
|
||||
if (!hasAccess) permissionUtil.value.handlePermissionFailed(null)
|
||||
return if (hasAccess) dir else defaultMusicDirectory
|
||||
|
@ -0,0 +1,259 @@
|
||||
package org.moire.ultrasonic.util
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import androidx.core.content.PermissionChecker
|
||||
import com.karumi.dexter.Dexter
|
||||
import com.karumi.dexter.MultiplePermissionsReport
|
||||
import com.karumi.dexter.PermissionToken
|
||||
import com.karumi.dexter.listener.PermissionRequest
|
||||
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.util.FileUtil.defaultMusicDirectory
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Contains static functions for Permission handling
|
||||
*/
|
||||
class PermissionUtil(private val applicationContext: Context) {
|
||||
private var activityContext: Context? = null
|
||||
|
||||
interface PermissionRequestFinishedCallback {
|
||||
fun onPermissionRequestFinished(hasPermission: Boolean)
|
||||
}
|
||||
|
||||
fun onForegroundApplicationStarted(context: Context?) {
|
||||
activityContext = context
|
||||
}
|
||||
|
||||
fun onForegroundApplicationStopped() {
|
||||
activityContext = null
|
||||
}
|
||||
|
||||
/**
|
||||
* This function can be used to handle file access permission failures.
|
||||
*
|
||||
* It will check if the failure is because the necessary permissions aren't available,
|
||||
* and it will request them, if necessary.
|
||||
*
|
||||
* @param callback callback function to execute after the permission request is finished
|
||||
*/
|
||||
fun handlePermissionFailed(callback: PermissionRequestFinishedCallback?) {
|
||||
val currentCachePath = Settings.cacheLocation
|
||||
val defaultCachePath = defaultMusicDirectory.path
|
||||
|
||||
// Ultrasonic can do nothing about this error when the Music Directory is already set to the default.
|
||||
if (currentCachePath.compareTo(defaultCachePath) == 0) return
|
||||
|
||||
if (PermissionChecker.checkSelfPermission(
|
||||
applicationContext,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
) == PermissionChecker.PERMISSION_DENIED ||
|
||||
PermissionChecker.checkSelfPermission(
|
||||
applicationContext,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||
) == PermissionChecker.PERMISSION_DENIED
|
||||
) {
|
||||
// While we request permission, the Music Directory is temporarily reset to its default location
|
||||
Settings.cacheLocation = defaultMusicDirectory.path
|
||||
// If the application is not running, we can't notify the user
|
||||
if (activityContext == null) return
|
||||
requestFailedPermission(activityContext!!, currentCachePath, callback)
|
||||
} else {
|
||||
Settings.cacheLocation = defaultMusicDirectory.path
|
||||
// If the application is not running, we can't notify the user
|
||||
if (activityContext != null) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
showWarning(
|
||||
activityContext!!,
|
||||
activityContext!!.getString(R.string.permissions_message_box_title),
|
||||
activityContext!!.getString(R.string.permissions_access_error),
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
callback?.onPermissionRequestFinished(false)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* This function requests permission to access the filesystem.
|
||||
* It can be used to request the permission initially, e.g. when the user decides to
|
||||
* use a non-default folder for the cache
|
||||
* @param context context for the operation
|
||||
* @param callback callback function to execute after the permission request is finished
|
||||
*/
|
||||
@JvmStatic
|
||||
fun requestInitialPermission(
|
||||
context: Context,
|
||||
callback: PermissionRequestFinishedCallback?
|
||||
) {
|
||||
Dexter.withContext(context)
|
||||
.withPermissions(
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||
)
|
||||
.withListener(object : MultiplePermissionsListener {
|
||||
override fun onPermissionsChecked(report: MultiplePermissionsReport) {
|
||||
if (report.areAllPermissionsGranted()) {
|
||||
Timber.i("R/W permission granted for external storage")
|
||||
callback?.onPermissionRequestFinished(true)
|
||||
return
|
||||
}
|
||||
if (report.isAnyPermissionPermanentlyDenied) {
|
||||
Timber.i(
|
||||
"R/W permission is permanently denied for external storage"
|
||||
)
|
||||
showSettingsDialog(context)
|
||||
callback?.onPermissionRequestFinished(false)
|
||||
return
|
||||
}
|
||||
Timber.i("R/W permission is missing for external storage")
|
||||
showWarning(
|
||||
context,
|
||||
context.getString(R.string.permissions_message_box_title),
|
||||
context.getString(R.string.permissions_rationale_description_initial),
|
||||
null
|
||||
)
|
||||
callback?.onPermissionRequestFinished(false)
|
||||
}
|
||||
|
||||
override fun onPermissionRationaleShouldBeShown(
|
||||
permissions: List<PermissionRequest>,
|
||||
token: PermissionToken
|
||||
) {
|
||||
showWarning(
|
||||
context,
|
||||
context.getString(R.string.permissions_rationale_title),
|
||||
context.getString(R.string.permissions_rationale_description_initial),
|
||||
token
|
||||
)
|
||||
}
|
||||
}).withErrorListener { error ->
|
||||
Timber.e(
|
||||
"An error has occurred during checking permissions with Dexter: %s",
|
||||
error.toString()
|
||||
)
|
||||
}
|
||||
.check()
|
||||
}
|
||||
|
||||
private fun requestFailedPermission(
|
||||
context: Context,
|
||||
cacheLocation: String?,
|
||||
callback: PermissionRequestFinishedCallback?
|
||||
) {
|
||||
Dexter.withContext(context)
|
||||
.withPermissions(
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||
)
|
||||
.withListener(object : MultiplePermissionsListener {
|
||||
override fun onPermissionsChecked(report: MultiplePermissionsReport) {
|
||||
if (report.areAllPermissionsGranted()) {
|
||||
Timber.i("Permission granted to use cache directory %s", cacheLocation)
|
||||
|
||||
if (cacheLocation != null) {
|
||||
Settings.cacheLocation = cacheLocation
|
||||
}
|
||||
callback?.onPermissionRequestFinished(true)
|
||||
return
|
||||
}
|
||||
if (report.isAnyPermissionPermanentlyDenied) {
|
||||
Timber.i(
|
||||
"R/W permission for cache directory %s was permanently denied",
|
||||
cacheLocation
|
||||
)
|
||||
showSettingsDialog(context)
|
||||
callback?.onPermissionRequestFinished(false)
|
||||
return
|
||||
}
|
||||
Timber.i(
|
||||
"At least one permission is missing to use directory %s ",
|
||||
cacheLocation
|
||||
)
|
||||
Settings.cacheLocation = defaultMusicDirectory.path
|
||||
showWarning(
|
||||
context, context.getString(R.string.permissions_message_box_title),
|
||||
context.getString(R.string.permissions_permission_missing), null
|
||||
)
|
||||
callback?.onPermissionRequestFinished(false)
|
||||
}
|
||||
|
||||
override fun onPermissionRationaleShouldBeShown(
|
||||
permissions: List<PermissionRequest>,
|
||||
token: PermissionToken
|
||||
) {
|
||||
showWarning(
|
||||
context,
|
||||
context.getString(R.string.permissions_rationale_title),
|
||||
context.getString(R.string.permissions_rationale_description_failed),
|
||||
token
|
||||
)
|
||||
}
|
||||
}).withErrorListener { error ->
|
||||
Timber.e(
|
||||
"An error has occurred during checking permissions with Dexter: %s",
|
||||
error.toString()
|
||||
)
|
||||
}
|
||||
.check()
|
||||
}
|
||||
|
||||
private fun showSettingsDialog(ctx: Context) {
|
||||
|
||||
val builder = Util.createDialog(
|
||||
context = ctx,
|
||||
android.R.drawable.ic_dialog_alert,
|
||||
ctx.getString(R.string.permissions_permanent_denial_title),
|
||||
ctx.getString(R.string.permissions_permanent_denial_description)
|
||||
)
|
||||
|
||||
builder.setPositiveButton(ctx.getString(R.string.permissions_open_settings)) {
|
||||
dialog, _ ->
|
||||
dialog.cancel()
|
||||
openSettings(ctx)
|
||||
}
|
||||
|
||||
builder.setNegativeButton(ctx.getString(R.string.common_cancel)) { dialog, _ ->
|
||||
Settings.cacheLocation = defaultMusicDirectory.path
|
||||
dialog.cancel()
|
||||
}
|
||||
|
||||
builder.show()
|
||||
}
|
||||
|
||||
private fun openSettings(context: Context) {
|
||||
val i = Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
i.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
i.data = Uri.parse("package:" + context.packageName)
|
||||
context.startActivity(i)
|
||||
}
|
||||
|
||||
private fun showWarning(
|
||||
context: Context,
|
||||
title: String,
|
||||
text: String,
|
||||
token: PermissionToken?
|
||||
) {
|
||||
|
||||
val builder = Util.createDialog(
|
||||
context = context,
|
||||
android.R.drawable.ic_dialog_alert,
|
||||
title,
|
||||
text
|
||||
)
|
||||
|
||||
builder.setPositiveButton(context.getString(R.string.common_ok)) { dialog, _ ->
|
||||
dialog.cancel()
|
||||
token?.continuePermissionRequest()
|
||||
}
|
||||
builder.show()
|
||||
}
|
||||
}
|
||||
}
|
@ -102,6 +102,23 @@ object Settings {
|
||||
return if (preloadCount == -1) Int.MAX_VALUE else preloadCount
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
var cacheLocation: String
|
||||
get() {
|
||||
return preferences.getString(
|
||||
Constants.PREFERENCES_KEY_CACHE_LOCATION,
|
||||
FileUtil.defaultMusicDirectory.path
|
||||
)!!
|
||||
}
|
||||
set(location) {
|
||||
val editor = preferences.edit()
|
||||
editor.putString(
|
||||
Constants.PREFERENCES_KEY_CACHE_LOCATION,
|
||||
location
|
||||
)
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val cacheSizeMB: Int
|
||||
get() {
|
||||
|
@ -393,17 +393,30 @@ object Util {
|
||||
|
||||
// The AlertDialog requires an Activity context, app context is not enough
|
||||
// See https://stackoverflow.com/questions/5436822/
|
||||
fun showDialog(context: Context?, icon: Int, titleId: Int, message: String?) {
|
||||
AlertDialog.Builder(context)
|
||||
fun createDialog(
|
||||
context: Context?,
|
||||
icon: Int = android.R.drawable.ic_dialog_info,
|
||||
title: String,
|
||||
message: String?
|
||||
): AlertDialog.Builder {
|
||||
return AlertDialog.Builder(context)
|
||||
.setIcon(icon)
|
||||
.setTitle(titleId)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(R.string.common_ok) {
|
||||
dialog: DialogInterface,
|
||||
_: Int ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
fun showDialog(
|
||||
context: Context,
|
||||
icon: Int = android.R.drawable.ic_dialog_info,
|
||||
titleId: Int,
|
||||
message: String?
|
||||
) {
|
||||
createDialog(context, icon, context.getString(titleId, ""), message).show()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
Loading…
x
Reference in New Issue
Block a user