我最近发现onActivityResult已弃用。我们该怎么处理呢?

有什么替代方案吗?


当前回答

如果您正在使用SMS同意API,则使用以下代码(Kotlin):

resultLauncher.launch( consentIntent
                            )

    var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        // There are no request codes
    //    val data: Intent? = result.data
        val message = result.data?.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
        getOtpFromMessage(message)

    }
}

其他回答

下面的代码在Kotlin片段中工作,用于检查蓝牙权限。年- 2022年

val intent = intent (BluetoothAdapter.ACTION_REQUEST_ENABLE)

        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                // There are no request codes
                val data: Intent? = result.data
                bluetoothAdapter.enable()
                Toast.makeText(context, "Permission Granted: ", Toast.LENGTH_SHORT).show()
                dynamicButton()
            }
            else{Toast.makeText(context, "You have to enable bluetooth to use this app.", Toast.LENGTH_SHORT).show()}
            
        }.launch(intent)

我的目标是用最少的代码更改重用startActivityForResult方法的当前实现。为此,我使用onActivityResultFromLauncher方法创建了一个包装器类和接口。

interface ActivityResultLauncherWrapper {

    fun launchIntentForResult(activity: FragmentActivity, intent: Intent, requestCode: Int, callBack: OnActivityResultListener)

    fun unregister()

    interface OnActivityResultListener {
        fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?)
    }
}

class ActivityResultLauncherWrapperImpl : ActivityResultLauncherWrapper {
    private var weakLauncher: WeakReference<ActivityResultLauncher<Intent>>? = null

    override fun launchIntentForResult(
            activity: FragmentActivity,
            intent: Intent,
            requestCode: Int,
            callBack: ActivityResultLauncherWrapper.OnActivityResultListener
    ) {

        weakLauncher = WeakReference(
                activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                    callBack.onActivityResultFromLauncher(requestCode, result.resultCode, result.data)
                }
        )

        weakLauncher?.get()?.launch(intent)
    }

    override fun unregister() {
        weakLauncher?.get()?.unregister()
    }
}

我在我的项目中使用匕首,我在需要的地方注入了包装器

@Inject
lateinit var activityResultLauncher: ActivityResultLauncherWrapper

但是包装器也可以直接实例化:

val activityResultLauncher = ActivityResultLauncherWrapper()

然后你必须用launchIntentForResult改变startActivityForResult方法。下面是一个从片段中调用它的例子:

activityResultLauncher.launchIntentForResult(
        requireActivity(),
        intent,
        REQUEST_CODE_CONSTANT,
        object: ActivityResultLauncherWrapper.OnActivityResultListener {
            override fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?) {
                /*do something*/
            }
        }
)

您将在匿名对象中收到结果。 你可以在Fragment或FragmentActivity中使用OnActivityResultListener,如果你实现了接口,并像这样重构当前的实现:

class MyFragment : Fragment(), OnActivityResultListener {
   
 ...
    
override fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?) {/*do somthing*/}

 ...

}

正如我们所知,Kotlin类ActivityResultLauncherWrapper也可以在java代码中使用。在我的项目中也有java类。这里有一个在Fragment中实现回调接口的例子:

public class MyFragment extends Fragment implements OnActivityResultListener {
    
...

    @Inject
    ActivityResultLauncherWrapper activityResultLauncher;
//ActivityResultLauncherWrapper activityResultLauncher = new ActivityResultLauncherWrapper()

...

public void launnchActivity(@NotNull Intent intent) {
        activityResultLauncher.launchIntentForResult(requireActivity(), intent, REQUEST_CODE_CONSTANT, this);
    }

...

 @Override
    public void onActivityResultFromLauncher(int requestCode, int resultCode, Intent data) {/*do somthing*/}
...
}

我希望这有助于为您的案例构建解决方案。

似乎onActivityResult在超类中已弃用,但你在你的问题中没有提到超类名称和compileSdkVersion。

在Java和Kotlin中,只要添加@Deprecated,每个类或方法都可以标记为deprecated,所以检查你的超类,你可能扩展了一个错误的类。

当一个类被弃用时,它的所有方法也被弃用。

要看到一个快速的解决方案,点击弃用的方法,并按Ctrl+Q在Android工作室查看方法的文档,应该有一个解决方案。


在我使用androidx和API 29作为compileSdkVersion的项目中,此方法在活动和片段中不弃用

另一种方法是分3步完成。(考虑到你有一个startActivityForResult(0和onActivityResult()))

创建一个形式为var resultLauncher的变量:ActivityResultLauncher<Intent> 创建一个私有函数,在其中以这种基本格式初始化resultLauncher

resultLauncher=registerForActivityResult(ActivityResultContracts.StartActivityForResult()){result ->  

// copy paste the code from the onActivityResult replacing resultcode to result.resultCode  

if(result.resultcode==Activity.Result_OK){
val data=result.data // this data variable is of type intent and you can use it 

}else{
//code if you do not get the data 
}
}

使用startActivityForResult()返回行,并将其替换为resultLauncher.launch(intent)

如果你像这样实现你的base Activity,你可以继续使用旧的startActivityForResult。 唯一的限制是你必须使用setResult(result, intent)在你的活动中设置结果。 关键是让结果将请求代码带回结果使用者。

public class MyBaseActivity extends AppCompatActivity {
    private ActivityResultLauncher<Intent> activityLauncher;
    protected static String ACTIVITY_REQUEST_CODE = "my.activity.request.code";
    protected _originalIntent; 

    public void launchActivityForResult(Intent intent, int requestCode){
        intent.putExtra(UGM_ACTIVITY_REQUEST_CODE, requestCode);
        activityLauncher.launch(intent);
    }

    //
    //In order to be signature compatible for the rest of derived activities, 
    //we will override the deprecated method with our own implementation!
    //
    @SuppressWarnings( "deprecation" )
    public void startActivityForResult(Intent intent, int requestCode){
        launchActivityForResult(intent, requestCode);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    _originalIntent = getIntent();
        //set the default result
        setResult(Activity.RESULT_OK, _originalIntent);

        activityLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult result) {
                Intent intent = result.getData();
                int requestCode = intent.getIntExtra(ACTIVITY_REQUEST_CODE, -1);
                MyBaseActivity.this.onActivityResult(requestCode, result.getResultCode(), intent);
            }
        });
    }

}