기존에 startActivityForResult() 및 onActivityResult() 를 통해서 결과를 받았던 것을 Activity Result API는 시스템에서 전달되면 결과를 등록, 실행 및 처리하기 위한 구성요소를 제공합니다.

 

참고 URL

https://developer.android.com/training/basics/intents/result?hl=ko

 

활동으로부터 결과 가져오기  |  Android 개발자  |  Android Developers

개발자 앱 내의 활동이든 다른 앱의 활동이든 다른 활동을 시작하는 것이 단방향 작업일 필요는 없습니다. 다른 활동을 시작하고 다시 결과를 받을 수도 있습니다. 예를 들어 앱에서 카메라 앱

developer.android.com

사용해보기 

 

1. gradle 설정 

implementation 'androidx.activity:activity-ktx:1.2.0-beta01'
implementation 'androidx.fragment:fragment-ktx:1.3.0-beta01'

2. ActivityResultLauncher 생성 

@RequiresApi(Build.VERSION_CODES.M)
private val singlePermissions = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
) {  isSuccess ->
    Log.d(TAG, "isSuccess : " + isSuccess)
}

registerForActivityResult 파라미터로 ActivityResultContracts, 과 ActivityResultCallback를 넘기게 됩니다. 

 

3. 실행 

singlePermissions.launch(permissionName)

 

4. 2번의 결과 로그 확인 

정상적으로 동작하는것을 확인해 보았습니다. 

 

동작확인

@NonNull
@Override
public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
        @NonNull ActivityResultContract<I, O> contract,
        @NonNull ActivityResultCallback<O> callback) {
    return registerForActivityResult(contract, mActivityResultRegistry, callback);

1. 위 registerForActivityResult를 통해서  ActivityResultLauncher를 생성한 인스턴스를 실행시키는 코드로 ActivityResultLauncher를 생성합니다.

2. 생성시 첫번재 파라미터로 전달된 RequestPermission는 권한요청을 위해  ActivityResultContract를 상속받아 구현되어 제공되고있는 클래스로 하기와 같이 구현되어 있습니다.

  간단히 보면 createIntent메소드에 permission을 전달받고 parseResult로 결과를 제공합니다.

 

 

3. 하기 FragmentActivity에서onRequestPermissionsResult 오버라이딩메소드에서 조건 검사를 통해서 등록이 되어있으면 doDispatch의 callback.onActivityResult(contract.parseResult(resultCode, data))를 통해서 전달이 되어 두번째 파라미터로 전달된 callback메소드로 결과를 받을 수 있습니다.

@CallSuper
    @Override
    @Deprecated
    public void onRequestPermissionsResult(
            int requestCode,
            @NonNull String[] permissions,
            @NonNull int[] grantResults) {
        if (!mActivityResultRegistry.dispatchResult(requestCode, Activity.RESULT_OK, new Intent()
                .putExtra(EXTRA_PERMISSIONS, permissions)
                .putExtra(EXTRA_PERMISSION_GRANT_RESULTS, grantResults))) {
            if (Build.VERSION.SDK_INT >= 23) {
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
    }


private <O> void doDispatch(String key, int resultCode, @Nullable Intent data,
        @Nullable CallbackAndContract<O> callbackAndContract) {
    if (callbackAndContract != null && callbackAndContract.mCallback != null) {
        ActivityResultCallback<O> callback = callbackAndContract.mCallback;
        ActivityResultContract<?, O> contract = callbackAndContract.mContract;
        callback.onActivityResult(contract.parseResult(resultCode, data));
    } else {
        mPendingResults.putParcelable(key, new ActivityResult(resultCode, data));
    }
}

 

간단히 사용해보았는데 기존에 onActivityResult를 오버라이딩해서 처리했던것을 제공된 api를 사용하여 하기 구글 예제와 같이 ActivityResultContract를 상속받아 구현을 하면 동작에 대한 요청과 결과의 소스관리과 명확해 질 것 같습니다.

class PickRingtone : ActivityResultContract<Int, Uri?>() {
        override fun createIntent(context: Context, ringtoneType: Int) =
            Intent(RingtoneManager.ACTION_RINGTONE_PICKER).apply {
                putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, ringtoneType)
            }

        override fun parseResult(resultCode: Int, result: Intent?) : Uri? {
            if (resultCode != Activity.RESULT_OK) {
                return null
            }
            return result?.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI)
        }
    }

 

+ Recent posts