mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-09 07:16:04 -04:00
Merge pull request #2727 from kiwix/refactor_permission
Added `MANAGE_EXTERNAL_STORAGE` permission for Android 11 and later
This commit is contained in:
commit
11901c2b69
@ -11,7 +11,7 @@
|
|||||||
<ID>MagicNumber:ShareFiles.kt$ShareFiles$24</ID>
|
<ID>MagicNumber:ShareFiles.kt$ShareFiles$24</ID>
|
||||||
<ID>MagicNumber:ZimManageViewModel.kt$ZimManageViewModel$5</ID>
|
<ID>MagicNumber:ZimManageViewModel.kt$ZimManageViewModel$5</ID>
|
||||||
<ID>MagicNumber:ZimManageViewModel.kt$ZimManageViewModel$500</ID>
|
<ID>MagicNumber:ZimManageViewModel.kt$ZimManageViewModel$500</ID>
|
||||||
<ID>MagicNumber:ZimHostFragment.kt$ZimHostFragment$4</ID>
|
<ID>NestedBlockDepth:LocalLibraryFragment.kt$LocalLibraryFragment$checkPermissions</ID>
|
||||||
<ID>NestedBlockDepth:PeerGroupHandshake.kt$PeerGroupHandshake$readHandshakeAndExchangeMetaData</ID>
|
<ID>NestedBlockDepth:PeerGroupHandshake.kt$PeerGroupHandshake$readHandshakeAndExchangeMetaData</ID>
|
||||||
<ID>NestedBlockDepth:ReceiverHandShake.kt$ReceiverHandShake$exchangeFileTransferMetadata</ID>
|
<ID>NestedBlockDepth:ReceiverHandShake.kt$ReceiverHandShake$exchangeFileTransferMetadata</ID>
|
||||||
<ID>PackageNaming:AvailableSpaceCalculator.kt$package org.kiwix.kiwixmobile.zim_manager.library_view</ID>
|
<ID>PackageNaming:AvailableSpaceCalculator.kt$package org.kiwix.kiwixmobile.zim_manager.library_view</ID>
|
||||||
|
@ -20,7 +20,9 @@ package org.kiwix.kiwixmobile.nav.destination.library
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Environment
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
@ -62,6 +64,12 @@ import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.Re
|
|||||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestSelect
|
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestSelect
|
||||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.FileSelectListState
|
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.FileSelectListState
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.provider.Settings
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog
|
||||||
|
|
||||||
private const val WAS_IN_ACTION_MODE = "WAS_IN_ACTION_MODE"
|
private const val WAS_IN_ACTION_MODE = "WAS_IN_ACTION_MODE"
|
||||||
|
|
||||||
@ -69,6 +77,7 @@ class LocalLibraryFragment : BaseFragment() {
|
|||||||
|
|
||||||
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
|
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||||
@Inject lateinit var sharedPreferenceUtil: SharedPreferenceUtil
|
@Inject lateinit var sharedPreferenceUtil: SharedPreferenceUtil
|
||||||
|
@Inject lateinit var dialogShower: DialogShower
|
||||||
|
|
||||||
private var actionMode: ActionMode? = null
|
private var actionMode: ActionMode? = null
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
@ -202,7 +211,25 @@ class LocalLibraryFragment : BaseFragment() {
|
|||||||
REQUEST_STORAGE_PERMISSION
|
REQUEST_STORAGE_PERMISSION
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
requestFileSystemCheck()
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
if (Environment.isExternalStorageManager()) {
|
||||||
|
// We already have permission!!
|
||||||
|
requestFileSystemCheck()
|
||||||
|
} else {
|
||||||
|
if (sharedPreferenceUtil.manageExternalFilesPermissionDialog) {
|
||||||
|
// We should only ask for first time, If the users wants to revoke settings
|
||||||
|
// then they can directly toggle this feature from settings screen
|
||||||
|
sharedPreferenceUtil.manageExternalFilesPermissionDialog = false
|
||||||
|
// Show Dialog and Go to settings to give permission
|
||||||
|
dialogShower.show(
|
||||||
|
KiwixDialog.ManageExternalFilesPermissionDialog,
|
||||||
|
::navigateToSettings
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestFileSystemCheck()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,4 +244,13 @@ class LocalLibraryFragment : BaseFragment() {
|
|||||||
private fun navigateToLocalFileTransferFragment() {
|
private fun navigateToLocalFileTransferFragment() {
|
||||||
requireActivity().navigate(R.id.localFileTransferFragment)
|
requireActivity().navigate(R.id.localFileTransferFragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
|
private fun navigateToSettings() {
|
||||||
|
val intent = Intent().apply {
|
||||||
|
action = Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
|
||||||
|
data = Uri.fromParts("package", requireActivity().packageName, null)
|
||||||
|
}
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
|
||||||
|
tools:ignore="ScopedStorage" />
|
||||||
|
|
||||||
<!-- Device with versions >= Pie need this permission -->
|
<!-- Device with versions >= Pie need this permission -->
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
@ -20,16 +20,23 @@ package org.kiwix.kiwixmobile.core.settings;
|
|||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.provider.Settings;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.navigation.NavController;
|
import androidx.navigation.NavController;
|
||||||
import androidx.preference.EditTextPreference;
|
import androidx.preference.EditTextPreference;
|
||||||
import androidx.preference.ListPreference;
|
import androidx.preference.ListPreference;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceCategory;
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import eu.mhutti1.utils.storage.StorageDevice;
|
import eu.mhutti1.utils.storage.StorageDevice;
|
||||||
@ -62,6 +69,9 @@ public abstract class CorePrefsFragment extends PreferenceFragmentCompat impleme
|
|||||||
public static final String PREF_CLEAR_ALL_HISTORY = "pref_clear_all_history";
|
public static final String PREF_CLEAR_ALL_HISTORY = "pref_clear_all_history";
|
||||||
public static final String PREF_CLEAR_ALL_NOTES = "pref_clear_all_notes";
|
public static final String PREF_CLEAR_ALL_NOTES = "pref_clear_all_notes";
|
||||||
public static final String PREF_CREDITS = "pref_credits";
|
public static final String PREF_CREDITS = "pref_credits";
|
||||||
|
public static final String PREF_MANAGE_EXTERNAL_STORAGE_PERMISSION =
|
||||||
|
"pref_manage_external_storage";
|
||||||
|
public static final String PREF_PERMISSION = "pref_permissions";
|
||||||
private static final int ZOOM_OFFSET = 2;
|
private static final int ZOOM_OFFSET = 2;
|
||||||
private static final int ZOOM_SCALE = 25;
|
private static final int ZOOM_SCALE = 25;
|
||||||
private static final String INTERNAL_TEXT_ZOOM = "text_zoom";
|
private static final String INTERNAL_TEXT_ZOOM = "text_zoom";
|
||||||
@ -87,6 +97,7 @@ public abstract class CorePrefsFragment extends PreferenceFragmentCompat impleme
|
|||||||
setStorage();
|
setStorage();
|
||||||
setUpSettings();
|
setUpSettings();
|
||||||
setupZoom();
|
setupZoom();
|
||||||
|
setMangeExternalStoragePermission();
|
||||||
new LanguageUtils(getActivity()).changeFont(getActivity().getLayoutInflater(),
|
new LanguageUtils(getActivity()).changeFont(getActivity().getLayoutInflater(),
|
||||||
sharedPreferenceUtil);
|
sharedPreferenceUtil);
|
||||||
}
|
}
|
||||||
@ -174,6 +185,28 @@ public abstract class CorePrefsFragment extends PreferenceFragmentCompat impleme
|
|||||||
versionPref.setSummary(getVersionName() + " Build: " + getVersionCode());
|
versionPref.setSummary(getVersionName() + " Build: " + getVersionCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setMangeExternalStoragePermission() {
|
||||||
|
Preference permissionPref = findPreference(PREF_MANAGE_EXTERNAL_STORAGE_PERMISSION);
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
|
||||||
|
showPermissionPreference();
|
||||||
|
boolean externalStorageManager = Environment.isExternalStorageManager();
|
||||||
|
if (externalStorageManager) {
|
||||||
|
permissionPref.setSummary(R.string.allowed);
|
||||||
|
} else {
|
||||||
|
permissionPref.setSummary(R.string.not_allowed);
|
||||||
|
}
|
||||||
|
permissionPref.setOnPreferenceClickListener(
|
||||||
|
preference -> {
|
||||||
|
navigateToSettings();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void showPermissionPreference() {
|
||||||
|
PreferenceCategory preferenceCategory = findPreference(PREF_PERMISSION);
|
||||||
|
preferenceCategory.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
private int getVersionCode() {
|
private int getVersionCode() {
|
||||||
try {
|
try {
|
||||||
return getActivity().getPackageManager()
|
return getActivity().getPackageManager()
|
||||||
@ -282,4 +315,14 @@ public abstract class CorePrefsFragment extends PreferenceFragmentCompat impleme
|
|||||||
}
|
}
|
||||||
return Unit.INSTANCE;
|
return Unit.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: 28/10/21 Refactor the code. We are using it twice.
|
||||||
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
|
private void navigateToSettings() {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
|
||||||
|
Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null);
|
||||||
|
intent.setData(uri);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,6 +140,13 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
|
|||||||
|
|
||||||
fun updateNightMode() = nightModes.offer(nightMode)
|
fun updateNightMode() = nightModes.offer(nightMode)
|
||||||
|
|
||||||
|
var manageExternalFilesPermissionDialog: Boolean
|
||||||
|
get() = sharedPreferences.getBoolean(PREF_MANAGE_EXTERNAL_FILES, true)
|
||||||
|
set(prefManageExternalFilesPermissionDialog) =
|
||||||
|
sharedPreferences.edit {
|
||||||
|
putBoolean(PREF_MANAGE_EXTERNAL_FILES, prefManageExternalFilesPermissionDialog)
|
||||||
|
}
|
||||||
|
|
||||||
var hostedBooks: Set<String>
|
var hostedBooks: Set<String>
|
||||||
get() = sharedPreferences.getStringSet(PREF_HOSTED_BOOKS, null)?.toHashSet() ?: HashSet()
|
get() = sharedPreferences.getStringSet(PREF_HOSTED_BOOKS, null)?.toHashSet() ?: HashSet()
|
||||||
set(hostedBooks) {
|
set(hostedBooks) {
|
||||||
@ -172,5 +179,6 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
|
|||||||
const val PREF_NIGHT_MODE = "pref_night_mode"
|
const val PREF_NIGHT_MODE = "pref_night_mode"
|
||||||
private const val TEXT_ZOOM = "true_text_zoom"
|
private const val TEXT_ZOOM = "true_text_zoom"
|
||||||
private const val DEFAULT_ZOOM = 100
|
private const val DEFAULT_ZOOM = 100
|
||||||
|
private const val PREF_MANAGE_EXTERNAL_FILES = "pref_manage_external_files"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,14 @@ sealed class KiwixDialog(
|
|||||||
cancelable = false
|
cancelable = false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
object ManageExternalFilesPermissionDialog : KiwixDialog(
|
||||||
|
R.string.all_files_permission_needed,
|
||||||
|
R.string.all_files_permission_needed_message,
|
||||||
|
R.string.yes,
|
||||||
|
R.string.no,
|
||||||
|
cancelable = false
|
||||||
|
)
|
||||||
|
|
||||||
data class ShowHotspotDetails(override val args: List<Any>) : KiwixDialog(
|
data class ShowHotspotDetails(override val args: List<Any>) : KiwixDialog(
|
||||||
R.string.hotspot_turned_on,
|
R.string.hotspot_turned_on,
|
||||||
R.string.hotspot_details_message,
|
R.string.hotspot_details_message,
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
<string name="pref_clear_all_history_title">Clear history</string>
|
<string name="pref_clear_all_history_title">Clear history</string>
|
||||||
<string name="pref_clear_all_history_summary">Clear recent searches and tabs history</string>
|
<string name="pref_clear_all_history_summary">Clear recent searches and tabs history</string>
|
||||||
<string name="pref_notes">Notes</string>
|
<string name="pref_notes">Notes</string>
|
||||||
|
<string name="pref_permission">Permissions</string>
|
||||||
<string name="all_history_cleared">All History Cleared</string>
|
<string name="all_history_cleared">All History Cleared</string>
|
||||||
<string name="pref_clear_all_bookmarks_title">Clear bookmarks</string>
|
<string name="pref_clear_all_bookmarks_title">Clear bookmarks</string>
|
||||||
<string name="clear_all_history_dialog_title">Clear All History?</string>
|
<string name="clear_all_history_dialog_title">Clear All History?</string>
|
||||||
@ -255,6 +256,7 @@
|
|||||||
<string name="status" tools:keep="@string/status">Status</string>
|
<string name="status" tools:keep="@string/status">Status</string>
|
||||||
<string name="pref_clear_all_notes_summary">Clears all notes on all articles</string>
|
<string name="pref_clear_all_notes_summary">Clears all notes on all articles</string>
|
||||||
<string name="pref_clear_all_notes_title">Clear all notes</string>
|
<string name="pref_clear_all_notes_title">Clear all notes</string>
|
||||||
|
<string name="pref_allow_to_read_or_write_zim_files_on_sd_card">Allow to read/write ZIM file\'s on SD card</string>
|
||||||
<string name="pref_text_zoom_summary">Change text size with 25\% increments.</string>
|
<string name="pref_text_zoom_summary">Change text size with 25\% increments.</string>
|
||||||
<string name="tag_pic">Pic</string>
|
<string name="tag_pic">Pic</string>
|
||||||
<string name="tag_vid">Vid</string>
|
<string name="tag_vid">Vid</string>
|
||||||
@ -289,6 +291,10 @@
|
|||||||
<string name="close_drawer">Close Drawer</string>
|
<string name="close_drawer">Close Drawer</string>
|
||||||
<string name="how_to_update_content">How to update content?</string>
|
<string name="how_to_update_content">How to update content?</string>
|
||||||
<string name="update_content_description">To update content (a zim file) you need to download the full latest version of this very same content. You can do that via the download section.</string>
|
<string name="update_content_description">To update content (a zim file) you need to download the full latest version of this very same content. You can do that via the download section.</string>
|
||||||
|
<string name="all_files_permission_needed">All Files Permission Needed</string>
|
||||||
|
<string name="all_files_permission_needed_message">In order to access all the zim files across device we need to have All Files Permission</string>
|
||||||
|
<string name="allowed">Allowed</string>
|
||||||
|
<string name="not_allowed">Not allowed</string>
|
||||||
<string-array name="pref_night_modes_entries">
|
<string-array name="pref_night_modes_entries">
|
||||||
<item>@string/on</item>
|
<item>@string/on</item>
|
||||||
<item>@string/off</item>
|
<item>@string/off</item>
|
||||||
|
@ -95,6 +95,18 @@
|
|||||||
android:title="@string/pref_clear_all_notes_title"
|
android:title="@string/pref_clear_all_notes_title"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
</PreferenceCategory>
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="pref_permissions"
|
||||||
|
android:title="@string/pref_permission"
|
||||||
|
app:isPreferenceVisible="false"
|
||||||
|
app:iconSpaceReserved="false">
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="pref_manage_external_storage"
|
||||||
|
android:title="@string/pref_allow_to_read_or_write_zim_files_on_sd_card"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="pref_language"
|
android:key="pref_language"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user