UFO ET IT

Android에서 startActivityForResult를 관리하는 방법

ufoet 2023. 6. 2. 21:46
반응형

Android에서 startActivityForResult를 관리하는 방법

제 활동에서, 저는 주요 활동의 두 번째 활동을 다음과 같이 부릅니다.startActivityForResult두 번째 활동에서 이 활동을 완료하는 몇 가지 방법(결과가 없을 수도 있음)이 있지만, 그 중 하나만 결과를 반환합니다.

예를 들어, 저는 주요 활동에서 두 번째 활동을 부릅니다.이 활동에서는 카메라가 장착되어 있는지와 같은 핸드셋의 몇 가지 기능을 확인하고 있습니다.이 작업이 없으면 이 작업을 종료합니다. 또한을 , 준는동안하.MediaRecorder또는MediaPlayer문제가 발생하면 이 활동을 종료합니다.

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

주요 활동의 결과를 확인하려면 어떻게 해야 합니까?

의 용자에서FirstActivity를 부르다SecondActivity 사용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();

당신의 제이당에.FirstActivityclass에 과 같은 합니다.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에서 두 활동 간에 훨씬 더 나은 방식으로 데이터 전달을 구현하려면 '활동 간에 데이터를 전달하는 더 나은 방법'을 수행하십시오.

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

재정의한 다음 매개 변수를 확인해야 합니다.

  • requestCode이 결과를 반환한 앱을 나타냅니다.은 이은당신전때정다니됩의할화이것다▁you▁when니▁this▁call▁by▁defined를 부를 때 당신이 정의합니다.startActivityForResult().
  • resultCode 실패했는지 것인지 .
  • data이 앱에서 반환된 모든 정보를 저장합니다.은 이은아도일 수 .null.

전체 프로세스를 상황에 맞게 보려면 다음과 같이 보충 답변을 제공합니다.자세한 설명은 제 전체 답변을 참조하십시오.

여기에 이미지 설명 입력

기본 활동.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);
            }
        }
    }
}

두 번째 활동.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();
    }
}

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

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

저는 문제가 있었습니다.

new Intent();

그 후에 저는 올바른 방법을 사용한다는 것을 알게 되었습니다.

getIntent();

현재의 의도를 파악하기 위해서입니다.

결과에 대한 작업 시작: Android X에서 더 이상 사용되지 않습니다.

우리가 가진 새로운 방식을 위하여.registerForActivityResult.

Java의 경우:

 // You need to create a launcher variable inside onAttach or onCreate or global, i.e, before the activity is displayed
 ActivityResultLauncher<Intent> launchSomeActivity = registerForActivityResult(
     new ActivityResultContracts.StartActivityForResult(),
     new ActivityResultCallback<ActivityResult>() {
              @Override
              public void onActivityResult(ActivityResult result) {
                   if (result.getResultCode() == Activity.RESULT_OK) {
                         Intent data = result.getData();
                         // your operation....
                    }
               }
      });

      public void openYourActivity() {
            Intent intent = new Intent(this, SomeActivity.class);
            launchSomeActivity.launch(intent);
      }

코틀린에서:

var resultLauncher = registerForActivityResult(StartActivityForResult()) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        val data: Intent? = result.data
        // your operation...
    }
}

fun openYourActivity() {
    val intent = Intent(this, SomeActivity::class.java)
    resultLauncher.launch(intent)
}

장점:

  1. 새로운 방법은 우리가 단편적인 활동이나 다른 활동을 부를 때 직면하는 복잡성을 줄이는 것입니다.
  2. 쉽게 모든 권한을 요청하고 연락을 받을 수 있습니다.

잘못된 요청에 문제가 있는 사람들을 위해 활동 결과에 코드를 삽입합니다.

▁▁you▁.startActivityForResult()의 신의에서.Fragment는 FragmentrequestCode " Fragment"를됩니다.

활동에서 올바른 결과를 얻으려면 다음을 수행하십시오. 코드는 다음과 같습니다.

변경:

startActivityForResult(intent, 1);받는 사람:

getActivity().startActivityForResult(intent, 1);

활동 결과 등록부가 권장되는 접근 방식입니다.

ComponentActivity 이제 을 제공합니다.ActivityResultRegistry당신이 그것을 다룰 수 있게 해줍니다.startActivityForResult()+onActivityResult()만 아니라requestPermissions()+onRequestPermissionsResult()를 않지흐에서 하지 않고 Activity또는Fragment다음을 통해 유형 안전성이 향상시킵니다.ActivityResultContract이러한 흐름을 테스트하기 위한 후크를 제공합니다.

Android 10 Activity 1.2.0-alpha02 및 Fragment 1.3.0-alpha02에 도입된 Activity Result API를 사용하는 것이 좋습니다.

을 당신의 니추합다에 추가하세요.build.gradle

def activity_version = "1.2.0-beta01"

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

사전 구축된 계약 사용 방법

이 새로운 API에는 다음과 같은 사전 구축된 기능이 있습니다.

  1. 비디오 촬영
  2. 연락처 선택
  3. 콘텐츠 가져오기
  4. 콘텐츠 가져오기
  5. 문서 열기
  6. 문서 열기
  7. 문서 열기나무
  8. 문서 작성
  9. 다이얼
  10. 사진 찍기
  11. 권한 요청
  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() }
}

무슨 일이 벌어지고 있는 거지?조금만 더 세분화해 보겠습니다. takePicture비트맵을 입니다. 는 null의 에 따라 달라집니다. null의 null은 null은 null입니다.onActivityResult프로세스가 성공했습니다. prepareCall 에서는 이를 그런다 이호새등기록에 있는 새 합니다.ComponentActivity라고 ActivityResultRegistry나중에 다시 얘기할게요. ActivityResultContracts.TakePicture()구글이 우리를 위해 만든 내장 도우미 중 하나이며, 마지막으로 호출합니다.takePicture실제로 이전에 사용했던 것과 같은 방식으로 의도를 트리거합니다.Activity.startActivityForResult(intent, REQUEST_CODE).

사용자 정의 계약서 작성 방법

Int를 입력으로 사용하고 요청된 활동이 Intent 결과로 반환하는 문자열을 반환하는 단순 계약입니다.

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

자세한 내용은 이 공식 문서를 참조하십시오.

작업 결과로 사용자 인터페이스를 업데이트하려는 경우 사용할 수 없습니다.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;
    }
}

이것은 바보같이 보이지만, 꽤 잘 작동합니다.

는 안드로이드 X의 새로운 "방법"을 짧은 답변으로 게시할 것입니다(경우에 따라 사용자 지정 레지스트리나 계약이 필요하지 않기 때문입니다).자세한 내용은 활동에서 결과 얻기를 참조하십시오.

중요: 실제로 Android X의 하위 호환성에 버그가 있으므로 추가해야 합니다.fragment_version당신의 Gradle 파일에.그렇지 않으면 "새 결과 API 오류: requestCode에 하위 16비트만 사용할 수 있습니다"라는 예외가 발생합니다.

dependencies {

    def activity_version = "1.2.0-beta01"
    // Java language implementation
    implementation "androidx.activity:activity:$activity_version"
    // Kotlin
    implementation "androidx.activity:activity-ktx:$activity_version"

    def fragment_version = "1.3.0-beta02"
    // Java language implementation
    implementation "androidx.fragment:fragment:$fragment_version"
    // Kotlin
    implementation "androidx.fragment:fragment-ktx:$fragment_version"
    // Testing Fragments in Isolation
    debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
}

이제 활동의 구성원 변수를 추가하면 됩니다.미리 정의된 레지스트리 및 일반 계약을 사용합니다.

public class MyActivity extends AppCompatActivity{

   ...

    /**
     * Activity callback API.
     */
    // https://developer.android.com/training/basics/intents/result
    private ActivityResultLauncher<Intent> mStartForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),

            new ActivityResultCallback<ActivityResult>() {

                @Override
                public void onActivityResult(ActivityResult result) {
                    switch (result.getResultCode()) {
                        case Activity.RESULT_OK:
                            Intent intent = result.getData();
                            // Handle the Intent
                            Toast.makeText(MyActivity.this, "Activity returned ok", Toast.LENGTH_SHORT).show();
                            break;
                        case Activity.RESULT_CANCELED:
                            Toast.makeText(MyActivity.this, "Activity canceled", Toast.LENGTH_SHORT).show();
                            break;
                    }
                }
            });

새로운 API 이전에는 다음과 같은 기능이 있었습니다.

btn.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MyActivity .this, EditActivity.class);
                startActivityForResult(intent, Constants.INTENT_EDIT_REQUEST_CODE);
            }
        });

이제 Google 프레임워크에서 요청 코드를 생성하고 유지할 수 있습니다.코드는 다음과 같습니다.

 btn.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(MyActivity .this, EditActivity.class);
                    mStartForResult.launch(intent);
                }
            });

코틀린

A와 B가 A의 활동이라고 가정합니다. 내비게이션은 A -> B의 활동입니다. 우리는 A <- B의 결과가 필요합니다.

A에서

    // calling the Activity B
    resultLauncher.launch(Intent(requireContext(), B::class.java))

    // we get data in here from B
    private var resultLauncher =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        when (result.resultCode) {
            Activity.RESULT_OK -> {
                result.data?.getStringExtra("VALUE")?.let {
                    // data received here
                }
            }
            Activity.RESULT_CANCELED -> {
                // cancel or failure
            }
        }
    }

B에서

    // Sending result value back to A
    if (success) {
       setResult(RESULT_OK, Intent().putExtra("VALUE", value))
    } else {
       setResult(RESULT_CANCELED)
    }

Android에서 매우 일반적인 문제입니다.

그것은 세 조각으로 나눌 수 있습니다.

  1. 활동 B 시작(활동 A에서 발생)
  2. 요청된 데이터 설정(활동 B에서 발생)
  3. 요청된 데이터 수신(활동 A에서 발생)
  1. 활동 B 시작
Intent i = new Intent(A.this, B.class);
startActivity(i);
  1. 요청된 데이터 설정

이 파트에서는 특정 이벤트가 발생할 때 데이터를 다시 보낼지 여부를 결정합니다.

예: 활동 B에는 편집 텍스트와 두 개의 버튼 b1, b2가 있습니다.Button 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_CANCL 응답 코드로 설정됩니다.

  1. 결과 검색

ActivityResult 메서드에 대한 재정의

@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{
       // The back button was clicked
    }
}

처사용때할을 합니다.startActivityForResult() 첫 번 에 째 변 있 경 우 는 가 수 매에 Activity그리고 만약 당신이 두 번째로부터 데이터를 보내고 싶다면.Activity 번째로Activity그런 다음 다음 다음을 사용하여 값을 전달합니다.IntentsetResult()를 를내가져다니옵부로 안에 .onActivityResult() 번째 제1의에 Activity.

기본 활동에서

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

    findViewById(R.id.takeCam).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent=new Intent(getApplicationContext(),TakePhotoActivity.class);
            intent.putExtra("Mode","Take");
            startActivity(intent);
        }
    });
    findViewById(R.id.selectGal).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent=new Intent(getApplicationContext(),TakePhotoActivity.class);
            intent.putExtra("Mode","Gallery");
            startActivity(intent);
        }
    });
}

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

}

표시할 두 번째 활동

private static final int CAMERA_REQUEST = 1888;
private ImageView imageView;
private static final int MY_CAMERA_PERMISSION_CODE = 100;
private static final int PICK_PHOTO_FOR_AVATAR = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_take_photo);

    imageView=findViewById(R.id.imageView);

    if(getIntent().getStringExtra("Mode").equals("Gallery"))
    {
        pickImage();
    }
    else {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.CAMERA}, MY_CAMERA_PERMISSION_CODE);
            } else {
                Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(cameraIntent, CAMERA_REQUEST);
            }
        }
    }
}
public void pickImage() {
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType("image/*");
    startActivityForResult(intent, PICK_PHOTO_FOR_AVATAR);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == MY_CAMERA_PERMISSION_CODE)
    {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
        {
            Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(cameraIntent, CAMERA_REQUEST);
        }
        else
        {
            Toast.makeText(this, "Camera Permission Denied..", Toast.LENGTH_LONG).show();
        }
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
        Bitmap photo = (Bitmap) data.getExtras().get("data");
        imageView.setImageBitmap(photo);
    }
        if (requestCode == PICK_PHOTO_FOR_AVATAR && resultCode == Activity.RESULT_OK) {
            if (data == null) {
                Log.d("ABC","No Such Image Selected");
                return;
            }
            try {
                Uri selectedData=data.getData();
                Log.d("ABC","Image Pick-Up");
                imageView.setImageURI(selectedData);
                InputStream inputStream = getApplicationContext().getContentResolver().openInputStream(selectedData);
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                Bitmap bmp=MediaStore.Images.Media.getBitmap(getContentResolver(),selectedData);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch(IOException e){

            }
    }
}

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{

    }
}

언급URL : https://stackoverflow.com/questions/10407159/how-to-manage-startactivityforresult-on-android

반응형