As we already know the startActivityForResult method is now deprecated which was used for passing data and, getting responses between two activities. We previously got the response on the onActivityResult() method which we used always until now.
OntActivityResult() the old way
for example to get response on the activity we used the below logic:
1 2 3 4 5 6 7 8 9 10 |
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (resultCode == Activity.RESULT_OK) { when (requestCode) { GET_ACTIVITY_RESULT -> { // Parse result and, set apply your logic } } } |
To Start the Activity We used:
1 |
startActivityForResult(Intent(this,NewActivity::class.java),GET_ACTIVITY_RESULT ) |
ActivityResultContract the New way
The new way to get the result back to your main activity or ask for permission with the help of the below example.
First, let’s create the POJO class we will use to pass our data to the main activity ContactDetail.kt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
class ContactDetail() :Parcelable { var name: String = "" var phoneNumber: String = "" constructor(parcel: Parcel) : this() { name = parcel.readString()?:"" phoneNumber = parcel.readString()?:"" } override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeString(name) parcel.writeString(phoneNumber) } override fun describeContents(): Int { return 0 } companion object CREATOR : Parcelable.Creator<ContactDetail> { override fun createFromParcel(parcel: Parcel): ContactDetail { return ContactDetail(parcel) } override fun newArray(size: Int): Array<ContactDetail?> { return arrayOfNulls(size) } } } |
Now we will add the layout design for our contact adding page at activity_contact.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="@dimen/default_padding"> <com.google.android.material.textfield.TextInputLayout android:id="@+id/name" style="@style/TextAppearance.MaterialComponents.Body1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/default_padding" tools:text="String" > <com.google.android.material.textfield.TextInputEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/enter_your_name" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:id="@+id/phone" style="@style/TextAppearance.MaterialComponents.Body1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/default_padding" > <com.google.android.material.textfield.TextInputEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/enter_your_phone_number" android:inputType="phone" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.button.MaterialButton android:id="@+id/add_contact_bt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/default_padding" android:layout_gravity="center_horizontal" android:text="@string/add" /> </LinearLayout> |
Now the Activity code for our ContactActivity.kt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
private const val CONTACT_BUNDLE = "ContactDetail" class ContactActivity : AppCompatActivity() { lateinit var mContentViewBinding:ActivityContactBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mContentViewBinding = ActivityContactBinding.inflate(layoutInflater) setContentView(mContentViewBinding.root) mContentViewBinding.addContactBt.setOnClickListener { val contactDetail=ContactDetail() contactDetail.name= mContentViewBinding.name.editText?.text?.toString()?:"" contactDetail.phoneNumber=mContentViewBinding.phone.editText?.text?.toString()?:"" setResult(RESULT_OK, Intent().putExtra(CONTACT_BUNDLE, contactDetail)) finish() } } class Contract : ActivityResultContract<Intent, ContactDetail>() { override fun createIntent(context: Context, input: Intent):Intent { return input } override fun parseResult(resultCode: Int, intent: Intent?):ContactDetail? { return if (resultCode == Activity.RESULT_OK){ return intent?.getParcelableExtra(CONTACT_BUNDLE) }else{ null } } } } |
In above code, I have added a inner class to which is extendending the abstract ActivityResultContract class. In this, the two parameters are used 1st as Intent and, 2nd ContactDetail.
- The first parameter type is used for input in our case it will be Intent.
- The second type is used for the output and, in our case the output will be ContactDetail model class(POJO).
After the input and, output type is decided then, we have to override 2 methods:
- createIntent(context: Context, input: Intent) and, it’s return type is intent, I have used the Intent in my case.
- parseResult(resultCode: Int, intent: Intent?) we will get our response from the intent and, then we will parse our result after then, set the return type of result.
To get the result on our main activity, MainResultActivity.kt:
1 2 3 4 5 6 7 8 9 10 |
class MainResultActivity : AppCompatActivity() { lateinit var mContentViewBinding: ActivityMainResultBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mContentViewBinding = DataBindingUtil.setContentView(this,R.layout.activity_contracts_demo) mContentViewBinding.handler= MainActivityResultHandler(this) } } |
The layout design activity_main_result.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="handler" type="com.example.appresultexample.MainActivityResultHandler" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="@dimen/default_padding"> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/permission_result" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" /> <com.google.android.material.button.MaterialButton android:id="@+id/request_permission" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:onClick="@{()->handler.onClickRequestPermission()}" android:layout_marginTop="@dimen/default_padding" android:text="@string/permission" /> <com.google.android.material.button.MaterialButton android:id="@+id/custom_contract" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:onClick="@{()->handler.onClickResultContract()}" android:text="@string/add_contact" /> </LinearLayout> </layout> |
Our Handler class having all the operation Code MainActivityResultHandler.kt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
class MainActivityResultHandler(private val mContext: MainResultActivity) { private val requestPermission = mContext.registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted -> onPermissionsResult(granted) } private val customContract = mContext.registerForActivityResult(ContactActivity.Contract()) { result -> if(result==null) { Toast.makeText(mContext,mContext.getString(R.string.something_went_wrong),Toast.LENGTH_LONG).show() }else{ onCustomContractResult(result) } } private fun onPermissionsResult(result: Boolean) { mContext.mContentViewBinding.permissionResult.text = if (result) mContext.getString( R.string.permission_granted ) else mContext.getString(R.string.permission_denied) } private fun onCustomContractResult(contactDetail: ContactDetail) { mContext.mContentViewBinding.permissionResult.text = String.format(mContext.getString(R.string.added_contact),contactDetail.name,contactDetail.phoneNumber) } fun onClickRequestPermission() { requestPermission.launch(Manifest.permission.CAMERA) } fun onClickResultContract() { customContract.launch(Intent(mContext,ContactActivity::class.java)) } } |
On the handler class I have created a instance for registering the Contact Activity class. You just have to pass your custom contract and, callback into register For Activity Result.
Now there is no nested code anymore and, you don’t have to add result code constant because, it will be maintained by Contact Activity class.
Requesting for Permission
Now we don’t have to code extra for asking the permission, it can also be maintained by the register For Activity Result method
Therefore, requesting permission will be easier than before. Request Permission method and, Request Multiple Permission method contract are now used to ask for permission request.
I have provided the example for the single permission on the above code to ask for multiple permission then you just have to make only 2 changes:
To ask for multiple permission then you just have to make only 2 changes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
private val requestMultiplePermission = mContext.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {permissions : Map<String, Boolean> -> var granted:Boolean=true permissions.entries.forEach { if(!it.value){ granted=false } } if(granted){ //All Permission is granted and you can add your code here }else{ // Handle the case if all permission access not provided. } } //and now to ask multiple permission: requestMultiplePermission .launch( arrayOf(Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE) ) |
The above example Result will be:
. . . . . . . . .
This is it on passing and getting the response between activities and permission. You can also check the official documentation provided by Google for more detail: Click Here.
That’s it from my side for today, thanks for reading it until now. You can check our other android blogs Click Here.