Android
 Computer >> コンピューター >  >> プログラミング >> Android

Androidで前のアクティビティにデータを返す方法!startActivityForResultの使い方を徹底解説

はじめに

Androidアプリ開発では、あるアクティビティから別のアクティビティを起動し、その処理結果を元の画面に返したいケースがよくあります。例えば、設定画面で選択した値をメイン画面に反映させたい場合などが典型例です。

本記事では、startActivityForResult()setResult()onActivityResult()を組み合わせて、セカンド画面(SecondActivity)からメイン画面(MainActivity)へデータを返す方法を、実際のコード付きで6つのステップに分けて解説します。

データ送信の全体像

今回のサンプルでは、以下のような流れでデータを受け渡します。

  1. MainActivityがstartActivityForResult()でSecondActivityを起動する
  2. SecondActivityでユーザーが入力した文字列をIntentに格納し、setResult()で結果として設定する
  3. finish()でSecondActivityを終了すると、MainActivityのonActivityResult()が自動的に呼び出される
  4. 受け取ったIntentからデータを取り出し、TextViewに表示する

ステップ1:新規プロジェクトを作成する

Android Studioを起動し、メニューから「File」→「New Project」を選択します。必要な項目をすべて入力して、新しいプロジェクトを作成してください。

ステップ2:activity_main.xmlを実装する

res/layout/activity_main.xmlに以下のコードを記述します。画面中央にTextView、下部に「Get Data」ボタンを配置したシンプルなレイアウトです。

<?xml version = "1.0" encoding = "utf-8"?>
<RelativeLayout xmlns:android = "https://schemas.android.com/apk/res/android"
    xmlns:tools = "https://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    android:layout_margin = "16dp"
    android:orientation = "vertical"
    tools:context = ".MainActivity">
    <TextView
        android:id = "@+id/text_view"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:layout_centerInParent = "true"
        android:layout_gravity = "center" />
    <Button
        android:id = "@+id/button"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:layout_alignParentBottom = "true"
        android:layout_gravity = "center"
        android:layout_marginTop = "16dp"
        android:text = "Get Data" />
</RelativeLayout>

ステップ3:MainActivity.javaを実装する

src/MainActivity.javaに以下のコードを記述します。

package com.example.myapplication;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private final static int MY_REQUEST_CODE = 1;
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.text_view);
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivityForResult(intent, MY_REQUEST_CODE);
            }
        });
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            if (requestCode == MY_REQUEST_CODE) {
                if (data != null)
                    textView.setText(data.getStringExtra("value"));
            }
        }
    }
}

実装のポイントは次の3点です。

  • MY_REQUEST_CODE:リクエストを識別するための任意のコード(ここでは1)
  • startActivityForResult(intent, MY_REQUEST_CODE):通常のstartActivity()ではなく、結果を受け取る前提でアクティビティを起動する
  • onActivityResult():SecondActivityが終了したタイミングで呼ばれ、resultCodeとrequestCodeを確認した上で、結果のIntentから「value」というキーの文字列を取得してTextViewにセットする

ステップ4:activity_second.xmlを実装する

res/layout/activity_second.xmlに以下のコードを記述します。テキスト入力用のEditTextと、確定用の「Done」ボタンを配置しています。

<?xml version = "1.0" encoding = "utf-8"?>
<RelativeLayout xmlns:android = "https://schemas.android.com/apk/res/android"
    xmlns:tools = "https://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    android:layout_margin = "16dp"
    android:orientation = "vertical"
    tools:context = ".SecondActivity">
    <EditText
        android:id = "@+id/edit_text"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:layout_centerInParent = "true"
        android:layout_gravity = "center"
        android:hint = "Enter something to return previous activity"
        android:inputType = "text" />
    <Button
        android:id = "@+id/button"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:layout_alignParentBottom = "true"
        android:layout_gravity = "center"
        android:layout_marginTop = "16dp"
        android:text = "Done" />
</RelativeLayout>

ステップ5:SecondActivity.javaを実装する

src/SecondActivity.javaに以下のコードを記述します。

package com.example.myapplication;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class SecondActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        final EditText editText = findViewById(R.id.edit_text);
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String value = editText.getText().toString().trim();
                Intent intent = new Intent();
                intent.putExtra("value", value);
                setResult(RESULT_OK, intent);
                finish();
            }
        });
    }
}

「Done」ボタンがタップされると、EditTextに入力された文字列をtrim()で整形し、putExtra("value", value)でIntentに格納します。その後、setResult(RESULT_OK, intent)で呼び出し元へ結果を返し、finish()で自身の画面を閉じます。この一連の処理によって、MainActivity側のonActivityResult()が発火する仕組みです。

ステップ6:AndroidManifest.xmlを設定する

androidManifest.xmlに以下のコードを記述し、SecondActivityを宣言します。

<?xml version = "1.0" encoding = "utf-8"?>
<manifest xmlns:android = "https://schemas.android.com/apk/res/android"
    package = "com.example.myapplication">
    <application
        android:allowBackup = "true"
        android:icon = "@mipmap/ic_launcher"
        android:label = "@string/app_name"
        android:roundIcon = "@mipmap/ic_launcher_round"
        android:supportsRtl = "true"
        android:theme = "@style/AppTheme">
        <activity android:name = ".MainActivity">
            <intent-filter>
                <action android:name = "android.intent.action.MAIN" />
                <category android:name = "android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name = ".SecondActivity"></activity>
    </application>
</manifest>

アプリを実行してみよう

それではアプリを実行しましょう。実機のAndroidスマートフォンをPCに接続し、Android Studioでプロジェクト内のアクティビティファイルを開いた状態で、ツールバーにあるRun(再生)アイコンをクリックします。デバイスを選択してアプリを起動すると、まず初期画面が表示されます。

「Get Data」ボタンをタップするとSecondActivityが開きます。任意の文字列を入力して「Done」を押すと前の画面に戻り、入力した内容がTextViewに表示されていれば成功です。

補足:最新の開発環境での注意点

本記事のコードは旧サポートライブラリ(android.support)時代のものです。現在のAndroid StudioではAndroidXが標準となっているため、import文をandroidx.appcompat.app.AppCompatActivityなどに置き換えて使用してください。

また、startActivityForResult()およびonActivityResult()はAPIレベル30以降で非推奨(Deprecated)となっており、現在はActivity Result API(registerForActivityResult)の利用が推奨されています。新規プロジェクトでは、より型安全でライフサイクルに強いActivity Result APIの採用を検討するとよいでしょう。

  1. 【Android】1つのフラグメントから別のフラグメントへデータを送信する方法(インターフェース活用の実装例)

    はじめに このチュートリアルでは、Androidアプリで1つのフラグメント(Fragment)から別のフラグメントへデータを送信する方法を解説します。フラグメント同士は直接通信することができません。そこで本記事では、カスタムインターフェース「SendMessage」を定義し、ホストとなるMainActivityを仲介してデータを受け渡す、定番かつ推奨されるパターンを紹介します。 具体的には、タブで切り替えられる2つのフラグメントを用意し、1つ目のフラグメントで入力したテキストをボタン操作で2つ目のフラグメントに表示させるサンプルアプリを作成します。 ステップ1:新しいプロジェクトを作成する

  2. Androidのデータバインディング入門:Data Binding Libraryでレイアウトとデータを結びつける方法

    データバインディングとは、アプリが扱う「データ」と、画面上の視覚的なUI要素を結びつける(バインドする)ための手法です。この仕組みを使うと、UI側の値が更新されるたびに、裏側で保持しているデータも自動的に更新されます。 決して目新しい概念ではなく、AngularJS、React、Vueなど、多くのフロントエンドフレームワークがすでにこの仕組みを設計に取り入れています。 しかし本記事で注目するのはフロントエンドフレームワークではなく、モバイル開発です。GoogleはAndroid向けにData Binding Libraryを提供しており、これはAndroid Jetpackの一部として位置づけ