PermissionsDispatcher × Kotlin

PermissionsDispatcher × Kotlin

CA.kt #2

Ce37cf75fa85b89a33916545978c64de?s=128

@hotchemi

July 18, 2017
Tweet

Transcript

  1. PermissionsDispatcher ✖ Kotlin

  2. • PermissionsDispatcher • Generate Runtime Permissions code • 100% reflection-free

    • Special permissions support • Xiaomi support • committer: @shiraji, @aurae
  3. • 3.0.0(beta) • fully Kotlin support • Why? • to

    support inline modifier • to make API Kotlin-ish • Now it’s official
  4. repositories { jcenter() maven { url ‘http://oss.jfrog.org/artifactory/oss-snapshot-local/' } } dependencies

    { compile(“com.github.hotchemi:permissionsdispatcher:3.0.0-SNAPSHOT”) { exclude module: "support-v13" } kapt "com.github.hotchemi:permissionsdispatcher-processor:3.0.0-SNAPSHOT" }
  5. @RuntimePermissions
 class MainActivity extends AppCompatActivity Java

  6. @NeedsPermission(Manifest.permission.CAMERA)
 void showCamera(); MainActivityPermissionsDispatcher.showCameraWithCheck(this); Java

  7. @RuntimePermissions(kotlin = true)
 class MainActivity : AppCompatActivity() Kotlin

  8. @NeedsPermission(Manifest.permission.CAMERA)
 inline fun showCamera() showCameraWithCheck() Kotlin

  9. private val REQUEST_SHOWCAMERA: Int = 0
 private val PERMISSION_SHOWCAMERA: Array<String>

    = arrayOf("android.permission.CAMERA")
 
 fun MainActivity.showCameraWithCheck() {
 if (PermissionUtils.hasSelfPermissions(this, PERMISSION_SHOWCAMERA)) {
 showCamera()
 } else {
 if (PermissionUtils.shouldShowRequestPermissionRationale(this, PERMISSION_SHOWCAMERA)) {
 showRationaleForCamera(ShowCameraPermissionRequest(this))
 } else {
 ActivityCompat.requestPermissions(this, PERMISSION_SHOWCAMERA, REQUEST_SHOWCAMERA)
 }
 }
 }
 
 fun MainActivity.onRequestPermissionsResult(requestCode: Int, grantResults: IntArray): Unit {
 when (requestCode) {
 REQUEST_SHOWCAMERA ->
 if (PermissionUtils.verifyPermissions(*grantResults)) {
 showCamera()
 } else {
 if (!PermissionUtils.shouldShowRequestPermissionRationale(this, PERMISSION_SHOWCAMERA)) {
 onCameraNeverAskAgain()
 } else {
 onCameraDenied()
 }
 }
 }
 }
 
 private class ShowCameraPermissionRequest(target: MainActivity) : PermissionRequest {
 private val weakTarget: WeakReference<MainActivity> = WeakReference(target)
 override fun proceed() {
 val target = weakTarget.get() ?: return
 ActivityCompat.requestPermissions(target, PERMISSION_SHOWCAMERA, REQUEST_SHOWCAMERA)
 }
 override fun cancel() {
 val target = weakTarget.get() ?: return
 target.onCameraDenied()
 }
 }
  10. • Under the hood • generate .kt file at compile

    time • KotlinPoet • kapt3 • Testing
  11. • KotlinPoet • Kotlin version of JavaPoet • DSL for

    generating source files • latest ver: 0.3.0 • early-access release • KDoc is not updated • writeTo(filer: Filer) is not supported
  12. class Greeter(val name: String) { fun greet() { println("Hello, $name")

    } } fun main(vararg args: String) { Greeter(args[0]).greet() }
  13. val greeterClass = ClassName("", "Greeter") val kotlinFile = KotlinFile.builder("", "HelloWorld")

    .addType(TypeSpec.classBuilder("Greeter") .primaryConstructor(FunSpec.constructorBuilder() .addParameter("name", String::class) .build()) .addProperty(PropertySpec.builder("name", String::class) .initializer("name") .build()) .addFun(FunSpec.builder("greet") .addStatement("println(%S)", "Hello, \$name") .build()) .build()) .addFun(FunSpec.builder("main") .addParameter("args", String::class, VARARG) .addStatement("%T(args[0]).greet()", greeterClass) .build()) .build() kotlinFile.writeTo(System.out)
  14. if (isKotlin) { val kaptGeneratedDirPath = processingEnv.options[KAPT_KOTLIN_GENERATED_OPTION_NAME]?.replace("kaptKotlin", "kap processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, "Can't

    find the target directory for generated Kot return false } val kaptGeneratedDir = File(kaptGeneratedDirPath) if (!kaptGeneratedDir.parentFile.exists()) { kaptGeneratedDir.parentFile.mkdirs() } val processorUnits = listOf(ActivityKtProcessorUnit(), SupportFragmentKtProcessorUnit(), NativeFragmentKtProces val processorUnit = findAndValidateKtProcessorUnit(processorUnits, it) val kotlinFile = processorUnit.createKotlinFile(rpe, requestCodeProvider) kotlinFile.writeTo(kaptGeneratedDir) } else { val processorUnits = listOf(ActivityProcessorUnit(), SupportFragmentProcessorUnit(), NativeFragmentProcessorUni val processorUnit = findAndValidateProcessorUnit(processorUnits, it) val javaFile = processorUnit.createJavaFile(rpe, requestCodeProvider) javaFile.writeTo(filer) }
  15. • kapt3 • supports .kt file generation • kt generated/source/kaptKotlin/$sourceSet

    • java generated/source/kapt/$sourceSet • apt generated/source/apt/$sourceSet • processingEnv.
 options[“kapt.kotlin.generated”]
  16. • kapt3 • But… • kaptKotlin dir was not recognized

    correctly with Android project… • worked well only on java project • filed a bug report • youtrack.jetbrains.com/issue/KT-19097
  17. • Testing • we can’t use google/compile-testing • write tests

    for behavior, not code itself • with PowerMockito, Robolectric • check test, test-v13 projects • read Testing Against Annotation Processing • by @shiraji san
  18. • What learned • Supporting Java/Kotlin is tough work than

    we expected • class delegation is a way to go? • Anyway it was fun:D
  19. • Misc • 3.0.0 would be officially released soon! •

    Hopefully end of July • Give us feedback!
  20. Thank you