AndroidでstartActivityForResultを管理する方法


969

私の活動では、メインの活動から2番目の活動をと呼んでいstartActivityForResultます。2番目のアクティビティーでは、このアクティビティーを終了するいくつかのメソッド(おそらく結果なし)がありますが、そのうちの1つだけが結果を返します。

たとえば、メインアクティビティから2番目のアクティビティを呼び出します。このアクティビティでは、カメラがあるかどうかなど、携帯電話のいくつかの機能を確認しています。ない場合は、このアクティビティを閉じます。また、準備中MediaRecorderまたはMediaPlayer問題が発生した場合は、このアクティビティを閉じます。

そのデバイスにカメラがあり、録画が完全に完了している場合、ビデオを録画した後、ユーザーが[完了]ボタンをクリックすると、結果(録画したビデオのアドレス)がメインアクティビティに返されます。

メインアクティビティの結果を確認するにはどうすればよいですか?


回答:


2447

あなたのFirstActivity呼び出しからSecondActivityusing startActivityForResult()メソッド

例えば:

int LAUNCH_SECOND_ACTIVITY = 1
Intent i = new Intent(this, SecondActivity.class);
startActivityForResult(i, LAUNCH_SECOND_ACTIVITY);

あなたの SecondActivity、あなたがに戻りたいのセットのデータFirstActivity。元に戻したくない場合は、何も設定しないでください。

例:SecondActivityデータを送り返す場合:

Intent returnIntent = new Intent();
returnIntent.putExtra("result",result);
setResult(Activity.RESULT_OK,returnIntent);
finish();

データを返したくない場合:

Intent returnIntent = new Intent();
setResult(Activity.RESULT_CANCELED, returnIntent);
finish();

次に、FirstActivityクラスにonActivityResult()メソッドの次のコードを記述します。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == LAUNCH_SECOND_ACTIVITY) {
        if(resultCode == Activity.RESULT_OK){
            String result=data.getStringExtra("result");
        }
        if (resultCode == Activity.RESULT_CANCELED) {
            //Write your code if there's no result
        }
    }
}//onActivityResult

このリンク「を介して行ってくださいKotlinにはるかに優れた方法で、2つのアクティビティ間でデータを受け渡す実装するには、活動の間でデータを渡すためのより良い方法


1
setResult(RESULT_CANCELED、returnIntent);にRESUT_CANCELLEDがあるときにインテントを配置する目的は何ですか。
Ismail Sahin 2013年

4
仮定@ismail SecondActivityいくつかの例外が発生し、その場合にも、あなたが結果を返す必要があるFirstActivityとして、あなたは結果を設定することができるように、"RESULT_CANCELLED"とcatchブロックと引き換えにFirstActivtyしてでFirstActivity's' 'onActivityResult()あなたが成功または失敗の結果を得たかどうかを確認することができます。
Nishant 2013年

10
したがって、それはあなた次第です。キャンセルの理由を知る必要がない場合は、単にsetResult(RESULT_CANCELED);を使用できます。意図なし
Ismail Sahin

2
@Lei Leyba startActivityForResult()を呼び出した後、finish()は呼び出されません。最初のActvityは一時停止状態に移行します。
Nishant 2014年

6
私にとってそれは機能していません-.-これは私がAndroidについてすごく嫌いなことです-このシステムはとても信頼できません:-/
Martin Pfeffer

50

メインアクティビティの結果を確認するにはどうすればよいですか?

オーバーライドしてActivity.onActivityResult()、そのパラメーターを確認する必要があります。

  • requestCodeこれらの結果を返したアプリを識別します。これは、を呼び出すときにユーザーが定義しますstartActivityForResult()
  • resultCode このアプリが成功したか、失敗したか、または別の何かであるかを通知します
  • dataこのアプリによって返される情報を保持します。これはそうかもしれませんnull

これは、requestCodeが最初のアクティビティでのみ使用され、2番目のアクティビティでは決して使用されないことを意味しますか?2番目のアクティビティのアプローチが異なる場合、2番目のアクティビティは変更されますが、requestCodeではなく、インテントエクストラに基づいています。編集:はい、stackoverflow.com
questions / 5104269 /…

44

@Nishantからの回答を補完する、アクティビティの結果を返す最善の方法は次のとおりです。

Intent returnIntent = getIntent();
returnIntent.putExtra("result",result);
setResult(RESULT_OK,returnIntent);
finish();

私は問題を抱えていました

new Intent();

次に、正しい方法が使用されていることがわかりました

getIntent();

現在の意図を取得する


Intentを保持するためだけに存在しBundle、アクションやコンポーネントのような通常の値を持たない新しいものを作成するのは少し奇妙に感じられます。しかしIntent、現在のアクティビティを起動するために使用されたを変更することも少し奇妙に感じられます(そして潜在的に危険ですか?)。そこで、Android自体のソースを検索したところIntent、結果として使用するために常に新しいものが作成されていることがわかりました。たとえば、github.com / aosp
mirror

spaaarky21様、コメントありがとうございます。最終的にどのようにしてその解決策に至ったのかを正確に説明できなかったことを残念に思います。それは3年前のことであり、「新しいインテント」が原因でアプリがクラッシュしたことを覚えているだけです。それが、「問題が発生した」と言ったときの意味です。実際、私は「getIntent」を試してみましたが、それは当時は意味があり、うまくいきました。そのため、自分の解決策を共有することにしました。「最善の方法」または「正しい方法」を言うのに最適な言葉ではないかもしれませんが、私は自分の解決策を支持しています。それは私の問題を解決したものであり、明らかに他の人々の問題でもありました。おかげで
ジュリアンアルベルト

1
うわー!よく働く。getIntent()アクティビティが呼び出された場所から、不明なアクティビティにデータを返すのに最適な方法のようです。ありがとう!
sam

43

全体のプロセスを確認するために、ここに補足的な答えがあります。詳細については、私の完全な回答を参照しください。

ここに画像の説明を入力してください

MainActivity.java

public class MainActivity extends AppCompatActivity {

    // Add a different request code for every activity you are starting from here
    private static final int SECOND_ACTIVITY_REQUEST_CODE = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    // "Go to Second Activity" button click
    public void onButtonClick(View view) {

        // Start the SecondActivity
        Intent intent = new Intent(this, SecondActivity.class);
        startActivityForResult(intent, SECOND_ACTIVITY_REQUEST_CODE);
    }

    // This method is called when the second activity finishes
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // check that it is the SecondActivity with an OK result
        if (requestCode == SECOND_ACTIVITY_REQUEST_CODE) {
            if (resultCode == RESULT_OK) { // Activity.RESULT_OK

                // get String data from Intent
                String returnString = data.getStringExtra("keyName");

                // set text view with string
                TextView textView = (TextView) findViewById(R.id.textView);
                textView.setText(returnString);
            }
        }
    }
}

SecondActivity.java

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }

    // "Send text back" button click
    public void onButtonClick(View view) {

        // get the text from the EditText
        EditText editText = (EditText) findViewById(R.id.editText);
        String stringToPassBack = editText.getText().toString();

        // put the String to pass back into an Intent and close this activity
        Intent intent = new Intent();
        intent.putExtra("keyName", stringToPassBack);
        setResult(RESULT_OK, intent);
        finish();
    }
}

これは2つの異なるアプリAとアプリbで実行できますか?stackoverflow.com/questions/52975645/…–
Jerry Abraham、

12

お困りの方へ onActivityResultの間違ったrequestCodeに

あなたstartActivityForResult()からあなたが呼んでいるならFragmentは、フラグメントを所有するアクティビティによってrequestCodeが変更されます。

あなたの活動で正しいresultCodeを取得したい場合は、これを試してください:

変化する:

startActivityForResult(intent, 1); に:

getActivity().startActivityForResult(intent, 1);


10

ユーザーインターフェイスをアクティビティの結果で更新する場合は、使用できません。this.runOnUiThread(new Runnable() {} これを行うと、UIは新しい値で更新されません。代わりに、これを行うことができます:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (resultCode == RESULT_CANCELED) {
        return;
    }

    global_lat = data.getDoubleExtra("LATITUDE", 0);
    global_lng = data.getDoubleExtra("LONGITUDE", 0);
    new_latlng = true;
}

@Override
protected void onResume() {
    super.onResume();

    if(new_latlng)
    {
        PhysicalTagProperties.this.setLocation(global_lat, global_lng);
        new_latlng=false;
    }
}

これはばかげているように見えますが、かなりうまくいきます。


2

最初にstartActivityForResult()withパラメータを最初に使用しActivity、2番目Activityから最初にデータを送信するActivity場合は、Intentwith setResult()メソッドを使用して値を渡しonActivityResult()、最初にmethod 内でそのデータを取得しますActivity


1

Androidでの非常に一般的な問題
3つの部分に分解できます
1)アクティビティBを開始(アクティビティAで発生)
2)要求されたデータを設定(アクティビティBで発生)
3)要求されたデータを受信(アクティビティAで発生)

1)startActivity B

Intent i = new Intent(A.this, B.class);
startActivity(i);

2)要求されたデータを設定する

この部分では、特定のイベントが発生したときにデータを送り返すかどうかを決定します。
例:アクティビティBにはEditTextと2つのボタンb1、b2があります。
ボタンb1をクリックすると、データがアクティビティAに送信されます。
送信されます。ボタンb2をクリックしても、データは送信されません。

データを送信する

b1......clickListener
{
   Intent resultIntent = new Intent();
   resultIntent.putExtra("Your_key","Your_value");
   setResult(RES_CODE_A,resultIntent);
   finish();
}

データを送信しない

b2......clickListener
    {
       setResult(RES_CODE_B,new Intent());
       finish();
    }

ユーザーが戻るボタンをクリックする
デフォルトでは、結果はActivity.RESULT_CANCEL応答コードで設定されます。

3)結果を取得する

そのオーバーライドのonActivityResultメソッド

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (resultCode == RES_CODE_A) {

     // b1 was clicked 
   String x = data.getStringExtra("RES_CODE_A");

}
else if(resultCode == RES_CODE_B){

   // b2 was clicked

}
else{
   // back button clicked 
}
}

1

ActivityResultRegistryは推奨されるアプローチです

ComponentActivity今提供しActivityResultRegistry、あなたが処理することができますそのstartActivityForResult()+をonActivityResult()だけでなく、requestPermissions()+はonRequestPermissionsResult()あなたのメソッドをオーバーライドすることなく、流れActivityFragment、経由増加型の安全性をもたらしますActivityResultContract、そしてこれらのフローをテストするためのフックを提供します。

AndroidX Activity 1.2.0-alpha02とFragment 1.3.0-alpha02で導入されたActivity Result APIを使用することを強くお勧めします。

これをあなたに追加 build.gradle

def activity_version = "1.2.0-alpha03"

// Java language implementation
implementation "androidx.activity:activity:$activity_version"
// Kotlin
implementation "androidx.activity:activity-ktx:$activity_version"

ビルド済みの契約をどのように使用しますか?

この新しいAPIには、次の事前構築された機能があります。

  1. TakeVideo
  2. PickContact
  3. GetContent
  4. GetContents
  5. OpenDocument
  6. OpenDocuments
  7. OpenDocumentTree
  8. CreateDocument
  9. ダイヤル
  10. 写真を撮る
  11. RequestPermission
  12. RequestPermissions

takePictureコントラクトを使用する例:

private val takePicture = prepareCall(ActivityResultContracts.TakePicture()) 
     { bitmap: Bitmap? ->
        // Do something with the Bitmap, if present
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button.setOnClickListener { takePicture() }
       }

ここで何が起こっているのでしょうか?少し分解してみましょう。takePicturenull可能なビットマップを返す単なるコールバックです。nullかどうかは、onActivityResultプロセスが成功したかどうかによって異なります。prepareCallその後、上の新しい機能に、このコール登録ComponentActivityと呼ばれるActivityResultRegistry私たちは、この後に戻ってくるだろうが- 。ActivityResultContracts.TakePicture()は、Googleが私たちのために作成した組み込みヘルパーの1つであり、最終的に呼び出すtakePictureと、以前と同じ方法で実際にインテントがトリガーされますActivity.startActivityForResult(intent, REQUEST_CODE)

カスタム契約を書く方法は?

Intを入力として受け取り、アクティビティを要求したStringを結果のインテントで返す単純なコントラクト。

    class MyContract : ActivityResultContract<Int, String>() {

    companion object {
        const val ACTION = "com.myapp.action.MY_ACTION"
        const val INPUT_INT = "input_int"
        const val OUTPUT_STRING = "output_string"
    }

    override fun createIntent(input: Int): Intent {
        return Intent(ACTION)
            .apply { putExtra(INPUT_INT, input) }
    }

    override fun parseResult(resultCode: Int, intent: Intent?): String? {
        return when (resultCode) {
            Activity.RESULT_OK -> intent?.getStringExtra(OUTPUT_STRING)
            else -> null
        }
    }
}



    class MyActivity : AppCompatActivity() {

    private val myActionCall = prepareCall(MyContract()) { result ->
        Log.i("MyActivity", "Obtained result: $result")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        button.setOnClickListener {
            myActionCall(500)
        }
    }
}

詳細については、この公式ドキュメントを確認してください。


0
You need to override Activity.onActivityResult()

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (resultCode == RESULT_CODE_ONE) {


   String a = data.getStringExtra("RESULT_CODE_ONE");

}
else if(resultCode == RESULT_CODE_TWO){

   // b was clicked

}
else{

}
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.