Skip to content

Commit

Permalink
[image-picker][android] Support using legacy image picker (#28514)
Browse files Browse the repository at this point in the history
# Why
Closes #27117
Follow up from #28510. Gives users an option to use the legacy method
for picking media on android.

# How
Added a new option to `ImagePickerOptions`, `legacy`, and updated the
docs.
cc @haileyok

# Test Plan
bare-expo ✅
  • Loading branch information
alanjhughes authored Apr 29, 2024
1 parent 1dac64d commit 7d86ee0
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const LAUNCH_PICKER_PARAMETERS: FunctionParameter[] = [
{ name: 'quality', type: 'number', values: [0, 0.2, 0.7, 1.0] },
{ name: 'exif', type: 'boolean', initial: false },
{ name: 'base64', type: 'boolean', initial: false },
{ name: 'legacy', type: 'boolean', initial: false },
{
name: 'videoExportPreset',
type: 'enum',
Expand Down
2 changes: 1 addition & 1 deletion docs/public/static/data/unversioned/expo-image-picker.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/public/static/data/v51.0.0/expo-image-picker.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions packages/expo-image-picker/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

### 🎉 New features

- Add new `legacy` option to `ImagePickerOptions` to allow using the legacy image picker on android. ([#28514](https://github.com/expo/expo/pull/28514) by [@alanjhughes](https://github.com/alanjhughes))

### 🐛 Bug fixes

- Fixed type exports for isolatedModules option in typescript ([#28499](https://github.com/expo/expo/pull/28499) by [@megacherry](https://github.com/megacherry))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ internal class ImagePickerOptions : Record, Serializable {
@Field
var cameraType: CameraType = CameraType.BACK

@Field
val legacy: Boolean = false

fun toCameraContractOptions(uri: String) = CameraContractOptions(uri, this)

fun toImageLibraryContractOptions() = ImageLibraryContractOptions(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia
import androidx.activity.result.contract.ActivityResultContracts.PickMultipleVisualMedia
import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia
import expo.modules.imagepicker.ImagePickerOptions
import expo.modules.imagepicker.MediaTypes
import expo.modules.imagepicker.UNLIMITED_SELECTION
Expand All @@ -33,6 +33,10 @@ internal class ImageLibraryContract(
?: throw Exceptions.ReactContextLost()

override fun createIntent(context: Context, input: ImageLibraryContractOptions): Intent {
if (input.options.legacy) {
return createLegacyIntent(input.options)
}

val request = PickVisualMediaRequest.Builder()
.setMediaType(
when (input.options.mediaTypes) {
Expand Down Expand Up @@ -79,11 +83,17 @@ internal class ImageLibraryContract(
} else {
intent?.takeIf { resultCode == Activity.RESULT_OK }?.getAllDataUris()?.let { uris ->
if (input.options.allowsMultipleSelection) {
ImagePickerContractResult.Success(
uris.map { uri ->
uri.toMediaType(contentResolver) to uri
val results = uris.map { uri ->
uri.toMediaType(contentResolver) to uri
}.let {
if (input.options.selectionLimit > 0) {
it.take(input.options.selectionLimit)
} else {
it
}
)
}

ImagePickerContractResult.Success(results)
} else {
if (intent.data != null) {
intent.data?.let { uri ->
Expand All @@ -99,6 +109,22 @@ internal class ImageLibraryContract(
}
} ?: ImagePickerContractResult.Error
}

private fun createLegacyIntent(options: ImagePickerOptions) = Intent(Intent.ACTION_GET_CONTENT)
.addCategory(Intent.CATEGORY_OPENABLE)
.setType("*/*")
.putExtra(
Intent.EXTRA_MIME_TYPES,
when (options.mediaTypes) {
MediaTypes.IMAGES -> arrayOf("image/*")
MediaTypes.VIDEOS -> arrayOf("video/*")
else -> arrayOf("image/*", "video/*")
}
).apply {
if (options.allowsMultipleSelection) {
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
}
}

internal data class ImageLibraryContractOptions(
Expand Down
6 changes: 6 additions & 0 deletions packages/expo-image-picker/build/ImagePicker.types.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/expo-image-picker/build/ImagePicker.types.js.map

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions packages/expo-image-picker/src/ImagePicker.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,12 @@ export type ImagePickerOptions = {
* @platform ios 14+
*/
preferredAssetRepresentationMode?: UIImagePickerPreferredAssetRepresentationMode;
/**
* Uses the legacy image picker on Android. This will allow media to be selected from outside the users photo library.
* @platform android
* @default false
*/
legacy?: boolean;
};

// @needsAudit
Expand Down

0 comments on commit 7d86ee0

Please sign in to comment.