Skip to main content

Activity Result Contracts

ActivityResultContracts is a class that we can use to do some standard and type-safe Activity operations, such as taking pictures or opening documents.

Taking Picture​

ActivityResultContracts.TakePicture class allows you to take a picture and save it to the provided content URI. The callback will return true if the picture is successfully saved.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<Uri>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.TakePicture()) { isSuccess ->
// Log the result
Log.i("TAG", isSuccess.toString())
}
}
}

Next, we only need to call the launch() method and provide the content URI of our picture file as the argument:

import androidx.core.content.FileProvider
import java.io.File

val file = File.createTempFile("temp", ".jpg")
uri = FileProvider.getUriForFile(
this@MainActivity,
"com.hanmajid.androidnotebook",
file,
)
launcher.launch(uri)

Taking Picture Preview​

ActivityResultContracts.TakePicturePreview class allows you to take a picture and save it as a Bitmap. The callback will return the Bitmap of the taken picture. Otherwise, it will return null.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<Void?>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.TakePicturePreview()) { bitmap ->
// Log the result
Log.i("TAG", bitmap.toString())
}
}
}

Next, we only need to call the launch() method:

launcher.launch(null)

Capturing Video​

ActivityResultContracts.CaptureVideo class allows you to take a video and save it to the provided content URI. The callback will return true if the video is successfully saved.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<Uri>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.CaptureVideo()) { isSuccess ->
// Log the result
Log.i("TAG", isSuccess.toString())
}
}
}

Next, we only need to call the launch() method and provide the content URI of our video file as the argument:

import androidx.core.content.FileProvider
import java.io.File

val file = File.createTempFile("temp", ".mp4")
uri = FileProvider.getUriForFile(
this@MainActivity,
"com.hanmajid.androidnotebook",
file,
)
launcher.launch(uri)

Creating Document​

ActivityResultContracts.CreateDocument class allows you to select a path for creating a new file with the given mimeType. The callback will return the content URI of the empty file that was created, or it will return null if user cancels the prompt.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<String>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.CreateDocument("text/plain")) { contentUri ->
// Log the result
Log.i("TAG", contentUri.toString())
}
}
}

In the above example, we want to create a text file (text/plain).

Next, we only need to call the launch() method and provide the suggested name for the file as the argument:

launcher.launch("new_file.txt")

Getting Document​

ActivityResultContracts.GetContent class allows you to display a prompt for user to select a file. The callback will return the content URI of the file, or it will return null if user cancels the prompt.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<String>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.GetContent()) { contentUri ->
// Log the result
Log.i("TAG", contentUri.toString())
}
}
}

Next, we only need to call the launch() method and provide the mime type filter as the argument:

launcher.launch("image/*")

Getting Multiple Documents​

ActivityResultContracts.GetMultipleContents class allows you to display a prompt for user to select one or more files. The callback will return a list of the content URI of the files, or it will return an empty list if user cancels the prompt.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<String>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.GetMultipleContents()) { contentUris ->
// Log the result
Log.i("TAG", contentUris.toString())
}
}
}

Next, we only need to call the launch() method and provide the mime type filter as the argument:

launcher.launch("image/*")

Opening Document​

ActivityResultContracts.OpenDocument class allows you to display a prompt for user to select a file similar to ActivityResultContracts.GetContent. The callback will return the content URI of the file, or it will return null if user cancels the prompt.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<Array<String>>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.OpenDocument()) { contentUri ->
// Log the result
Log.i("TAG", contentUri.toString())
}
}
}

Next, we only need to call the launch() method and provide the mime types filter as the argument:

launcher.launch(arrayOf("image/*", "video/*"))

Opening Document Tree​

ActivityResultContracts.OpenDocumentTree class allows you to display a prompt for user to select a directory. The callback will return the content URI of the directory, or it will return null if user cancels the prompt. Apps can fully manage documents within the returned directory.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<Uri?>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { contentUri ->
// Log the result
Log.i("TAG", contentUri.toString())
}
}
}

Next, we only need to call the launch() method and provide optional Uri of the initial starting location as the argument:

launcher.launch(null)

Opening Multiple Documents​

ActivityResultContracts.OpenMultipleDocuments class allows you to display a prompt for user to select multiple files similar to ActivityResultContracts.GetMultipleContents. The callback will return list of the content URI of the files, or it will return empty list if user cancels the prompt.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<Array<String>>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { contentUris ->
// Log the result
Log.i("TAG", contentUris.toString())
}
}
}

Next, we only need to call the launch() method and provide the mime types filter as the argument:

launcher.launch(arrayOf("image/*", "video/*"))

Picking Contact​

ActivityResultContracts.PickContact class allows you to display a prompt for user to select a contact from their device. The callback will return the content URI of the contact, or it will return null if the user cancels the prompt.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<Void?>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.PickContact()) { uri ->
// Log the result
Log.i("TAG", uri.toString())
}
}
}

Next, we only need to call the launch() method:

launcher.launch(null)

Picking Visual Media​

ActivityResultContracts.PickVisualMedia class allows you to display a prompt for user to select a single image, video, or other type of visual media. The callback will return the content URI of the visual media, or it will return null if the user cancels the prompt.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<PickVisualMediaRequest>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { contentUri ->
// Log the result
Log.i("TAG", contentUri.toString())
}
}
}

Next, we only need to call the launch() method and pass a PickVisualMediaRequest instance:

// For picking an image
launcher.launch(
PickVisualMediaRequest.Builder()
.setMediaType(ActivityResultContracts.PickVisualMedia.ImageOnly)
.build()
)

// For picking a video
launcher.launch(
PickVisualMediaRequest.Builder()
.setMediaType(ActivityResultContracts.PickVisualMedia.VideoOnly)
.build()
)

// For picking an image or a video
launcher.launch(
PickVisualMediaRequest.Builder()
.setMediaType(ActivityResultContracts.PickVisualMedia.ImageAndVideo)
.build()
)

// For picking a visual media with mime type "image/png"
launcher.launch(
PickVisualMediaRequest.Builder()
.setMediaType(ActivityResultContracts.PickVisualMedia.SingleMimeType("image/png"))
.build()
)

Requesting Permission​

ActivityResultContracts.RequestPermission class allows you to display a prompt for user to grant a certain permission for the app. The callback will return true if the permission is granted, or it will return false if the user denies or cancels it.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<String>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
// Log the result
Log.i("TAG", isGranted.toString())
}
}
}

Next, we only need to call the launch() method and provide the permission that you want to grant:

launcher.launch(android.Manifest.permission.ACCESS_COARSE_LOCATION)

Requesting Multiple Permissions​

ActivityResultContracts.RequestMultiplePermissions class allows you to display a prompt for user to grant multiple permissions for the app. The callback will return a Map<String, bool> that contains the permission status for each requested permission.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<Array<String>>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { mapIsGranted ->
// Log the result
Log.i("TAG", mapIsGranted.toString())
}
}
}

Next, we only need to call the launch() method and provide the array of permissions that you want to grant:

launcher.launch(
arrayOf(
android.Manifest.permission.ACCESS_COARSE_LOCATION,
android.Manifest.permission.READ_CONTACTS,
)
)

Starting Intent (Activity For Result)​

ActivityResultContracts.StartActivityForResult class allows you to start an Intent. The callback will return an ActivityResult of the output. With this class, we don't have to manage request codes ourselves.

First, register the launcher within Activity's onCreate method:

package com.hanmajid.androidnotebook

import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : ComponentActivity() {

private lateinit var launcher: ActivityResultLauncher<Intent>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { activityResult ->
// Log the result
Log.i("TAG", activityResult.toString())
}
}
}

Next, we only need to call the launch() method and provide the Intent that we want to launch:

launcher.launch(
Intent(ACTION_REQUEST_PERMISSIONS).apply {
putExtra(
EXTRA_PERMISSIONS, arrayOf(
android.Manifest.permission.ACCESS_COARSE_LOCATION
)
)
}
)

References​