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();
당신의 제이당에.FirstActivity
class에 과 같은 합니다.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)
}
장점:
- 새로운 방법은 우리가 단편적인 활동이나 다른 활동을 부를 때 직면하는 복잡성을 줄이는 것입니다.
- 쉽게 모든 권한을 요청하고 연락을 받을 수 있습니다.
잘못된 요청에 문제가 있는 사람들을 위해 활동 결과에 코드를 삽입합니다.
▁▁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에는 다음과 같은 사전 구축된 기능이 있습니다.
- 비디오 촬영
- 연락처 선택
- 콘텐츠 가져오기
- 콘텐츠 가져오기
- 문서 열기
- 문서 열기
- 문서 열기나무
- 문서 작성
- 다이얼
- 사진 찍기
- 권한 요청
- 사용 권한 요청
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에서 매우 일반적인 문제입니다.
그것은 세 조각으로 나눌 수 있습니다.
- 활동 B 시작(활동 A에서 발생)
- 요청된 데이터 설정(활동 B에서 발생)
- 요청된 데이터 수신(활동 A에서 발생)
- 활동 B 시작
Intent i = new Intent(A.this, B.class);
startActivity(i);
- 요청된 데이터 설정
이 파트에서는 특정 이벤트가 발생할 때 데이터를 다시 보낼지 여부를 결정합니다.
예: 활동 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 응답 코드로 설정됩니다.
- 결과 검색
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
그런 다음 다음 다음을 사용하여 값을 전달합니다.Intent
setResult()
를 를내가져다니옵부로 안에 .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
'UFO ET IT' 카테고리의 다른 글
UITableViewCell 내부의 버튼 클릭 (0) | 2023.06.02 |
---|---|
GitHub에서 분기 이름 변경 (0) | 2023.06.02 |
jQuery에서 확인란 값 가져오기 (0) | 2023.06.02 |
iPhone Safari에서 작업할 때 오버플로: 숨김이 적용됩니까? (0) | 2023.06.02 |
CSS 디스플레이: 인라인 vs 인라인 블록 (0) | 2023.06.02 |