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