加上動態申請權限
This commit is contained in:
parent
3b25ab2ab7
commit
e5ba0fe34b
@ -3,8 +3,11 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
|
||||
<application
|
||||
android:name=".MyApplication"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
@ -39,6 +42,18 @@
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/i_o_s_clock_widget_info" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".AutoStartReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true" >
|
||||
<intent-filter>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@ -34,8 +34,6 @@ class AlarmService : Service() {
|
||||
|
||||
isServiceRunning = true
|
||||
|
||||
//RetrofitClient.init("http://192.168.0.173:8080")
|
||||
|
||||
startForeground()
|
||||
}
|
||||
|
||||
@ -105,7 +103,7 @@ class AlarmService : Service() {
|
||||
companion object {
|
||||
private val TAG = AlarmService::class.java.simpleName
|
||||
|
||||
const val SERVICE_ID = 0x1
|
||||
const val SERVICE_ID = 0x101
|
||||
|
||||
private const val NOTIFICATION_SERVICE_CH = "clock.service"
|
||||
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
package com.ray650128.iosclockwidget
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
|
||||
class AutoStartReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
Log.d("AutoStartReceiver", "intent: ${intent?.action}")
|
||||
if (context == null || intent == null) return
|
||||
if (!PreferenceUtil.isGranted) return
|
||||
val i = Intent(context, AlarmService::class.java)
|
||||
context.startForegroundService(i)
|
||||
Log.d("AutoStartReceiver", "Boot completed.")
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,52 @@
|
||||
package com.ray650128.iosclockwidget
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.os.Bundle
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private val callback = object : PermissionUtil.PermissionResultCallback {
|
||||
override fun onGrant() {
|
||||
PreferenceUtil.isGranted = true
|
||||
if (AlarmService.isServiceRunning) return
|
||||
startForegroundService(
|
||||
Intent(this@MainActivity, AlarmService::class.java)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDeny(denies: ArrayList<String>?) {
|
||||
PreferenceUtil.isGranted = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
if (!AlarmService.isServiceRunning) {
|
||||
checkPermissionForNotification()
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<out String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
PermissionUtil.onRequestPermissionsResult(this, requestCode, permissions, grantResults)
|
||||
}
|
||||
|
||||
private fun checkPermissionForNotification() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
PermissionUtil.checkPermission(this,
|
||||
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
|
||||
callback
|
||||
)
|
||||
} else {
|
||||
PreferenceUtil.isGranted = true
|
||||
if (AlarmService.isServiceRunning) return
|
||||
startForegroundService(
|
||||
Intent(this@MainActivity, AlarmService::class.java)
|
||||
)
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package com.ray650128.iosclockwidget
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
|
||||
class MyApplication : Application() {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
instance = this
|
||||
}
|
||||
|
||||
companion object {
|
||||
var instance: Application? = null
|
||||
|
||||
fun getAppContext(): Context {
|
||||
return instance!!.applicationContext
|
||||
}
|
||||
}
|
||||
}
|
||||
169
app/src/main/java/com/ray650128/iosclockwidget/PermissionUtil.kt
Normal file
169
app/src/main/java/com/ray650128/iosclockwidget/PermissionUtil.kt
Normal file
@ -0,0 +1,169 @@
|
||||
package com.ray650128.iosclockwidget
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import androidx.annotation.NonNull
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
|
||||
|
||||
/**
|
||||
* 權限工具
|
||||
* 用法:
|
||||
* 1.在 Activity 中定義所需的權限陣列
|
||||
* 2.呼叫 PermissionUtil.checkPermissions()
|
||||
* 3.在 PermissionResultCallback 中處理權限授與或拒絕的處裡
|
||||
*/
|
||||
object PermissionUtil {
|
||||
/**
|
||||
* 當權限拒絕時,是否顯示系統的應用程式設定頁面
|
||||
*/
|
||||
var showSystemSetting: Boolean = true
|
||||
|
||||
private const val mRequestCode: Int = 100
|
||||
private var mPermissionResult: PermissionResultCallback? = null
|
||||
private var mPermissionDialog: AlertDialog? = null
|
||||
|
||||
/**
|
||||
* 檢查權限
|
||||
* @param context Activity 對象
|
||||
* @param permissions 要求的權限陣列
|
||||
* @param permissionResultCallback 權限授與/拒絕的回呼
|
||||
*/
|
||||
fun checkPermission(
|
||||
context: Activity,
|
||||
permissions: Array<String>,
|
||||
@NonNull permissionResultCallback: PermissionResultCallback
|
||||
) {
|
||||
mPermissionResult = permissionResultCallback
|
||||
|
||||
if (Build.VERSION.SDK_INT < 23) { // 如果系統低於 Android 6.0,不使用動態申請
|
||||
permissionResultCallback.onGrant()
|
||||
return
|
||||
}
|
||||
|
||||
// 遍歷整個 permissions 陣列,檢查有哪些權限未允許
|
||||
val mPermissionList = ArrayList<String>()
|
||||
for (permission in permissions) {
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
context,
|
||||
permission
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// 將沒有允許的權限加入 mPermissionList
|
||||
mPermissionList.add(permission)
|
||||
}
|
||||
}
|
||||
|
||||
// 申請權限
|
||||
if (mPermissionList.size > 0) { // mPermissionList 中有權限沒有被允許
|
||||
ActivityCompat.requestPermissions(context, permissions, mRequestCode)
|
||||
} else {
|
||||
// 全部的權限都已被允許
|
||||
permissionResultCallback.onGrant()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* onRequestPermissionsResult,
|
||||
* 請務必在 Activity 的 onRequestPermissionsResult 呼叫此方法
|
||||
* @param context Activity 對象
|
||||
* @param requestCode
|
||||
* @param permissions
|
||||
* @param grantResults
|
||||
*/
|
||||
fun onRequestPermissionsResult(
|
||||
context: Activity,
|
||||
requestCode: Int,
|
||||
@NonNull permissions: Array<out String>,
|
||||
@NonNull grantResults: IntArray
|
||||
) {
|
||||
// 檢查是否有權限被拒
|
||||
var hasPermissionDenied = false
|
||||
|
||||
// 被拒絕的權限
|
||||
val denyList = ArrayList<String>()
|
||||
|
||||
if (mRequestCode == requestCode) {
|
||||
for (i in grantResults.indices) {
|
||||
if (grantResults[i] == -1) {
|
||||
hasPermissionDenied = true
|
||||
denyList.add(permissions[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有權限被拒絕時
|
||||
if (hasPermissionDenied) {
|
||||
if (showSystemSetting) {
|
||||
showSystemPermissionSettingDialog(context, denyList)
|
||||
} else {
|
||||
mPermissionResult?.onDeny(denyList)
|
||||
}
|
||||
} else {
|
||||
// 全部的權限都已被允許
|
||||
mPermissionResult?.onGrant()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 顯示系統設定對話框
|
||||
* @param context
|
||||
* @param denies 被拒絕的權限
|
||||
*/
|
||||
private fun showSystemPermissionSettingDialog(context: Activity, denies: ArrayList<String>?) {
|
||||
val mPackageName = context.packageName
|
||||
if (mPermissionDialog == null) {
|
||||
mPermissionDialog = AlertDialog.Builder(context)
|
||||
.setMessage("已禁用權限,請手動授與")
|
||||
.setPositiveButton("前往設定") { _, _ ->
|
||||
cancelPermissionDialog()
|
||||
|
||||
val packageUri = Uri.parse("package:$mPackageName")
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageUri)
|
||||
context.startActivity(intent)
|
||||
context.finish()
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ ->
|
||||
// 關閉對話框
|
||||
cancelPermissionDialog()
|
||||
|
||||
mPermissionResult?.onDeny(denies)
|
||||
}
|
||||
.create()
|
||||
}
|
||||
mPermissionDialog?.show()
|
||||
}
|
||||
|
||||
/**
|
||||
* 關閉對話框
|
||||
*/
|
||||
private fun cancelPermissionDialog() {
|
||||
if (mPermissionDialog != null) {
|
||||
mPermissionDialog?.cancel()
|
||||
mPermissionDialog = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 動態申請權限的狀態回呼
|
||||
*/
|
||||
interface PermissionResultCallback {
|
||||
/**
|
||||
* 已授與
|
||||
*/
|
||||
fun onGrant()
|
||||
|
||||
/**
|
||||
* 已拒絕
|
||||
* @param denies 被拒絕的權限
|
||||
*/
|
||||
fun onDeny(denies: ArrayList<String>?)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.ray650128.iosclockwidget
|
||||
|
||||
import android.content.Context
|
||||
import java.lang.reflect.Type
|
||||
|
||||
|
||||
/**
|
||||
* Shared Preferences 工具類別
|
||||
* @author Raymond Yang
|
||||
*/
|
||||
object PreferenceUtil {
|
||||
private const val MAIN_KEY = "iOS_Clock_Widget"
|
||||
private const val IS_GRANTED = "IS_GRANTED"
|
||||
|
||||
private val sharedPreferences = MyApplication.getAppContext().getSharedPreferences(MAIN_KEY, Context.MODE_PRIVATE)
|
||||
|
||||
var isGranted: Boolean
|
||||
get() = sharedPreferences.getBoolean(IS_GRANTED, false)
|
||||
set(value) = sharedPreferences.edit().putBoolean(IS_GRANTED, value).apply()
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user