HiltでPermissionチェック

PermissionのチェックをHiltでやってみようと思います。

### 条件

* Hilt導入済み

### Listenerを作成

```kotlin
interface PermissionListener {

    fun permissionGranted()
    fun permissionDenied()
}
```

### Lifecycleと紐付ける

Lifecycleと紐付けるため、継承出来るようにします。

```kotlin
abstract class AbstractPermissionObserver : DefaultLifecycleObserver {

    var isGranted: Boolean = false
    var permissionListener: PermissionListener? = null

    abstract fun launch()
    abstract fun checkPermission(): Boolean
}
```

### 位置情報のPermissionチェック

位置情報以外でも好きなPermissionをlaunch()とcheckPermission()でチェックしてください。

```kotlin
@ActivityScoped
class LocationPermissionObserver @Inject constructor(
    @ActivityContext private val context: Context
) : AbstractPermissionObserver() {

    private var requestPermission: ActivityResultLauncher<Array<String>>? = null

    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)

        if (context is AppCompatActivity) {
            requestPermission =
                context.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
                    permissions.entries.forEach {
                        isGranted = it.value
                        if (!it.value) {
                            return@forEach
                        }
                    }
                    if (isGranted) {
                        permissionListener?.permissionGranted()
                    } else {
                        permissionListener?.permissionDenied()
                    }
                }
        }
    }

    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)

        requestPermission = null
    }

    override fun launch() {
        requestPermission?.launch(
            arrayOf(
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION
            )
        )
    }

    override fun checkPermission(): Boolean {
        val fineLocationPermission = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
        val coarseLocationPermission = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)
        return fineLocationPermission == PackageManager.PERMISSION_GRANTED &&
                coarseLocationPermission == PackageManager.PERMISSION_GRANTED
    }
}
```

### Activityのlifecycleと紐付ける

```kotlin
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var locationPermissionObserver: LocationPermissionObserver

    private val viewModel by viewModels<MainViewModel>()
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        setSupportActionBar(binding.toolbar)

        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .replace(R.id.container, MainFragment.newInstance())
                .commitNow()
        }

        lifecycle.addObserver(locationPermissionObserver)
    }

    override fun onDestroy() {
        super.onDestroy()
        lifecycle.removeObserver(locationPermissionObserver)
    }
}
```

### FragmentでPermissionチェックを実施

onStart時に実施していますが、ボタンを押下した際でも、どこでも大丈夫です。

```kotlin
@AndroidEntryPoint
class MainFragment : Fragment() {

    @Inject
    lateinit var locationPermissionObserver: LocationPermissionObserver

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        locationPermissionObserver.permissionListener = object : PermissionListener {
            override fun permissionGranted() {
            }

            override fun permissionDenied() {
            }
        }
    }

    override fun onStart() {
        super.onStart()

        // Permissionチェック、許可されてない場合は許可を求めるダイアログを表示
        if (!locationPermissionObserver.checkPermission()) {
            locationPermissionObserver.launch()
        }
    }
```

---

xxxPermissionObserverを色んなPermissionチェックで作成するとどこでもPermissionチェック出来るようになりますので、是非活用してみてください。