expo-image-picker 14.3.0 → 14.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,19 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 14.3.2 — 2023-07-23
14
+
15
+ ### 💡 Others
16
+
17
+ - On Android, restore behavior from [#22658](https://github.com/expo/expo/pull/22658). ([#23617](https://github.com/expo/expo/pull/23617) by [@alanhughes](https://github.com/alanjhughes))
18
+
19
+ ## 14.3.1 - 2023-07-04
20
+
21
+ ### 🐛 Bug fixes
22
+
23
+ - Fix manifest merger build fail on Android. ([#23191](https://github.com/expo/expo/pull/23191) by [@alexandrius](https://github.com/alexandrius))
24
+ - [Android] Fix backported photo picker crashing with null intent. ([#23224](https://github.com/expo/expo/pull/23224) by [@thespacemanatee](https://github.com/thespacemanatee))
25
+
13
26
  ## 14.3.0 — 2023-06-13
14
27
 
15
28
  ### 🎉 New features
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '14.3.0'
6
+ version = '14.3.2'
7
7
 
8
8
  buildscript {
9
9
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -67,7 +67,7 @@ android {
67
67
  minSdkVersion safeExtGet("minSdkVersion", 21)
68
68
  targetSdkVersion safeExtGet("targetSdkVersion", 33)
69
69
  versionCode 22
70
- versionName "14.3.0"
70
+ versionName "14.3.2"
71
71
  }
72
72
  lintOptions {
73
73
  abortOnError false
@@ -82,10 +82,10 @@ android {
82
82
  dependencies {
83
83
  implementation project(':expo-modules-core')
84
84
 
85
- implementation "androidx.activity:activity-ktx:1.7.1"
86
- implementation "androidx.appcompat:appcompat:1.4.2"
85
+ implementation "androidx.activity:activity-ktx:1.7.2"
86
+ implementation "androidx.appcompat:appcompat:1.6.1"
87
87
  implementation "androidx.exifinterface:exifinterface:1.3.3"
88
- implementation "com.github.CanHub:Android-Image-Cropper:4.3.0"
88
+ implementation "com.github.CanHub:Android-Image-Cropper:4.3.1"
89
89
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
90
90
  implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.3"
91
91
  implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.3"
@@ -1,50 +1,51 @@
1
- <manifest xmlns:tools="http://schemas.android.com/tools"
2
- xmlns:android="http://schemas.android.com/apk/res/android">
3
- <!-- Required for picking images from camera directly -->
4
- <uses-permission android:name="android.permission.CAMERA"/>
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ xmlns:tools="http://schemas.android.com/tools">
3
+ <!-- Required for picking images from camera directly -->
4
+ <uses-permission android:name="android.permission.CAMERA" />
5
5
 
6
- <!-- Required for picking images from camera roll -->
7
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
8
- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
9
- <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
10
- <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
6
+ <!-- Required for picking images from camera roll -->
7
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
8
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
9
+ <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
10
+ <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
11
11
 
12
- <application>
13
- <!-- Trigger Google Play services to install the backported photo picker module. -->
14
- <service android:name="com.google.android.gms.metadata.ModuleDependencies"
15
- android:enabled="false"
16
- android:exported="false"
17
- tools:ignore="MissingClass">
18
- <intent-filter>
19
- <action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" />
20
- </intent-filter>
21
- <meta-data android:name="photopicker_activity:0:required" android:value="" />
22
- </service>
12
+ <application>
13
+ <service
14
+ android:name="com.google.android.gms.metadata.ModuleDependencies"
15
+ android:enabled="false"
16
+ android:exported="false"
17
+ tools:ignore="MissingClass">
18
+ <intent-filter>
19
+ <action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" />
20
+ </intent-filter>
21
+ <meta-data
22
+ android:name="photopicker_activity:0:required"
23
+ android:value="" />
24
+ </service>
23
25
 
26
+ <activity
27
+ android:name="com.canhub.cropper.CropImageActivity"
28
+ android:theme="@style/Base.Theme.AppCompat" />
29
+ <!-- https://developer.android.com/guide/topics/manifest/provider-element.html -->
30
+ <provider
31
+ android:name=".fileprovider.ImagePickerFileProvider"
32
+ android:authorities="${applicationId}.ImagePickerFileProvider"
33
+ android:exported="false"
34
+ android:grantUriPermissions="true">
35
+ <meta-data
36
+ android:name="android.support.FILE_PROVIDER_PATHS"
37
+ android:resource="@xml/image_picker_provider_paths" />
38
+ </provider>
39
+ </application>
24
40
 
25
- <activity
26
- android:name="com.canhub.cropper.CropImageActivity"
27
- android:theme="@style/Base.Theme.AppCompat"/>
28
- <!-- https://developer.android.com/guide/topics/manifest/provider-element.html -->
29
- <provider
30
- android:name=".fileprovider.ImagePickerFileProvider"
31
- android:authorities="${applicationId}.ImagePickerFileProvider"
32
- android:exported="false"
33
- android:grantUriPermissions="true">
34
- <meta-data
35
- android:name="android.support.FILE_PROVIDER_PATHS"
36
- android:resource="@xml/image_picker_provider_paths"/>
37
- </provider>
38
- </application>
39
-
40
- <queries>
41
- <intent>
42
- <!-- Required for picking images from the camera roll if targeting API 30 -->
43
- <action android:name="android.media.action.IMAGE_CAPTURE" />
44
- </intent>
45
- <intent>
46
- <!-- Required for picking images from the camera if targeting API 30 -->
47
- <action android:name="android.media.action.ACTION_VIDEO_CAPTURE" />
48
- </intent>
49
- </queries>
41
+ <queries>
42
+ <intent>
43
+ <!-- Required for picking images from the camera roll if targeting API 30 -->
44
+ <action android:name="android.media.action.IMAGE_CAPTURE" />
45
+ </intent>
46
+ <intent>
47
+ <!-- Required for picking images from the camera if targeting API 30 -->
48
+ <action android:name="android.media.action.ACTION_VIDEO_CAPTURE" />
49
+ </intent>
50
+ </queries>
50
51
  </manifest>
@@ -10,6 +10,9 @@ internal class FailedToDeduceTypeException :
10
10
  internal class FailedToCreateFileException(path: String, cause: Throwable? = null) :
11
11
  CodedException("Failed to create the file '$path'", cause)
12
12
 
13
+ internal class FailedToPickMediaException :
14
+ CodedException("Failed to parse PhotoPicker result")
15
+
13
16
  internal class FailedToExtractVideoMetadataException(file: File? = null, cause: Throwable? = null) :
14
17
  CodedException("Failed to extract metadata from video file '${file?.toUri()?.toString() ?: ""}'", cause)
15
18
 
@@ -166,6 +166,7 @@ class ImagePickerModule : Module() {
166
166
  when (val pickingResult = pickerLauncher()) {
167
167
  is ImagePickerContractResult.Success -> pickingResult
168
168
  is ImagePickerContractResult.Cancelled -> throw OperationCanceledException()
169
+ is ImagePickerContractResult.Error -> throw FailedToPickMediaException()
169
170
  }
170
171
  }
171
172
 
@@ -23,7 +23,7 @@ import java.io.Serializable
23
23
  internal class CameraContract(
24
24
  private val appContextProvider: AppContextProvider,
25
25
  ) : AppContextActivityResultContract<CameraContractOptions, ImagePickerContractResult> {
26
- val contentResolver: ContentResolver
26
+ private val contentResolver: ContentResolver
27
27
  get() = requireNotNull(appContextProvider.appContext.reactContext) {
28
28
  "React Application Context is null"
29
29
  }.contentResolver
@@ -7,6 +7,7 @@ import expo.modules.imagepicker.MediaType
7
7
  * Data required to be returned upon successful contract completion
8
8
  */
9
9
  internal sealed class ImagePickerContractResult private constructor() {
10
- class Cancelled : ImagePickerContractResult()
11
10
  class Success(val data: List<Pair<MediaType, Uri>>) : ImagePickerContractResult()
11
+ class Cancelled : ImagePickerContractResult()
12
+ class Error : ImagePickerContractResult()
12
13
  }
@@ -4,6 +4,7 @@ import android.app.Activity
4
4
  import android.content.Context
5
5
  import android.content.Intent
6
6
  import android.net.Uri
7
+ import android.os.Build
7
8
  import androidx.core.net.toFile
8
9
  import androidx.core.net.toUri
9
10
  import androidx.core.os.bundleOf
@@ -54,7 +55,11 @@ internal class CropImageContract(
54
55
  }
55
56
 
56
57
  override fun parseResult(input: CropImageContractOptions, resultCode: Int, intent: Intent?): ImagePickerContractResult {
57
- val result = intent?.getParcelableExtra<CropImage.ActivityResult?>(CropImage.CROP_IMAGE_EXTRA_RESULT)
58
+ val result = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
59
+ intent?.getParcelableExtra(CropImage.CROP_IMAGE_EXTRA_RESULT, CropImage.ActivityResult::class.java)
60
+ } else {
61
+ intent?.getParcelableExtra(CropImage.CROP_IMAGE_EXTRA_RESULT)
62
+ }
58
63
  if (resultCode == Activity.RESULT_CANCELED || result == null) {
59
64
  return ImagePickerContractResult.Cancelled()
60
65
  }
@@ -27,7 +27,7 @@ import java.io.Serializable
27
27
  internal class ImageLibraryContract(
28
28
  private val appContextProvider: AppContextProvider,
29
29
  ) : AppContextActivityResultContract<ImageLibraryContractOptions, ImagePickerContractResult> {
30
- val contentResolver: ContentResolver
30
+ private val contentResolver: ContentResolver
31
31
  get() = requireNotNull(appContextProvider.appContext.reactContext) {
32
32
  "React Application Context is null"
33
33
  }.contentResolver
@@ -39,14 +39,17 @@ internal class ImageLibraryContract(
39
39
  MediaTypes.VIDEOS -> {
40
40
  PickVisualMedia.VideoOnly
41
41
  }
42
+
42
43
  MediaTypes.IMAGES -> {
43
44
  PickVisualMedia.ImageOnly
44
45
  }
46
+
45
47
  else -> {
46
48
  PickVisualMedia.ImageAndVideo
47
49
  }
48
50
  }
49
- ).build()
51
+ )
52
+ .build()
50
53
 
51
54
  if (input.options.allowsMultipleSelection) {
52
55
  val selectionLimit = input.options.selectionLimit
@@ -73,13 +76,28 @@ internal class ImageLibraryContract(
73
76
  override fun parseResult(input: ImageLibraryContractOptions, resultCode: Int, intent: Intent?) =
74
77
  if (resultCode == Activity.RESULT_CANCELED) {
75
78
  ImagePickerContractResult.Cancelled()
76
- } else if (input.options.allowsMultipleSelection) {
77
- val uris = requireNotNull(intent).getAllDataUris()
78
- ImagePickerContractResult.Success(uris.map { uri -> uri.toMediaType(contentResolver) to uri })
79
79
  } else {
80
- val uri = requireNotNull(requireNotNull(intent).data)
81
- val type = uri.toMediaType(contentResolver)
82
- ImagePickerContractResult.Success(listOf(type to uri))
80
+ intent?.takeIf { resultCode == Activity.RESULT_OK }?.getAllDataUris()?.let { uris ->
81
+ if (input.options.allowsMultipleSelection) {
82
+ ImagePickerContractResult.Success(
83
+ uris.map { uri ->
84
+ uri.toMediaType(contentResolver) to uri
85
+ }
86
+ )
87
+ } else {
88
+ if (intent.data != null) {
89
+ intent.data?.let {
90
+ val type = it.toMediaType(contentResolver)
91
+ ImagePickerContractResult.Success(listOf(type to it))
92
+ }
93
+ } else {
94
+ uris.firstOrNull()?.let { uri ->
95
+ val type = uri.toMediaType(contentResolver)
96
+ ImagePickerContractResult.Success(listOf(type to uri))
97
+ } ?: ImagePickerContractResult.Error()
98
+ }
99
+ }
100
+ } ?: ImagePickerContractResult.Error()
83
101
  }
84
102
  }
85
103
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-image-picker",
3
- "version": "14.3.0",
3
+ "version": "14.3.2",
4
4
  "description": "Provides access to the system's UI for selecting images and videos from the phone's library or taking a photo with the camera.",
5
5
  "main": "build/ImagePicker.js",
6
6
  "types": "build/ImagePicker.d.ts",
@@ -44,5 +44,5 @@
44
44
  "peerDependencies": {
45
45
  "expo": "*"
46
46
  },
47
- "gitHead": "3ccd2edee9cbfed217557675cb50f0ba5e55a9e4"
47
+ "gitHead": "c0d646e9295094bca877513e500d3c9f2e990c42"
48
48
  }