안드로이드에서 startActivityForResult를 관리하는 방법?


969

내 활동에서에 의해 주 활동에서 두 번째 활동을 호출하고 startActivityForResult있습니다. 두 번째 액티비티에는이 액티비티를 완료하는 메소드가 있지만 (결과가 없을 수도 있지만) 그 중 하나만 결과를 반환합니다.

예를 들어, 주요 활동에서 두 번째 활동을 호출합니다. 이 액티비티에서는 카메라가있는 것과 같은 핸드셋의 일부 기능을 확인하고 있습니다. 그것이 없다면이 활동을 닫을 것입니다. 또한 준비하는 동안 MediaRecorder또는 MediaPlayer문제가 발생하면이 활동을 닫습니다.

장치에 카메라가 있고 녹화가 완전히 완료된 경우 사용자가 완료 버튼을 클릭하면 비디오를 녹화 한 후 결과 (기록 된 비디오의 주소)를 기본 활동으로 다시 보냅니다.

주요 활동의 결과를 어떻게 확인합니까?


답변:


2446

당신의 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

이 링크 '를 통해 이동하시기 바랍니다 코 틀린에 더 나은 방법이 개 활동 사이에 데이터를 전달 구현하기 위해 활동 사이에 데이터를 전달하는 더 좋은 방법 '


1
setResult (RESULT_CANCELED, returnIntent)에서 RESUT_CANCELLED를 할 때 의도를 두는 목적은 무엇입니까?
Ismail Sahin

4
에서 가정 @ismail SecondActivity일부 예외 경우에도 당신은에 결과를 반환 할 필요가 발생 FirstActivity하면 같은 결과를 설정할 수 있도록 "RESULT_CANCELLED"catch 블록 및 반환에 FirstActivty와에 FirstActivity's' 'onActivityResult()당신은 당신이 성공 또는 실패 결과를 가지고 있는지 확인할 수 있습니다.
Nishant

10
따라서 취소 이유를 알 필요가 없으면 setResult (RESULT_CANCELED); 의도 없음
Ismail Sahin

2
@Lei Leyba startActivityForResult ()를 호출 한 후 finish ()가 호출되지 않습니다. 첫 번째 활동은 일시 정지 상태로 이동합니다.
Nishant

6
나를 위해이 작동하지 않습니다 -.-이 내가 soooo를 훨씬 안드로이드에 대한 증오 것입니다 -이 시스템은 매우 신뢰할 : - /
마틴 페퍼

50

주요 활동의 결과를 확인하는 방법은 무엇입니까?

Activity.onActivityResult()매개 변수 를 대체 한 후 점검 해야합니다 .

  • requestCode이 결과를 반환 한 앱을 식별합니다. 전화 할 때 사용자가 정의합니다 startActivityForResult().
  • resultCode 이 앱의 성공 또는 실패 여부를 알려줍니다.
  • data이 앱에서 반환 한 모든 정보를 보유합니다. 이 될 수 있습니다 null.

requestCode는 첫 번째 활동에서만 사용되며 두 번째 활동에는 사용되지 않습니까? 두 번째 액티비티에 다른 접근 방식이있는 경우 요청 코드가 아닌 인 텐트 엑스트라를 기반으로 변경됩니다. 편집 : 예, stackoverflow.com/questions/5104269/…
JCarlosR

44

@Nishant의 답변을 보완하면 활동 결과를 반환하는 가장 좋은 방법은 다음과 같습니다.

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

나는 문제가 있었다

new Intent();

그런 다음 올바른 방법으로 사용하고 있음을 알았습니다.

getIntent();

현재 의도를 얻기 위해


a IntentBundle가지고 있고 액션이나 구성 요소와 같은 정상적인 값을 갖지 않는 새로운 것을 만드는 것은 조금 이상합니다 . 그러나 Intent현재 활동을 시작하는 데 사용 된 것을 수정하는 것은 약간 이상하다고 생각합니다 (그리고 잠재적으로 위험합니까?) . 그래서 Android 자체의 소스를 검색하여 항상 Intent결과로 사용할 새로운 것을 만듭니다 . 예를 들어, github.com/aosp-mirror/platform_frameworks_base/blob/…
spaaarky21

안녕하세요 spaaarky21, 의견 주셔서 감사합니다. 해당 솔루션을 어떻게 완성했는지 정확하게 설명하지 못해서 죄송합니다. 3 년 전이었고 "새로운 의도"로 인해 내 앱이 중단되었다는 것을 기억할 수 있습니다. 이것이 "문제가 발생했습니다"라고 말했을 때의 의미입니다. 실제로 나는 "getIntent"로 시도했는데, 당시에는 의미가 있었기 때문에 효과가있었습니다! 이 때문에 솔루션을 공유하기로 결정했습니다. 어쩌면 "가장 좋은 방법"또는 "올바른 방법"이라고하는 단어 중에서 가장 좋은 선택은 아니지만, 나는 내 해결책을 기다립니다. 그것은 내 문제와 다른 사람들의 부모도 해결 한 것입니다. 감사합니다
Julian Alberto

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();
    }
}

두 개의 다른 앱 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()매개 변수를 먼저 사용 하고 Activity두 번째 Activity에서 첫 번째 로 데이터를 보내려면 method를 Activity사용하여 값을 전달 Intent하고 setResult()method 내부의 데이터 onActivityResult()를 먼저 가져옵니다 Activity.


1

안드로이드에서 매우 일반적인 문제
그것은 3 조각으로 나눌 수 있습니다
1) 활동 B 시작 (활동 A에서 발생)
2) 요청 된 데이터 설정 (활동 B에서 발생)
3) 요청 된 데이터 수신 (활동 A에서 발생)

1) startActivity B

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

2) 요청 데이터 설정

이 부분에서는 특정 이벤트가 발생할 때 데이터를 다시 보낼지 여부를 결정합니다.
예 : 활동 B에는 EditText와 두 개의 버튼 b1, b2가 있습니다.
버튼 b1을 클릭하면 데이터가 다시 활동으로 전송
됩니다. 버튼 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()당신의 방법을 무시하지 않고 흐름 Activity또는 Fragment를 통해 증가 된 형태의 안전성을 제공 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. 비디오 가져 오기
  2. 연락처
  3. GetContent
  4. GetContents
  5. OpenDocument
  6. OpenDocuments
  7. OpenDocumentTree
  8. 문서 작성
  9. 다이얼
  10. 사진을 촬영
  11. RequestPermission
  12. 요청 권한

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() }
       }

무슨 일이야? 조금 세분화합시다. takePicturenullable 비트 맵을 반환하는 콜백입니다. null인지 여부는 onActivityResult프로세스의 성공 여부에 따라 다릅니다 . prepareCall다음의 새로운 기능에이 호출 등록 ComponentActivity(가)라고 ActivityResultRegistry우리가 나중에 다시 올 것이다을 -. ActivityResultContracts.TakePicture()은 Google이 우리를 위해 만든 기본 제공 도우미 중 하나이며 마지막으로 호출 takePicture하면 이전과 같은 방식으로 실제로 의도를 트리거합니다 Activity.startActivityForResult(intent, REQUEST_CODE).

맞춤 계약을 작성하는 방법은 무엇입니까?

Int를 입력으로 사용하고 요청 된 Activity가 결과 인 텐트에 반환 한 문자열을 반환하는 간단한 계약입니다.

    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.