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

例如,从主活动中调用第二个活动。在这个活动中,我正在检查手机的一些功能,比如它是否有摄像头。如果没有,我就关闭这个活动。此外,在MediaRecorder或MediaPlayer的准备过程中,如果发生问题,我将关闭此活动。

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

如何检查主活动的结果?


当前回答

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

如果你在Fragment中调用startActivityForResult(), requestCode会被拥有Fragment的Activity改变。

如果你想在你的活动中得到正确的resultCode,试试这个:

变化:

startActivityForResult(意图,1);:

getActivity()。startActivityForResult(意图,1);

其他回答

从你的FirstActivity,使用startActivityForResult()方法调用SecondActivity。

例如:

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中以更好的方式实现两个活动之间的数据传递,请参见“在活动之间传递数据的更好方式”。

ActivityResultRegistry是推荐的方法

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具有以下预构建的功能

TakeVideo PickContact GetContent GetContents OpenDocument opendocument OpenDocumentTree CreateDocument 刻度盘 TakePicture RequestPermission 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() }
}

So what’s going on here? Let’s break it down slightly. takePicture is just a callback which returns a nullable Bitmap - whether or not it’s null depends on whether or not the onActivityResult process was successful. prepareCall then registers this call into a new feature on ComponentActivity called the ActivityResultRegistry - we’ll come back to this later. ActivityResultContracts.TakePicture() is one of the built-in helpers which Google have created for us, and finally invoking takePicture actually triggers the Intent in the same way that you would previously with 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)
        }
    }
}

查看官方文档了解更多信息。

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

重要提示:Android X的向后兼容性存在bug,所以你必须在Gradle文件中添加fragment_version。否则你会得到一个异常“新结果API错误:只能使用低16位的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);
            }
        });

您可能注意到请求代码现在由谷歌框架生成(并保持)。 你的代码变成:

 btn.setOnClickListener(new View.OnClickListener() {

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

首先,你在第一个活动中使用startActivityForResult()和参数,如果你想从第二个活动发送数据到第一个活动,然后使用意图通过setResult()方法传递值,并在第一个活动中的onActivityResult()方法中获取数据。

这在Android上是一个非常常见的问题

它可以被分解成三个部分

开始活动B(发生在活动A中) 设置请求的数据(发生在活动B中) 接收请求的数据(发生在活动A中)

startActivity B

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

设置请求数据

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

例如:在活动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响应代码

检索结果

重写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
    }
}