Activityで他のActivityに処理を依頼して、その結果を処理するために、startActivityForResult()/onActivityResult()があります。現時点では、まだalphaですがActivity1.2.0、Fragment1.3.0から新しいAPIが追加されました。

ActivityResultRegistry: ComponentActivity で ActivityResultRegistry が利用できるようになり、アクティビティまたはフラグメントのメソッドをオーバーライドせずに startActivityForResult() + onActivityResult()、requestPermissions() + onRequestPermissionsResult() の各フローを処理できるようになりました。ActivityResultContract によりタイプ セーフティーが向上し、これらのフローをテストするためのフックを提供するようになりました。更新された アクティビティから結果を取得するをご覧ください。(b/125158199)

注: Activity 1.2.0-alpha02 へのアップグレードを行う場合、RequestPermission または RequestPermissions の Activity Result コントラクトを使用するには、Fragment 1.3.0-alpha02 へのアップグレードが必要です。

やってみる

日本語はまだないので英語でみるとドキュメントが新しいやり方に変わっています。

Getting a result from an activity

今回やったサンプルは以下の通りです。

  • Activityから暗黙/明示的intentで結果をもらうケース
  • Fragmentから暗黙/明示的intentで結果をもらうケース

サンプルはこちらです。

kamedon/AndroidIntentResult

また、今回はアルファ機能を使っていますので、リリース時には異なる可能性があります。

def activity_version = "1.2.0-alpha04"
implementation "androidx.activity:activity-ktx:$activity_version"

def fragment_version = "1.3.0-alpha04"
implementation "androidx.fragment:fragment-ktx:$fragment_version"
debugImplementation "androidx.fragment:fragment-testing:$fragment_version"

Activityから暗黙/明示的intentで結果をもらうケース

暗黙Intent

以下は、暗黙Intentでギャラリーアプリなどから、写真をもらうケースです。かなりシンプルになっています。registerForActivityResultで送受信を作っています。 呼ぶ側で、従来でいうところのContentTypeを指定して読んでるだけです。第2引数にOptionを設定できますが今回は割愛します。

class SelectPhotoActivity : AppCompatActivity(R.layout.activity_select_photo) {

    val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
        Log.d("result", "activity: $uri")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        selectBtn.setOnClickListener {
            getContent("image/*")
        }
    }

}

明示的Intent

以下は、ResultActivityからResultを取得するサンプルになります。

明示的のときはStartActivityForResultを使用することで、従来のようなActivityResultが返ってくるようになるので、あとは同じように処理できます。startForResultを呼ぶとき、どのActivityを呼ぶか指定します。

class CustomActivity : AppCompatActivity(R.layout.activity_custom) {
    val startForResult =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
            if (result.resultCode == Activity.RESULT_OK) {
                val intent = result.data
                Toast.makeText(
                    this,
                    "result: ${intent?.getStringExtra("result")}",
                    Toast.LENGTH_SHORT
                ).show()
            }
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        startBtn.setOnClickListener {
            startForResult(Intent(this, ResultActivity::class.java))
        }
    }
}

#android #スマートフォン

AndroidのstartActivityForResultに変わる新しいAPIが追加されました
13.15 GEEK