Android 的權限很煩人,而且會讓MainActivity.kt 變的複雜而難維護,所以精簡如下方式
AndroidManifest.xml
AndroidManifest.xml 指定要開通的權限,請設定如下藍色的部份
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-feature android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application>
............
</application>
</manifest>
todo
MainActivity.kt
指定要開通的權限後,還需在 Android 的 MainActivity 讓使用者選擇是否允許權限開通。
package net.ddns.mahaljsp.camera
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import net.ddns.mahaljsp.camera.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var permission:MainPermission
lateinit var ui: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ui= ActivityMainBinding.inflate(layoutInflater)
setContentView(ui.root)
permission=MainPermission(this)
}
fun init(){
}
//底下一定要寫在 Activity 視窗中
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array,
grantResults:IntArray)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
permission.onRequestPermissionsResult(this, requestCode)
}
}
上述的
permission=MainPermission()
會開始進行權限詢問,詢問結果回到 MainAcitvy 的 onRequestPermissionResult() 方法。請注意 onRequestPermissionResult() 一定要寫在 MainActivity 類別中。這方法則又調用 MainPermission 裏的 result,這是為了不要讓 MainActivity 太複雜。
MainPermission.kt
MainPermission.kt 的完整代碼如下 。
package net.ddns.mahaljsp.camera
import android.Manifest
import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import android.content.pm.PackageManager
import android.os.Build
import android.view.WindowInsets
import android.view.WindowInsetsController
import android.view.WindowManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
class MainPermission(context: Context) {
val REQUEST_CODE = 10
val REQUIRED_PERMISSIONS = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
)
fun allPermissionsGranted(context: Context) = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
}
init{
//視窗最大化
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
var controller: WindowInsetsController? = (context as MainActivity).window.insetsController
controller?.hide(WindowInsets.Type.statusBars())
} else {
@Suppress("DEPRECATION")
(context as MainActivity).window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
)
}
//取得權限
if(!allPermissionsGranted(context)){
ActivityCompat.requestPermissions(context as MainActivity,
REQUIRED_PERMISSIONS,
REQUEST_CODE
)
}
else{
(context as MainActivity).init()
}
}
fun onRequestPermissionsResult(context: Context,requestCode:Int, ){
if (requestCode== REQUEST_CODE) {
if(!allPermissionsGranted(context)){
val dialog= AlertDialog.Builder(context)
dialog
.setTitle("旅遊記")
.setMessage("因您拒絕授權手機相關權限\n本程式無法提供AI派工服務\n\n若您真有需求, 請移除本程式, 並重新安裝")
.setPositiveButton("離開", DialogInterface.OnClickListener{ _, _->
(context as MainActivity).finish()
})
.show()
}
else{
(context as MainActivity).init()
}
}
}
}
todo
為什麼要經過這二層
為什麼 AndroidManiFest.xml 要指定一次權限,而 MainActivity.kt 又要詢問一次? 非得經過這二層嗎?? 答案是一定要這樣,因為 AndroidManiFest.xml 是為了讓 Google Play 商店辨識用的,而代碼的部份是讓使用者選擇是否打開權限。
todo
todo
其它相關事項
todo
todo
todo
AndroidManifest.xml
todo
todo
todo
