1076

在我的活动中,我正在调用主要活动中的第二个活动startActivityForResult。在我的第二个活动中,有一些方法可以完成此活动(可能没有结果),但是,其中只有一个返回结果。

例如,从主要活动中,我调用了第二个活动。在这个活动中,我正在检查手机的一些功能,例如它是否有摄像头。如果没有,那么我将关闭此活动。此外,在准备期间MediaRecorderMediaPlayer如果发生问题,我将关闭此活动。

如果它的设备有摄像头并且录制完成,那么在录制视频后,如果用户点击完成按钮,我会将结果(录制视频的地址)发送回主活动。

如何检查主要活动的结果?

4

14 回答 14

2611

从您的FirstActivity, 调用SecondActivityusingstartActivityForResult()方法。

例如:

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 中以更好的方式在两个 Activity 之间传递数据,请阅读A better way to pass data between Activities

于 2012-05-02T03:36:38.790 回答
54

如何检查主要活动的结果?

您需要覆盖Activity.onActivityResult()然后检查其参数:

  • requestCode标识哪个应用程序返回了这些结果。这是您在调用时定义的startActivityForResult()
  • resultCode通知您此应用程序是成功、失败还是其他情况
  • data保存此应用程序返回的任何信息。这可能是null
于 2012-05-02T03:07:14.187 回答
52

例子

要在上下文中查看整个过程,这是一个补充答案。有关更多解释,请参阅我的完整答案

在此处输入图像描述

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();
    }
}
于 2016-12-05T08:36:32.750 回答
47

补充Nishant 的答案,返回活动结果的最佳方法是:

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

我遇到了问题

new Intent();

然后我发现正确的方法是使用

getIntent();

获取当前意图。

于 2015-05-26T20:40:47.470 回答
20

startActivityForResult:在 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. 轻松请求任何许可并获得回调
于 2021-02-24T06:28:42.133 回答
14

对于那些在 onActivityResult 中有错误 requestCode问题的人

如果您是startActivityForResult()从您的 调用Fragment,则 requestCode 由拥有 Fragment 的 Activity 更改。

如果您想在活动中获得正确的 resultCode,请尝试以下操作:

改变:

startActivityForResult(intent, 1);至:

getActivity().startActivityForResult(intent, 1);

于 2015-10-23T12:58:55.243 回答
14

ActivityResultRegistry 是推荐的方法

ComponentActivity现在提供一个ActivityResultRegistry允许您处理startActivityForResult()+onActivityResult()requestPermissions()+onRequestPermissionsResult()流的方法,而无需覆盖Activityor中的方法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只是一个返回可空位图的回调 - 它是否为空取决于该onActivityResult过程是否成功。prepareCall然后将此调用注册到ComponentActivity名为 the的新功能中ActivityResultRegistry- 我们稍后再讨论。ActivityResultContracts.TakePicture()是 Google 为我们创建的内置助手之一,最后调用takePicture实际上会触发 Intent,就像您之前使用Activity.startActivityForResult(intent, REQUEST_CODE).

如何编写自定义合同

一个简单的契约,它将 Int 作为输入并返回一个字符串,请求的 Activity 在结果 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)
        }
    }
}

查看此官方文档以获取更多信息。

于 2020-04-03T10:06:46.710 回答
10

If you want to update the user interface with the activity result, you can't to use this.runOnUiThread(new Runnable() {}. Doing this, the UI won't refresh with the new value. Instead, you can do this:

@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;
    }
}

This seems silly, but it works pretty well.

于 2014-03-08T13:54:56.313 回答
3

我将在简短的回答中发布 Android X的新“方式” (因为在某些情况下您不需要自定义注册表或合同)。如果您想了解更多信息,请参阅: 从活动中获取结果

重要提示:Android X 的向后兼容性实际上存在一个错误,因此您必须fragment_version在 Gradle 文件中添加。否则你会得到一个异常 "New result API error : Can only use lower 16 bits for requestCode"

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);
                }
            });
于 2020-12-06T11:00:28.393 回答
2

首先,您startActivityForResult()在第一个中使用 with 参数,Activity如果您想将数据从第二个发送Activity到第一个,然后使用with方法Activity传递值并在第一个方法中获取该数据。IntentsetResult()onActivityResult()Activity

于 2014-09-30T12:30:37.843 回答
2

这是Android上非常常见的问题

它可以分为三部分

  1. 开始活动 B(在活动 A 中发生)
  2. 设置请求的数据(在活动 B 中发生)
  3. 接收请求的数据(在活动 A 中发生)
  1. 开始活动 B
Intent i = new Intent(A.this, B.class);
startActivity(i);
  1. 设置请求的数据

在这一部分中,您决定在特定事件发生时是否要发回数据。

例如:在活动 B 中有一个 EditText 和两个按钮 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 响应代码设置结果

  1. 检索结果

对于那个覆盖 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{
       // The back button was clicked
    }
}
于 2017-12-22T09:54:47.103 回答
0

您需要覆盖 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{

    }
}
于 2019-04-24T13:38:57.017 回答
0

科特林

假设 A 和 B 是导航来自 A -> B 的活动 我们需要从 A <- B 返回的结果

一个

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

    // Sending result value back to A
    if (success) {
       setResult(RESULT_OK, Intent().putExtra("VALUE", value))
    } else {
       setResult(RESULT_CANCELED)
    }
于 2022-03-02T12:59:16.240 回答
0

在您的主要活动中

@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){

            }
    }
}
于 2020-08-15T03:37:47.370 回答