mirror of
https://github.com/gedoor/legado.git
synced 2025-08-10 00:52:30 +00:00
优化
This commit is contained in:
@@ -4,8 +4,11 @@ import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.lifecycle.LifecycleService
|
||||
import io.legado.app.R
|
||||
import io.legado.app.help.LifecycleHelp
|
||||
import io.legado.app.help.coroutine.Coroutine
|
||||
import io.legado.app.lib.permission.Permissions
|
||||
import io.legado.app.lib.permission.PermissionsCompat
|
||||
import kotlinx.coroutines.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
@@ -22,6 +25,7 @@ abstract class BaseService : LifecycleService(), CoroutineScope by MainScope() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
LifecycleHelp.onServiceCreate(this)
|
||||
checkNotificationPermission()
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@@ -41,4 +45,24 @@ abstract class BaseService : LifecycleService(), CoroutineScope by MainScope() {
|
||||
cancel()
|
||||
LifecycleHelp.onServiceDestroy(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新通知
|
||||
*/
|
||||
open fun upNotification() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测通知权限
|
||||
*/
|
||||
private fun checkNotificationPermission() {
|
||||
PermissionsCompat.Builder()
|
||||
.addPermissions(Permissions.POST_NOTIFICATIONS)
|
||||
.rationale(R.string.notification_permission_rationale)
|
||||
.onGranted {
|
||||
upNotification()
|
||||
}
|
||||
.request()
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package io.legado.app.lib.permission
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
internal class ActivitySource(activity: AppCompatActivity) : RequestSource {
|
||||
|
||||
private val actRef: WeakReference<AppCompatActivity> = WeakReference(activity)
|
||||
|
||||
override val context: Context?
|
||||
get() = actRef.get()
|
||||
|
||||
override fun startActivity(intent: Intent) {
|
||||
actRef.get()?.startActivity(intent)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.legado.app.lib.permission
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
internal class FragmentSource(fragment: Fragment) : RequestSource {
|
||||
|
||||
private val fragRef: WeakReference<Fragment> = WeakReference(fragment)
|
||||
|
||||
override val context: Context?
|
||||
get() = fragRef.get()?.requireContext()
|
||||
|
||||
override fun startActivity(intent: Intent) {
|
||||
fragRef.get()?.startActivity(intent)
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.view.KeyEvent
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import io.legado.app.R
|
||||
@@ -15,6 +16,8 @@ import io.legado.app.utils.toastOnUi
|
||||
|
||||
class PermissionActivity : AppCompatActivity() {
|
||||
|
||||
private var rationaleDialog: AlertDialog? = null
|
||||
|
||||
private val settingActivityResult =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
RequestPlugins.sRequestCallback?.onSettingActivityResult()
|
||||
@@ -23,42 +26,45 @@ class PermissionActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val rationale = intent.getStringExtra(KEY_RATIONALE)
|
||||
val requestCode = intent.getIntExtra(KEY_INPUT_PERMISSIONS_CODE, 1000)
|
||||
val permissions = intent.getStringArrayExtra(KEY_INPUT_PERMISSIONS)
|
||||
val permissions = intent.getStringArrayExtra(KEY_INPUT_PERMISSIONS)!!
|
||||
when (intent.getIntExtra(KEY_INPUT_REQUEST_TYPE, Request.TYPE_REQUEST_PERMISSION)) {
|
||||
//权限请求
|
||||
Request.TYPE_REQUEST_PERMISSION -> {
|
||||
if (permissions != null) {
|
||||
ActivityCompat.requestPermissions(this, permissions, requestCode)
|
||||
} else {
|
||||
Request.TYPE_REQUEST_PERMISSION -> showSettingDialog(permissions, rationale){
|
||||
ActivityCompat.requestPermissions(this, permissions, requestCode)
|
||||
}
|
||||
//跳转到设置界面
|
||||
Request.TYPE_REQUEST_SETTING -> showSettingDialog(permissions, rationale) {
|
||||
openSettingsActivity()
|
||||
}
|
||||
//所有文件的管理权限
|
||||
Request.TYPE_MANAGE_ALL_FILES_ACCESS -> showSettingDialog(permissions, rationale) {
|
||||
try {
|
||||
if (Permissions.isManageExternalStorage()) {
|
||||
val settingIntent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
|
||||
settingActivityResult.launch(settingIntent)
|
||||
} else {
|
||||
throw NoStackTraceException("no MANAGE_ALL_FILES_ACCESS_PERMISSION")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
toastOnUi(e.localizedMessage)
|
||||
RequestPlugins.sRequestCallback?.onError(e)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
//跳转到设置界面
|
||||
Request.TYPE_REQUEST_SETTING -> openSettingsActivity()
|
||||
//所有文件的管理权限
|
||||
Request.TYPE_MANAGE_ALL_FILES_ACCESS_PERMISSION -> try {
|
||||
if (Permissions.isManageExternalStorage()) {
|
||||
val settingIntent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
|
||||
settingActivityResult.launch(settingIntent)
|
||||
} else {
|
||||
throw NoStackTraceException("no MANAGE_ALL_FILES_ACCESS_PERMISSION")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
toastOnUi(e.localizedMessage)
|
||||
RequestPlugins.sRequestCallback?.onError(e)
|
||||
finish()
|
||||
}
|
||||
Request.TYPE_REQUEST_NOTIFICATIONS -> kotlin.runCatching {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
//这种方案适用于 API 26, 即8.0(含8.0)以上可以用
|
||||
val intent = Intent()
|
||||
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
|
||||
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
|
||||
intent.putExtra(Settings.EXTRA_CHANNEL_ID, applicationInfo.uid)
|
||||
settingActivityResult.launch(intent)
|
||||
} else {
|
||||
openSettingsActivity()
|
||||
Request.TYPE_REQUEST_NOTIFICATIONS -> showSettingDialog(permissions, rationale) {
|
||||
kotlin.runCatching {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
//这种方案适用于 API 26, 即8.0(含8.0)以上可以用
|
||||
val intent = Intent()
|
||||
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
|
||||
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
|
||||
intent.putExtra(Settings.EXTRA_CHANNEL_ID, applicationInfo.uid)
|
||||
settingActivityResult.launch(intent)
|
||||
} else {
|
||||
openSettingsActivity()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,8 +112,34 @@ class PermissionActivity : AppCompatActivity() {
|
||||
} else super.onKeyDown(keyCode, event)
|
||||
}
|
||||
|
||||
private fun showSettingDialog(
|
||||
permissions: Array<String>,
|
||||
rationale: CharSequence?,
|
||||
onOk: () -> Unit
|
||||
) {
|
||||
rationaleDialog?.dismiss()
|
||||
if (rationale.isNullOrEmpty()) {
|
||||
|
||||
return
|
||||
}
|
||||
rationaleDialog = AlertDialog.Builder(this)
|
||||
.setTitle(R.string.dialog_title)
|
||||
.setMessage(rationale)
|
||||
.setPositiveButton(R.string.dialog_setting) { _, _ ->
|
||||
onOk.invoke()
|
||||
}
|
||||
.setNegativeButton(R.string.dialog_cancel) { _, _ ->
|
||||
RequestPlugins.sRequestCallback?.onRequestPermissionsResult(
|
||||
permissions,
|
||||
IntArray(0)
|
||||
)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val KEY_RATIONALE = "KEY_RATIONALE"
|
||||
const val KEY_INPUT_REQUEST_TYPE = "KEY_INPUT_REQUEST_TYPE"
|
||||
const val KEY_INPUT_PERMISSIONS_CODE = "KEY_INPUT_PERMISSIONS_CODE"
|
||||
const val KEY_INPUT_PERMISSIONS = "KEY_INPUT_PERMISSIONS"
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package io.legado.app.lib.permission
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
@Suppress("unused")
|
||||
class PermissionsCompat private constructor() {
|
||||
@@ -14,15 +12,7 @@ class PermissionsCompat private constructor() {
|
||||
}
|
||||
|
||||
class Builder {
|
||||
private val request: Request
|
||||
|
||||
constructor(activity: AppCompatActivity) {
|
||||
request = Request(activity)
|
||||
}
|
||||
|
||||
constructor(fragment: Fragment) {
|
||||
request = Request(fragment)
|
||||
}
|
||||
private val request: Request = Request()
|
||||
|
||||
fun addPermissions(vararg permissions: String): Builder {
|
||||
request.addPermissions(*permissions)
|
||||
|
||||
@@ -4,48 +4,29 @@ import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import io.legado.app.R
|
||||
import io.legado.app.utils.startActivity
|
||||
import splitties.init.appCtx
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
internal class Request : OnRequestPermissionsResultCallback {
|
||||
|
||||
internal val requestTime: Long
|
||||
internal val requestTime: Long = System.currentTimeMillis()
|
||||
private var requestCode: Int = TYPE_REQUEST_PERMISSION
|
||||
private var source: RequestSource? = null
|
||||
private var permissions: ArrayList<String>? = null
|
||||
private var permissions: ArrayList<String> = ArrayList()
|
||||
private var grantedCallback: OnPermissionsGrantedCallback? = null
|
||||
private var deniedCallback: OnPermissionsDeniedCallback? = null
|
||||
private var errorCallback: OnErrorCallback? = null
|
||||
private var rationale: CharSequence? = null
|
||||
|
||||
private var rationaleDialog: AlertDialog? = null
|
||||
|
||||
private val deniedPermissions: Array<String>?
|
||||
get() {
|
||||
return getDeniedPermissions(this.permissions?.toTypedArray())
|
||||
return getDeniedPermissions(this.permissions.toTypedArray())
|
||||
}
|
||||
|
||||
constructor(activity: AppCompatActivity) {
|
||||
source = ActivitySource(activity)
|
||||
permissions = ArrayList()
|
||||
requestTime = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
constructor(fragment: Fragment) {
|
||||
source = FragmentSource(fragment)
|
||||
permissions = ArrayList()
|
||||
requestTime = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
fun addPermissions(vararg permissions: String) {
|
||||
this.permissions?.addAll(listOf(*permissions))
|
||||
this.permissions.addAll(listOf(*permissions))
|
||||
}
|
||||
|
||||
fun setOnGrantedCallback(callback: OnPermissionsGrantedCallback) {
|
||||
@@ -61,7 +42,7 @@ internal class Request : OnRequestPermissionsResultCallback {
|
||||
}
|
||||
|
||||
fun setRationale(@StringRes resId: Int) {
|
||||
rationale = source?.context?.getString(resId)
|
||||
rationale = appCtx.getString(resId)
|
||||
}
|
||||
|
||||
fun setRationale(rationale: CharSequence) {
|
||||
@@ -82,22 +63,16 @@ internal class Request : OnRequestPermissionsResultCallback {
|
||||
return
|
||||
}
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
showSettingDialog(deniedPermissions, rationale) {
|
||||
toSetting()
|
||||
}
|
||||
toSetting()
|
||||
} else {
|
||||
if (deniedPermissions.contains(Permissions.MANAGE_EXTERNAL_STORAGE)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
showSettingDialog(deniedPermissions, rationale) {
|
||||
toManageFileSetting()
|
||||
}
|
||||
toManageFileSetting()
|
||||
}
|
||||
} else if (deniedPermissions.contains(Permissions.POST_NOTIFICATIONS)) {
|
||||
showSettingDialog(deniedPermissions, rationale) {
|
||||
toNotificationSetting()
|
||||
}
|
||||
toNotificationSetting()
|
||||
} else if (deniedPermissions.size > 1) {
|
||||
source?.context?.startActivity<PermissionActivity> {
|
||||
appCtx.startActivity<PermissionActivity> {
|
||||
putExtra(PermissionActivity.KEY_INPUT_REQUEST_TYPE, TYPE_REQUEST_PERMISSION)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS_CODE, requestCode)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS, deniedPermissions)
|
||||
@@ -111,92 +86,39 @@ internal class Request : OnRequestPermissionsResultCallback {
|
||||
deniedCallback = null
|
||||
}
|
||||
|
||||
fun getDeniedPermissions(permissions: Array<String>?): Array<String>? {
|
||||
val context = source?.context ?: return permissions
|
||||
if (permissions != null) {
|
||||
val deniedPermissionList = ArrayList<String>()
|
||||
for (permission in permissions) {
|
||||
when (permission) {
|
||||
Permissions.POST_NOTIFICATIONS -> {
|
||||
if (!NotificationManagerCompat.from(appCtx).areNotificationsEnabled()) {
|
||||
deniedPermissionList.add(permission)
|
||||
}
|
||||
fun getDeniedPermissions(permissions: Array<String>): Array<String>? {
|
||||
val deniedPermissionList = ArrayList<String>()
|
||||
for (permission in permissions) {
|
||||
when (permission) {
|
||||
Permissions.POST_NOTIFICATIONS -> {
|
||||
if (!NotificationManagerCompat.from(appCtx).areNotificationsEnabled()) {
|
||||
deniedPermissionList.add(permission)
|
||||
}
|
||||
Permissions.MANAGE_EXTERNAL_STORAGE -> {
|
||||
if (Permissions.isManageExternalStorage()) {
|
||||
if (!Environment.isExternalStorageManager()) {
|
||||
deniedPermissionList.add(permission)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if (
|
||||
ContextCompat.checkSelfPermission(context, permission)
|
||||
!= PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
}
|
||||
Permissions.MANAGE_EXTERNAL_STORAGE -> {
|
||||
if (Permissions.isManageExternalStorage()) {
|
||||
if (!Environment.isExternalStorageManager()) {
|
||||
deniedPermissionList.add(permission)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if (
|
||||
ContextCompat.checkSelfPermission(appCtx, permission)
|
||||
!= PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
deniedPermissionList.add(permission)
|
||||
}
|
||||
}
|
||||
}
|
||||
val size = deniedPermissionList.size
|
||||
if (size > 0) {
|
||||
return deniedPermissionList.toTypedArray()
|
||||
}
|
||||
}
|
||||
val size = deniedPermissionList.size
|
||||
if (size > 0) {
|
||||
return deniedPermissionList.toTypedArray()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun showSettingDialog(
|
||||
permissions: Array<String>,
|
||||
rationale: CharSequence,
|
||||
onOk: () -> Unit
|
||||
) {
|
||||
rationaleDialog?.dismiss()
|
||||
source?.context?.let {
|
||||
runCatching {
|
||||
rationaleDialog = AlertDialog.Builder(it)
|
||||
.setTitle(R.string.dialog_title)
|
||||
.setMessage(rationale)
|
||||
.setPositiveButton(R.string.dialog_setting) { _, _ ->
|
||||
onOk.invoke()
|
||||
}
|
||||
.setNegativeButton(R.string.dialog_cancel) { _, _ ->
|
||||
onPermissionsDenied(permissions)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun toSetting() {
|
||||
source?.context?.startActivity<PermissionActivity> {
|
||||
putExtra(
|
||||
PermissionActivity.KEY_INPUT_REQUEST_TYPE,
|
||||
TYPE_REQUEST_SETTING
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toManageFileSetting() {
|
||||
source?.context?.startActivity<PermissionActivity> {
|
||||
putExtra(
|
||||
PermissionActivity.KEY_INPUT_REQUEST_TYPE,
|
||||
TYPE_MANAGE_ALL_FILES_ACCESS_PERMISSION
|
||||
)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS_CODE, requestCode)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS, deniedPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toNotificationSetting() {
|
||||
source?.context?.startActivity<PermissionActivity> {
|
||||
putExtra(PermissionActivity.KEY_INPUT_REQUEST_TYPE, TYPE_REQUEST_NOTIFICATIONS)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS_CODE, requestCode)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS, deniedPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onPermissionsGranted() {
|
||||
try {
|
||||
grantedCallback?.onPermissionsGranted()
|
||||
@@ -215,20 +137,40 @@ internal class Request : OnRequestPermissionsResultCallback {
|
||||
RequestPlugins.sResultCallback?.onPermissionsDenied(deniedPermissions)
|
||||
}
|
||||
|
||||
private fun toSetting() {
|
||||
appCtx.startActivity<PermissionActivity> {
|
||||
putExtra(
|
||||
PermissionActivity.KEY_INPUT_REQUEST_TYPE,
|
||||
TYPE_REQUEST_SETTING
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toManageFileSetting() {
|
||||
appCtx.startActivity<PermissionActivity> {
|
||||
putExtra(PermissionActivity.KEY_RATIONALE, rationale)
|
||||
putExtra(PermissionActivity.KEY_INPUT_REQUEST_TYPE, TYPE_MANAGE_ALL_FILES_ACCESS)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS_CODE, requestCode)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS, deniedPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toNotificationSetting() {
|
||||
appCtx.startActivity<PermissionActivity> {
|
||||
putExtra(PermissionActivity.KEY_RATIONALE, rationale)
|
||||
putExtra(PermissionActivity.KEY_INPUT_REQUEST_TYPE, TYPE_REQUEST_NOTIFICATIONS)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS_CODE, requestCode)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS, deniedPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
permissions: Array<String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
val deniedPermissions = getDeniedPermissions(permissions)
|
||||
if (deniedPermissions != null) {
|
||||
val rationale = this.rationale
|
||||
if (rationale != null) {
|
||||
showSettingDialog(deniedPermissions, rationale) {
|
||||
|
||||
}
|
||||
} else {
|
||||
onPermissionsDenied(deniedPermissions)
|
||||
}
|
||||
onPermissionsDenied(deniedPermissions)
|
||||
} else {
|
||||
onPermissionsGranted()
|
||||
}
|
||||
@@ -251,7 +193,7 @@ internal class Request : OnRequestPermissionsResultCallback {
|
||||
companion object {
|
||||
const val TYPE_REQUEST_PERMISSION = 1
|
||||
const val TYPE_REQUEST_SETTING = 2
|
||||
const val TYPE_MANAGE_ALL_FILES_ACCESS_PERMISSION = 3
|
||||
const val TYPE_MANAGE_ALL_FILES_ACCESS = 3
|
||||
const val TYPE_REQUEST_NOTIFICATIONS = 4
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.legado.app.lib.permission
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
||||
interface RequestSource {
|
||||
|
||||
val context: Context?
|
||||
|
||||
fun startActivity(intent: Intent)
|
||||
|
||||
}
|
||||
@@ -495,7 +495,7 @@ class AudioPlayService : BaseService(),
|
||||
/**
|
||||
* 更新通知
|
||||
*/
|
||||
private fun upNotification() {
|
||||
override fun upNotification() {
|
||||
execute {
|
||||
var nTitle: String = when {
|
||||
pause -> getString(R.string.audio_pause)
|
||||
|
||||
@@ -355,7 +355,7 @@ abstract class BaseReadAloudService : BaseService(),
|
||||
/**
|
||||
* 更新通知
|
||||
*/
|
||||
private fun upNotification() {
|
||||
override fun upNotification() {
|
||||
execute {
|
||||
var nTitle: String = when {
|
||||
pause -> getString(R.string.read_aloud_pause)
|
||||
|
||||
@@ -260,7 +260,7 @@ class CheckSourceService : BaseService() {
|
||||
/**
|
||||
* 更新通知
|
||||
*/
|
||||
private fun upNotification() {
|
||||
override fun upNotification() {
|
||||
notificationBuilder.setContentText(notificationMsg)
|
||||
notificationBuilder.setProgress(allIds.size, checkedIds.size, false)
|
||||
postEvent(EventBus.CHECK_SOURCE, notificationMsg)
|
||||
|
||||
@@ -144,7 +144,7 @@ class WebService : BaseService() {
|
||||
/**
|
||||
* 更新通知
|
||||
*/
|
||||
private fun upNotification() {
|
||||
override fun upNotification() {
|
||||
val builder = NotificationCompat.Builder(this, AppConst.channelIdWeb)
|
||||
.setSmallIcon(R.drawable.ic_web_service_noti)
|
||||
.setOngoing(true)
|
||||
|
||||
@@ -109,7 +109,7 @@ class FileAssociationActivity :
|
||||
if (data.isContentScheme()) {
|
||||
viewModel.dispatchIndent(data)
|
||||
} else if (!AppConst.isPlayChannel || Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
|
||||
PermissionsCompat.Builder(this)
|
||||
PermissionsCompat.Builder()
|
||||
.addPermissions(*Permissions.Group.STORAGE)
|
||||
.rationale(R.string.tip_perm_request_storage)
|
||||
.onGranted {
|
||||
|
||||
@@ -189,7 +189,7 @@ class ImportBookActivity : BaseImportBookActivity<ActivityImportBookBinding, Imp
|
||||
|
||||
private fun initRootPath(path: String) {
|
||||
binding.tvEmptyMsg.visible()
|
||||
PermissionsCompat.Builder(this)
|
||||
PermissionsCompat.Builder()
|
||||
.addPermissions(*Permissions.Group.STORAGE)
|
||||
.rationale(R.string.tip_perm_request_storage)
|
||||
.onGranted {
|
||||
|
||||
@@ -295,7 +295,7 @@ class BackupConfigFragment : PreferenceFragment(),
|
||||
}
|
||||
|
||||
private fun backupUsePermission(path: String) {
|
||||
PermissionsCompat.Builder(this)
|
||||
PermissionsCompat.Builder()
|
||||
.addPermissions(*Permissions.Group.STORAGE)
|
||||
.rationale(R.string.tip_perm_request_storage)
|
||||
.onGranted {
|
||||
@@ -366,7 +366,7 @@ class BackupConfigFragment : PreferenceFragment(),
|
||||
}
|
||||
|
||||
private fun restoreUsePermission(path: String) {
|
||||
PermissionsCompat.Builder(this)
|
||||
PermissionsCompat.Builder()
|
||||
.addPermissions(*Permissions.Group.STORAGE)
|
||||
.rationale(R.string.tip_perm_request_storage)
|
||||
.onGranted {
|
||||
|
||||
@@ -182,7 +182,7 @@ class HandleFileActivity :
|
||||
}
|
||||
|
||||
private fun checkPermissions(success: (() -> Unit)? = null) {
|
||||
PermissionsCompat.Builder(this)
|
||||
PermissionsCompat.Builder()
|
||||
.addPermissions(*Permissions.Group.STORAGE)
|
||||
.rationale(R.string.tip_perm_request_storage)
|
||||
.onGranted {
|
||||
|
||||
@@ -127,7 +127,7 @@ class FontSelectDialog : BaseDialogFragment(R.layout.dialog_font_select),
|
||||
}
|
||||
|
||||
private fun loadFontFilesByPermission(path: String) {
|
||||
PermissionsCompat.Builder(this@FontSelectDialog)
|
||||
PermissionsCompat.Builder()
|
||||
.addPermissions(*Permissions.Group.STORAGE)
|
||||
.rationale(R.string.tip_perm_request_storage)
|
||||
.onGranted {
|
||||
|
||||
@@ -28,8 +28,6 @@ import io.legado.app.help.config.LocalConfig
|
||||
import io.legado.app.help.coroutine.Coroutine
|
||||
import io.legado.app.help.storage.Backup
|
||||
import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.permission.Permissions
|
||||
import io.legado.app.lib.permission.PermissionsCompat
|
||||
import io.legado.app.lib.theme.elevation
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.service.BaseReadAloudService
|
||||
@@ -94,8 +92,6 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
|
||||
if (!privacyPolicy()) return@launch
|
||||
//版本更新
|
||||
upVersion()
|
||||
//检测通知权限
|
||||
checkNotificationPermission()
|
||||
//备份同步
|
||||
backupSync()
|
||||
//自动更新书籍
|
||||
@@ -198,25 +194,6 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测通知权限
|
||||
*/
|
||||
private suspend fun checkNotificationPermission() = suspendCoroutine { block ->
|
||||
PermissionsCompat.Builder(this)
|
||||
.addPermissions(Permissions.POST_NOTIFICATIONS)
|
||||
.rationale(R.string.notification_permission_rationale)
|
||||
.onDenied {
|
||||
block.resume(null)
|
||||
}
|
||||
.onGranted {
|
||||
block.resume(null)
|
||||
}
|
||||
.onError {
|
||||
block.resume(null)
|
||||
}
|
||||
.request()
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份同步
|
||||
*/
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.widget.EditText
|
||||
import androidx.activity.viewModels
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.VMBaseActivity
|
||||
@@ -14,6 +15,8 @@ import io.legado.app.databinding.ActivityRssSourceEditBinding
|
||||
import io.legado.app.help.config.LocalConfig
|
||||
import io.legado.app.lib.dialogs.SelectItem
|
||||
import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.theme.accentColor
|
||||
import io.legado.app.lib.theme.backgroundColor
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.ui.document.HandleFileContract
|
||||
import io.legado.app.ui.login.SourceLoginActivity
|
||||
@@ -37,6 +40,8 @@ class RssSourceEditActivity :
|
||||
}
|
||||
private val adapter by lazy { RssSourceEditAdapter() }
|
||||
private val sourceEntities: ArrayList<EditEntity> = ArrayList()
|
||||
private val listEntities: ArrayList<EditEntity> = ArrayList()
|
||||
private val webViewEntities: ArrayList<EditEntity> = ArrayList()
|
||||
private val selectDoc = registerForActivityResult(HandleFileContract()) {
|
||||
it.uri?.let { uri ->
|
||||
if (uri.isContentScheme()) {
|
||||
@@ -148,8 +153,41 @@ class RssSourceEditActivity :
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
binding.tabLayout.addTab(binding.tabLayout.newTab().apply {
|
||||
setText(R.string.source_tab_base)
|
||||
})
|
||||
binding.tabLayout.addTab(binding.tabLayout.newTab().apply {
|
||||
setText(R.string.source_tab_list)
|
||||
})
|
||||
binding.tabLayout.addTab(binding.tabLayout.newTab().apply {
|
||||
text = "WEB_VIEW"
|
||||
})
|
||||
binding.recyclerView.setEdgeEffectColor(primaryColor)
|
||||
binding.recyclerView.adapter = adapter
|
||||
binding.tabLayout.setBackgroundColor(backgroundColor)
|
||||
binding.tabLayout.setSelectedTabIndicatorColor(accentColor)
|
||||
binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||
setEditEntities(tab?.position)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun setEditEntities(tabPosition: Int?) {
|
||||
when (tabPosition) {
|
||||
1 -> adapter.editEntities = listEntities
|
||||
2 -> adapter.editEntities = webViewEntities
|
||||
else -> adapter.editEntities = sourceEntities
|
||||
}
|
||||
binding.recyclerView.scrollToPosition(0)
|
||||
}
|
||||
|
||||
private fun upSourceView(rs: RssSource? = viewModel.rssSource) {
|
||||
@@ -175,6 +213,9 @@ class RssSourceEditActivity :
|
||||
add(EditEntity("variableComment", rs?.variableComment, R.string.variable_comment))
|
||||
add(EditEntity("concurrentRate", rs?.concurrentRate, R.string.concurrent_rate))
|
||||
add(EditEntity("sortUrl", rs?.sortUrl, R.string.sort_url))
|
||||
}
|
||||
listEntities.clear()
|
||||
listEntities.apply {
|
||||
add(EditEntity("ruleArticles", rs?.ruleArticles, R.string.r_articles))
|
||||
add(EditEntity("ruleNextPage", rs?.ruleNextPage, R.string.r_next))
|
||||
add(EditEntity("ruleTitle", rs?.ruleTitle, R.string.r_title))
|
||||
@@ -182,13 +223,17 @@ class RssSourceEditActivity :
|
||||
add(EditEntity("ruleDescription", rs?.ruleDescription, R.string.r_description))
|
||||
add(EditEntity("ruleImage", rs?.ruleImage, R.string.r_image))
|
||||
add(EditEntity("ruleLink", rs?.ruleLink, R.string.r_link))
|
||||
}
|
||||
webViewEntities.clear()
|
||||
webViewEntities.apply {
|
||||
add(EditEntity("ruleContent", rs?.ruleContent, R.string.r_content))
|
||||
add(EditEntity("style", rs?.style, R.string.r_style))
|
||||
add(EditEntity("injectJs", rs?.injectJs, R.string.r_inject_js))
|
||||
add(EditEntity("contentWhitelist", rs?.contentWhitelist, R.string.c_whitelist))
|
||||
add(EditEntity("contentBlacklist", rs?.contentBlacklist, R.string.c_blacklist))
|
||||
}
|
||||
adapter.editEntities = sourceEntities
|
||||
binding.tabLayout.selectTab(binding.tabLayout.getTabAt(0))
|
||||
setEditEntities(0)
|
||||
}
|
||||
|
||||
private fun getRssSource(): RssSource {
|
||||
@@ -213,6 +258,10 @@ class RssSourceEditActivity :
|
||||
"variableComment" -> source.variableComment = it.value
|
||||
"concurrentRate" -> source.concurrentRate = it.value
|
||||
"sortUrl" -> source.sortUrl = it.value
|
||||
}
|
||||
}
|
||||
listEntities.forEach {
|
||||
when (it.key) {
|
||||
"ruleArticles" -> source.ruleArticles = it.value
|
||||
"ruleNextPage" -> source.ruleNextPage =
|
||||
viewModel.ruleComplete(it.value, source.ruleArticles, 2)
|
||||
@@ -226,6 +275,10 @@ class RssSourceEditActivity :
|
||||
viewModel.ruleComplete(it.value, source.ruleArticles, 3)
|
||||
"ruleLink" -> source.ruleLink =
|
||||
viewModel.ruleComplete(it.value, source.ruleArticles)
|
||||
}
|
||||
}
|
||||
webViewEntities.forEach {
|
||||
when (it.key) {
|
||||
"ruleContent" -> source.ruleContent =
|
||||
viewModel.ruleComplete(it.value, source.ruleArticles)
|
||||
"style" -> source.style = it.value
|
||||
|
||||
@@ -41,7 +41,7 @@ fun AppCompatActivity.readUri(
|
||||
success.invoke(fileDoc, inputStream)
|
||||
}
|
||||
} else {
|
||||
PermissionsCompat.Builder(this)
|
||||
PermissionsCompat.Builder()
|
||||
.addPermissions(
|
||||
Permissions.READ_EXTERNAL_STORAGE,
|
||||
Permissions.WRITE_EXTERNAL_STORAGE
|
||||
@@ -81,7 +81,7 @@ fun Fragment.readUri(uri: Uri?, success: (fileDoc: FileDoc, inputStream: InputSt
|
||||
success.invoke(fileDoc, inputStream)
|
||||
}
|
||||
} else {
|
||||
PermissionsCompat.Builder(this)
|
||||
PermissionsCompat.Builder()
|
||||
.addPermissions(
|
||||
Permissions.READ_EXTERNAL_STORAGE,
|
||||
Permissions.WRITE_EXTERNAL_STORAGE
|
||||
|
||||
@@ -87,6 +87,14 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tab_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="36dp"
|
||||
android:background="@color/background"
|
||||
android:elevation="3dp"
|
||||
tools:ignore="SpeakableTextPresentCheck" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -1071,4 +1071,5 @@
|
||||
<string name="jump_to_another_app">跳转其它应用</string>
|
||||
<string name="clear_webview_data">清除 WebView 数据</string>
|
||||
<string name="clear_webview_data_summary">清除内置浏览器所有数据</string>
|
||||
<string name="source_tab_list">列表</string>
|
||||
</resources>
|
||||
|
||||
@@ -1074,4 +1074,5 @@
|
||||
<string name="jump_to_another_app">跳转其它应用</string>
|
||||
<string name="clear_webview_data">清除 WebView 数据</string>
|
||||
<string name="clear_webview_data_summary">清除内置浏览器所有数据</string>
|
||||
<string name="source_tab_list">列表</string>
|
||||
</resources>
|
||||
|
||||
@@ -1074,4 +1074,5 @@
|
||||
<string name="jump_to_another_app">跳转其它应用</string>
|
||||
<string name="clear_webview_data">清除 WebView 数据</string>
|
||||
<string name="clear_webview_data_summary">清除内置浏览器所有数据</string>
|
||||
<string name="source_tab_list">列表</string>
|
||||
</resources>
|
||||
|
||||
@@ -1071,4 +1071,5 @@
|
||||
<string name="jump_to_another_app">跳转其它应用</string>
|
||||
<string name="clear_webview_data">清除 WebView 数据</string>
|
||||
<string name="clear_webview_data_summary">清除内置浏览器所有数据</string>
|
||||
<string name="source_tab_list">列表</string>
|
||||
</resources>
|
||||
|
||||
@@ -1073,4 +1073,5 @@
|
||||
<string name="jump_to_another_app">跳转其它应用</string>
|
||||
<string name="clear_webview_data">清除 WebView 数据</string>
|
||||
<string name="clear_webview_data_summary">清除内置浏览器所有数据</string>
|
||||
<string name="source_tab_list">列表</string>
|
||||
</resources>
|
||||
|
||||
@@ -1073,4 +1073,5 @@
|
||||
<string name="jump_to_another_app">跳转其它应用</string>
|
||||
<string name="clear_webview_data">清除 WebView 数据</string>
|
||||
<string name="clear_webview_data_summary">清除内置浏览器所有数据</string>
|
||||
<string name="source_tab_list">列表</string>
|
||||
</resources>
|
||||
|
||||
@@ -1074,4 +1074,5 @@
|
||||
<string name="jump_to_another_app">Jump to another app</string>
|
||||
<string name="clear_webview_data">清除 WebView 数据</string>
|
||||
<string name="clear_webview_data_summary">清除内置浏览器所有数据</string>
|
||||
<string name="source_tab_list">List</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user