KotlinでのActivityの遷移とそれに伴ってデータを別Activityに送る、またそのActivityから何かのデータを受け取る方法について調べてみました。
2021.1.1
Activity 画面を遷移しデータを受け渡すアプリ
画面遷移だけのKotlinのケースは、
にて説明しましたが、
- 遷移したタイミングでデータを渡したい
- 遷移先から戻るタイミングでデータを受け取りたい
という場合にはIntentを使ってActivity間でデータを渡すことができます。
以前は、startActivityForResult(Intent, int)とonActivityResult(int, int, Intent)
これらを使っていましたが
AndroidX Activity と Fragment で導入された Activity Result API を使用すること推奨されています応(Activity クラスでは使用できますが…)アクティビティの結果を取得する
1. MainActivity :putExtra & onActivityResult
2. SubActivity :データを受け取る
3. SubActivity :[back] ボタンのタップで元に戻り、データを返す
4. MainActivity :元の画面でデータを受け取る
5. サンプルコード
MainActivity: putExtra & registerForActivityResult()
MainActivity から SubActivity への遷移は
1 2 |
val intent = Intent(applicationContext, SubActivity::class.java) startActivity(intent) |
別の Activity を開始する ではpublicなKeyを設定しています。これはputExtraによると
String: The name of the extra data, with package prefix.
とありますので、例えばpackage名をprefix(com.example.testactivitytransdata)としてEXTRA_MESSAGEというのを設定します。
1 2 3 |
companion object { const val EXTRA_MESSAGE = "com.example.testactivitytransdata.MESSAGE" } |
このEXTRA_MESSAGEを使って putExtra(name, value) に渡すデータの key(name) と value を入れます
入れるデータの型指定はありません
1 2 3 |
val intent = Intent(applicationContext, SubActivity::class.java) intent.putExtra(EXTRA_MESSAGE, data); startActivity(intent) |
data を渡すだけならこれでいいのですが、SubActivity からの返しを受け取りたいので
1 2 3 4 |
val intent = Intent(applicationContext, SubActivity::class.java) intent.putExtra(EXTRA_MESSAGE, data); getResult.launch(intent) |
registerForActivityResult()で受け取り、返ってくる結果が正常か、またリクエストコードの判定をします。it がActivityResult になります。
1 2 3 4 5 6 7 8 |
val getResult = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { if (it.resultCode == Activity.RESULT_OK) { val res = it.data?.getStringExtra(EXTRA_MESSAGE) ... } } |
SubActivity: データを受け取る
渡されたデータを受け取るときには、型に合わせてgetString()などを使います
1 |
val message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE) |
name とデータの型を指定します。
データが int の場合は、初期値を入れますがString型ではいりません。
その他、
getBooleanExtra(String name, boolean defaultValue)
…etc.
Intent reference
SubActivity: [back] ボタンタップで元に戻り、データを返す
SubActivity から戻るときにデータを返すには同様に
putExtra(name, value)
を使います
1 2 3 |
val intent = Intent() intent.putExtra(MainActivity.EXTRA_MESSAGE, message) setResult(Activity.RESULT_OK, intent) |
MainActivity: 元の画面でデータを受け取る
SubActivity からのデータを受け取るにはregisterForActivityResult()から、RESULT_OKであるか判定してデータを受け取ります。
1 2 3 4 5 6 7 8 |
val getResult = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { if (it.resultCode == Activity.RESULT_OK) { val res = it.data?.getStringExtra(EXTRA_MESSAGE) ... } } |
サンプルコード
色々追加して、以下のような機能でまとめてみます。
MainActivityで文字入力
SubActivityで受け取って表示
SubActivityから、受け取った文字列に追加して戻す
MainActivityではSubActivityから戻された文字列を表示
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
//package com.example.testactivitytransdata import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.app.Activity import android.content.Intent import androidx.activity.result.contract.ActivityResultContracts import com.example.testactivitytransdata.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { companion object { const val EXTRA_MESSAGE = "com.example.testactivitytransdata.MESSAGE" } private lateinit var binding: ActivityMainBinding private val getResult = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { if (it.resultCode == Activity.RESULT_OK) { val res = it.data?.getStringExtra(EXTRA_MESSAGE) binding.textView.text = res } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) binding.button.setOnClickListener { if (binding.editText.text != null) { val intent = Intent(applicationContext, SubActivity::class.java) val str = binding.editText.text.toString() intent.putExtra(EXTRA_MESSAGE, str) getResult.launch(intent) binding.editText.setText("") } } } } |
遷移先のActivity
SubActivity.ktを作成し
コードを記述します。
SubActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
//package com.example.testactivitytransdata import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.app.Activity import android.content.Intent import com.example.testactivitytransdata.databinding.ActivitySubBinding class SubActivity : AppCompatActivity() { private lateinit var binding: ActivitySubBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivitySubBinding.inflate(layoutInflater) setContentView(binding.root) // to get message from MainActivity val message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE) binding.textView.text = message binding.button.setOnClickListener { val intentSub = Intent() if (binding.editText.text != null) { val str = message + binding.editText.text.toString() intentSub.putExtra(MainActivity.EXTRA_MESSAGE, str) binding.editText.setText("") } setResult(Activity.RESULT_OK, intentSub) finish() } } } |
MainActivityのレイアウトです。作りやすさでLinearLayoutを選んでますがデフォルトの constraintlayout ではないので注意してください。
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#dfe" android:orientation="vertical" tools:context=".MainActivity"> <TextView android:text="@string/main" android:textSize="24sp" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_marginTop="40dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" android:text="@string/to_sub" android:textSize="24sp" /> <EditText android:id="@+id/editText" android:inputType="text" android:layout_width="220dp" android:layout_height="wrap_content" android:layout_margin="20dp" android:background="#fff" android:hint="@string/hint1" android:autofillHints="@string/hint1" android:textSize="24sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" android:text="@string/from_sub" android:textSize="24sp" /> <TextView android:id="@+id/textView" android:layout_width="220dp" android:layout_height="wrap_content" android:layout_margin="20dp" android:textSize="24sp" /> </LinearLayout> <Button android:id="@+id/button" android:text="@string/move" android:textSize="24sp" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_margin="20dp" /> </LinearLayout> |
SubActivityのレイアウト用のxmlファイルを作成
activity_sub.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#fde" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:text="@string/sub" android:textSize="24sp" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_marginTop="40dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" android:text="@string/from_main" android:textSize="24sp" /> <TextView android:id="@+id/textView" android:textSize="24sp" android:layout_width="220dp" android:layout_height="wrap_content" android:layout_margin="20dp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" android:text="@string/to_main" android:textSize="24sp" /> <EditText android:id="@+id/editText" android:inputType="text" android:layout_width="220dp" android:layout_height="wrap_content" android:layout_margin="20dp" android:background="#fff" android:hint="@string/hint2" android:autofillHints="@string/hint1" android:textSize="24sp" /> </LinearLayout> <Button android:id="@+id/button" android:text="@string/back" android:textSize="24sp" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="20dp" /> </LinearLayout> |
リソースです
strings.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<resources> <string name="button">YourAppName</string> <string name="main">Main Activity</string> <string name="sub">Sub Activity</string> <string name="hint1">Message to Sub</string> <string name="hint2">Message to Main</string> <string name="to_main">" to Main"</string> <string name="from_main">"from Main"</string> <string name="to_sub">" to Sub"</string> <string name="from_sub">"from Sub"</string> <string name="move">move</string> <string name="back">back</string> </resources> |
Manifest に SubActivity の記述も忘れずに、package名は適宜合わせてください。
AndroidManifest.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" ... <application ... <activity android:name=".MainActivity"> ... </activity> <activity android:name=".SubActivity" > </activity> </application> </manifest> |
View Binding の設定
build.gradle
1 2 3 4 5 6 7 8 |
... android { ... buildFeatures { viewBinding true } } ... |
References:
アクティビティの結果を取得する | Android デベロッパー | Android
Activity | Android Developers
別の Activity を開始する | Android Developers
Intent | Android Developers