【Android × Kotlin】Activity Result API で他の Activity の結果を取得する
今回は、Activity Result API で他の Activity の結果を取得する方法を解説します。
なお、ここに掲載しているソースコードは以下の環境で動作確認しています。
- Android Studio Chipmunk | 2021.2.1 Patch 1
- JDK 11.0.12
- Android Gradle Plugin 7.2.1
- Kotlin 1.6.21
- Gradle 7.4.2
- androidx.activity 1.4.0
- androidx.fragment 1.4.1
概要
以前、他の Activity の結果を取得する方法として、startActivityForResult と onActivityResult を使う方法がありました。しかし、現在この方法は非推奨になっており、代わりに Activity Result API を使う方法が推奨されています。
今回は、文字列を結果として返す Activity から Activity Result API でその結果を取得するサンプルの作成を通して、Activity Result API の使い方を解説します。
なお、Activity Result API は、ComponentActivity と Fragment の両方で使用することができるため、Activity と Fragment のそれぞれで解説します。
Activity で Activity Result API を使う
ライブラリのインポート
Activity で Activity Result API を使う場合、アプリの build.gradle ファイルの dependencies
に activity-ktx
を追加してください。
dependencies {
implementation "androidx.activity:activity-ktx:1.4.0"
}
他の Activity の結果を取得する
ここから、文字列を結果として返す Activity と、Activity Result API でその結果を取得する Activity を作成します。
まず、文字列を結果として返す Activity から作成します。
class SubActivity : AppCompatActivity(R.layout.sub_activity) { companion object { const val EXTRA_RESULT = "result" fun createIntent(context: Context) = Intent(context, SubActivity::class.java) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) findViewById<Button>(R.id.inputButton) .setOnClickListener { setResult(RESULT_OK, Intent().apply { val editText: TextInputEditText = findViewById(R.id.textInputEditText) val text = editText.text.toString() putExtra(EXTRA_RESULT, text) }) finish() } } }
この Activity には EditText と Button があり、Button が押されると EditText に入力された文字列を Activity の結果として返すようにします。
Activity の結果として返す際には、setResult に RESULT_OK と 返す文字列を格納した Intent を渡します。setResult を使って Activity の結果を返す方法は、startActivityForResult と onActivityResult を使っていたときと同じです。
次に、Activity Result API で他の Activity の結果を取得する Activity を作成します。
class MainActivity : AppCompatActivity(R.layout.main_activity) { private val subActivityLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { result -> if (result.resultCode == RESULT_OK) { val text = result.data?.getStringExtra(SubActivity.EXTRA_RESULT) ?: "" findViewById<TextView>(R.id.resultTextView).text = text } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) findViewById<Button>(R.id.inputButton) .setOnClickListener { val intent = SubActivity.createIntent(this) subActivityLauncher.launch(intent) } } }
Activity Result API を使う場合、まず registerForActivityResult を使って、他のアクティビティを開始するために使用する ActivityResultLauncher を取得します。
この registerForActivityResult には、他のアクティビティから結果を取得することを表す ActivityResultContracts.StartActivityForResult() を渡します。そして、結果を取得した後に呼び出されるコールバックも渡します。
private val subActivityLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { result -> if (result.resultCode == RESULT_OK) { val text = result.data?.getStringExtra(SubActivity.EXTRA_RESULT) ?: "" findViewById<TextView>(R.id.resultTextView).text = text } }
そして、文字列を結果として返す Activity を開始する処理を作成します。Intent を生成し、さきほど取得した ActivityResultLauncher の launch に Intent を渡して、Activity を開始します。
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) findViewById<Button>(R.id.inputButton) .setOnClickListener { val intent = SubActivity.createIntent(this) subActivityLauncher.launch(intent) } }
以上で、文字列を結果として返す Activity からその文字列を取得できるようになります。
Fragment で Activity Result API を使う
ライブラリのインポート
Fragment で Activity Result API を使う場合、アプリの build.gradle ファイルの dependencies
に fragment-ktx
を追加してください。
dependencies {
implementation "androidx.fragment:fragment-ktx:1.4.1"
}
他の Activity の結果を取得する
ここから、Activity Result API で他の Activity の結果を取得する Fragment を作成します。
なお、文字列を結果として返す Activity については、Activity で Activity Result API を使う場合と同様なので、ここでは省略します。
以下が、実際のコードです。
class MainFragment : Fragment(R.layout.main_fragment) { private val subActivityLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { result -> if (result.resultCode == RESULT_OK) { view?.let { view -> val text = result.data?.getStringExtra(SubActivity.EXTRA_RESULT) ?: "" val textView = view.findViewById<TextView>(R.id.resultTextView) textView.text = text } } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) view.findViewById<Button>(R.id.inputButton) .setOnClickListener { val intent = SubActivity.createIntent(requireContext()) subActivityLauncher.launch(intent) } } }
Activity のときと同様に、registerForActivityResult を使って、他のアクティビティを開始するために使用する ActivityResultLauncher を取得します。
private val subActivityLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { result -> if (result.resultCode == RESULT_OK) { view?.let { view -> val text = result.data?.getStringExtra(SubActivity.EXTRA_RESULT) ?: "" val textView = view.findViewById<TextView>(R.id.resultTextView) textView.text = text } } }
そして、文字列を結果として返す Activity を開始する処理を作成します。こちらも、Activity のときと同様です。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) view.findViewById<Button>(R.id.inputButton) .setOnClickListener { val intent = SubActivity.createIntent(requireContext()) subActivityLauncher.launch(intent) } }
以上で、Fragment でも文字列を結果として返す Activity からその文字列を取得できるようになります。