正しい結果が得られます(パート1)。アクティビティ結果API

すべてのAndroid開発者は、あるアクティビティから別のアクティビティにデータを転送する必要に直面していました。この些細な作業で、あまりエレガントでないコードを書くことを余儀なくされることがよくあります。 





最後に、2020年に、Googleは古い問題の解決策であるActivity ResultAPIを導入しました。これは、アクティビティ間でデータを交換し、実行時のアクセス許可を要求するための強力なツールです。 





この記事では、新しいAPIの使用方法とその利点について説明します。





onActivityResult()の何が問題になっていますか?

“ ” — DRY Don’t repeat yourself, , . 





onActivityResult()



, . , , — SecondActivity



. SecondActivity



, .





class OldActivity : AppCompatActivity(R.layout.a_main) {

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

       vButtonCamera.setOnClickListener {
           when {
               checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED -> {
                   //    ,  
                   startActivityForResult(
                       Intent(MediaStore.ACTION_IMAGE_CAPTURE),
                       PHOTO_REQUEST_CODE
                   )
               }
               shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
                   //    ,      
               }
               else -> {
                   //    ,  
                   requestPermissions(
                       arrayOf(Manifest.permission.CAMERA),
                       PHOTO_PERMISSIONS_REQUEST_CODE
                   )
               }
           }
       }

       vButtonSecondActivity.setOnClickListener {
           val intent = Intent(this, SecondActivity::class.java)
               .putExtra("my_input_key", "What is the answer?")

           startActivityForResult(intent, SECOND_ACTIVITY_REQUEST_CODE)
       }
   }

   override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
       when (requestCode) {
           PHOTO_REQUEST_CODE -> {
               if (resultCode == RESULT_OK && data != null) {
                   val bitmap = data.extras?.get("data") as Bitmap
                   //  bitmap
               } else {
                   //    
               }
           }
           SECOND_ACTIVITY_REQUEST_CODE -> {
               if (resultCode == RESULT_OK && data != null) {
                   val result = data.getIntExtra("my_result_extra")
                   //  result
               } else {
                   //    
               }
           }
           else -> super.onActivityResult(requestCode, resultCode, data)
       }
   }

   override fun onRequestPermissionsResult(
       requestCode: Int,
       permissions: Array<out String>,
       grantResults: IntArray
   ) {
       if (requestCode == PHOTO_PERMISSIONS_REQUEST_CODE) {
           when {
               grantResults[0] == PackageManager.PERMISSION_GRANTED -> {
                   //    ,  
                   startActivityForResult(
                       Intent(MediaStore.ACTION_IMAGE_CAPTURE),
                       PHOTO_REQUEST_CODE
                   )
               }
               !shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
                   //    ,    Don't ask again.
               }
               else -> {
                   //    ,   
               }
           }
       } else {
           super.onRequestPermissionsResult(requestCode, permissions, grantResults)
       }
   }

   companion object {
       private const val PHOTO_REQUEST_CODE = 1
       private const val PHOTO_PERMISSIONS_REQUEST_CODE = 2
       private const val SECOND_ACTIVITY_REQUEST_CODE = 3
   }
}
      
      



, onActivityResult()



, Activity. , .





, , .





Activity Result API

API AndroidX Activity 1.2.0-alpha02



Fragment 1.3.0-alpha02



, build.gradle:





implementation 'androidx.activity:activity-ktx:1.3.0-alpha02'
implementation 'androidx.fragment:fragment-ktx:1.3.0'
      
      



Activity Result :





1.

— , ActivityResultContract<I,O>.



I



, Activity, O



— . 





“ ”: PickContact



, TakePicture



, RequestPermission



. .





:





  • createIntent()



    — , launch()





  • parseResult()



    — , resultCode





getSynchronousResult()



— . , Activity, , ,   . , null







, SecondActivity, :





class MySecondActivityContract : ActivityResultContract<String, Int?>() {

   override fun createIntent(context: Context, input: String?): Intent {
       return Intent(context, SecondActivity::class.java)
           .putExtra("my_input_key", input)
   }

   override fun parseResult(resultCode: Int, intent: Intent?): Int? = when {
       resultCode != Activity.RESULT_OK -> null
       else -> intent?.getIntExtra("my_result_key", 42)
   }

   override fun getSynchronousResult(context: Context, input: String?): SynchronousResult<Int?>? {
       return if (input.isNullOrEmpty()) SynchronousResult(42) else null
   }
}
      
      



2.

registerForActivityResult()



. ActivityResultContract



ActivityResultCallback



. .





val activityLauncher = registerForActivityResult(MySecondActivityContract()) { result ->
   //  result
}
      
      



Activity



, ActivityResultLauncher



, . 





3.

Activity launch()



ActivityResultLauncher



, .





vButton.setOnClickListener {
   activityLauncher.launch("What is the answer?")
}
      
      



!

, :





  • , CREATED . — .





  • registerForActivityResult()



    if



    when



    . , (, , ). , .





  • , Activity, ActivityNotFoundException: “No Activity found to handle Intent”. , launch()



    getSynchronousResult()



    resolveActivity()



    c   PackageManager



    .





runtime permissions

Activity Result API . checkSelfPermission()



, requestPermissions()



onRequestPermissionsResult()



, — RequestPermission



RequestMultiplePermissions







, — . RequestPermission



true



, , false



. RequestMultiplePermissions



Map



, — , — .





. Google :





runtime permissions:





  • , , ( 5a)





  • ( 8b), , , “Don't ask again”





shouldShowRequestPermissionRationale()



. true



, , . shouldShowRequestPermissionRationale()



false



— “Don't ask again”, . 





:





class PermissionsActivity : AppCompatActivity(R.layout.a_main) {

   val singlePermission = registerForActivityResult(RequestPermission()) { granted ->
       when {
           granted -> {
               //    ,  
           }
           !shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
               //    ,    Don't ask again.
           }
           else -> {
               //    ,   
           }
       }
   }

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

       vButtonPermission.setOnClickListener {
           if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
               //    ,      
           } else {
               singlePermission.launch(Manifest.permission.CAMERA)
           }
       }
   }
}


      
      



新しいAPIの知識を実践し、彼らの助けを借りて最初の例の画面を書き直してみましょう。その結果、かなりコンパクトで、読みやすく、スケーラブルなコードが得られます。





class NewActivity : AppCompatActivity(R.layout.a_main) {

   val permission = registerForActivityResult(RequestPermission()) { granted ->
       when {
           granted -> {
               camera.launch() //    ,  
           }
           !shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
               //    ,    Don't ask again.
           }
           else -> {
               //    
           }
       }
   }

   val camera = registerForActivityResult(TakePicturePreview()) { bitmap ->
       //  bitmap
   }

   val custom = registerForActivityResult(MySecondActivityContract()) { result ->
       //  result
   }

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

       vButtonCamera.setOnClickListener {
           if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
               //  ,     
           } else {
               permission.launch(Manifest.permission.CAMERA)
           }
       }

       vButtonSecondActivity.setOnClickListener {
           custom.launch("What is the answer?")
       }
   }
}


      
      



onActivityResult()を介した通信の欠点を確認し、Activity Result APIの利点について学び、実際の使用方法を学びました。  





新しいAPIは通常どおり完全に安定しており、非推奨onRequestPermissionsResult()



onActivityResult()



なりstartActivityForResult()



ました。プロジェクトに変更を加える時が来ました! 





ランタイム権限の操作を含む、Activty Result APIのさまざまな使用例を含むデモアプリケーションは、私のGithubリポジトリにあります








All Articles