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 +13 -0
- package/android/build.gradle +5 -5
- package/android/src/main/AndroidManifest.xml +46 -45
- package/android/src/main/java/expo/modules/imagepicker/ImagePickerExceptions.kt +3 -0
- package/android/src/main/java/expo/modules/imagepicker/ImagePickerModule.kt +1 -0
- package/android/src/main/java/expo/modules/imagepicker/contracts/CameraContract.kt +1 -1
- package/android/src/main/java/expo/modules/imagepicker/contracts/ContractsUtils.kt +2 -1
- package/android/src/main/java/expo/modules/imagepicker/contracts/CropImageContract.kt +6 -1
- package/android/src/main/java/expo/modules/imagepicker/contracts/ImageLibraryContract.kt +26 -8
- package/package.json +2 -2
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
|
package/android/build.gradle
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
86
|
-
implementation "androidx.appcompat:appcompat:1.
|
|
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.
|
|
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:
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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 =
|
|
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
|
-
)
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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.
|
|
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": "
|
|
47
|
+
"gitHead": "c0d646e9295094bca877513e500d3c9f2e990c42"
|
|
48
48
|
}
|