Skip to content
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
e6fbb60
save images in app data folder instead of temp
Sep 15, 2017
c4bb480
save full image in library folder
Sep 28, 2017
616f4af
retain gallery image exif for android
Sep 29, 2017
c22e8e1
read origianl exif from ios roll
Sep 29, 2017
1254ee7
fixed permission error on ios
Sep 29, 2017
d44858b
added thumbnail
Oct 13, 2017
8ca3665
fixed HEIF format
Nov 24, 2017
40440fe
check for null progress dialog
l0stpenguin Feb 5, 2018
e5d1eb2
allow orientation change
l0stpenguin Feb 5, 2018
51baed1
prevent activity recreation on orientation change
l0stpenguin Feb 5, 2018
2004bd6
Fixed incorrect orientation exif
l0stpenguin Feb 20, 2018
b0d0f78
fixed requestPermission callback on ios
l0stpenguin Jun 19, 2018
f7d2ebe
added missing method
l0stpenguin Jun 19, 2018
df98b2b
Merge pull request #1 from Telerik-Verified-Plugins/master
ombr Jun 21, 2018
b62aaa0
disable thumbnails
Aug 3, 2018
2ef685a
fixed memory leak for android bitmaps
l0stpenguin Sep 10, 2018
0fcd3ea
updated appcompat dependency
l0stpenguin Nov 13, 2018
a3adb71
Merge branch 'master' of https://github.com/Telerik-Verified-Plugins/…
Jan 14, 2019
8b04ee9
Merge branch 'Telerik-Verified-Plugins-master'
Jan 14, 2019
bf46e51
Merge pull request #3 from Telerik-Verified-Plugins/master
l0stpenguin May 6, 2019
10ed770
fixed incorrect file extension on ios
l0stpenguin Oct 15, 2019
8752d1e
Update GMGridViewController.m
l0stpenguin Oct 15, 2019
312a113
Update GMGridViewController.m
l0stpenguin Oct 16, 2019
2c94208
Merge pull request #4 from spoonconsulting/mevinDhun-patch-1
l0stpenguin Oct 16, 2019
146e76b
Fixed android permissions callback
Nov 14, 2019
5cf0c5e
Merge pull request #5 from spoonconsulting/fix-android-permissions
ombr Nov 23, 2019
5cc9d00
update package json
dinitri Sep 2, 2020
242eb84
remove repo pkg json
dinitri Sep 2, 2020
ea49d00
update pkg json
dinitri Sep 2, 2020
2d767a2
update package.json
dinitri Sep 2, 2020
b0f492f
update author
dinitri Sep 2, 2020
ab6e471
update version
dinitri Sep 2, 2020
091fa2c
add correct cordova plugin id
dinitri Feb 26, 2021
ec5f713
Merge pull request #6 from spoonconsulting/fix-plugin-cordova-id
ombr Mar 2, 2021
26cfe85
remove write external storage persmission
dinitri Apr 23, 2021
0092c72
handle content uri
dinitri Apr 28, 2021
7cf8bc4
copyToDirectory
dinitri Apr 28, 2021
e5252f4
add missing import
dinitri Apr 28, 2021
dcf7cfe
getFileDire
dinitri Apr 28, 2021
eb3f90f
add permission back
dinitri Apr 29, 2021
9691208
refactor
dinitri Apr 29, 2021
cedcca1
add selection limit and only allow native file opener ( trial)
dinitri Apr 30, 2021
3298da4
add limit exceeded msg
dinitri Apr 30, 2021
4d60664
handle cross profile exception
dinitri May 4, 2021
117e18a
reafactor package
dinitri May 4, 2021
7523a9a
refactor package
dinitri May 4, 2021
4d7c314
fix js to java link
dinitri May 4, 2021
cef0585
change intent action, change toast order
dinitri May 4, 2021
2be1573
review comment az
dinitri May 5, 2021
f29f4cd
update change log
dinitri May 5, 2021
63a29ea
Merge pull request #7 from spoonconsulting/read-external-storage
dinitri May 5, 2021
b1a4ac6
Demo added
sc-nick May 10, 2021
11141ba
Reset ImagePicker
sc-nick May 10, 2021
42d07be
Refactoring
sc-nick May 12, 2021
bae813a
Refactor
sc-nick May 14, 2021
40b1fbe
Update src/android/ImagePicker.java
azharbeebeejaun May 17, 2021
80541d5
Refactor
sc-nick May 17, 2021
a7a9752
Merge branch 'add-demo' of https://github.com/spoonconsulting/cordova…
sc-nick May 17, 2021
d2d1ed9
Update homepage
sc-nick May 17, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## [2.0.0](https://github.com/spoonconsulting/cordova-plugin-telerik-imagepicker/compare/1.0.2...2.0.0) (2021-05-05)


### Breaking Changes

* **android:** Android 11 does not support WRITE_EXTERNAL_STORAGE permission and Playstore will reject any app's manifest containting this permission.

The plugin's new package name is: com.spoon.imagepicker


## [1.0.2](https://github.com/spoonconsulting/cordova-plugin-telerik-imagepicker/releases/tag/1.0.2)
14 changes: 1 addition & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ window.imagePicker.getPictures(

### Note for Android Use

When outputType is FILE_URI the plugin returns images that are stored in a temporary directory. These images will often not be deleted automatically though. The files should be moved or deleted after you get their filepaths in javascript. If Base64 Strings are being returned, there is nothing to clean up.
The 'maximumImagesCount' option is currently the only option supported for Android

## Android 6 (M) Permissions
On Android 6 you need to request permission to read external storage at runtime when targeting API level 23+.
Expand Down Expand Up @@ -120,18 +120,6 @@ For iOS this plugin uses the ELCImagePickerController, with slight modifications

https://github.com/B-Sides/ELCImagePickerController

#### MultiImageChooser

For Android this plugin uses MultiImageChooser, with modifications. MultiImageChooser uses the BSD 2-Clause License which can be found in the file BSD_LICENSE. Some code inside MultImageChooser is licensed under the Apache license which can be found in the file APACHE_LICENSE.

https://github.com/derosa/MultiImageChooser

#### FakeR

Code(FakeR) was also taken from the phonegap BarCodeScanner plugin. This code uses the MIT license.

https://github.com/wildabeast/BarcodeScanner

## License

The MIT License
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@spoonconsulting/cordova-plugin-telerik-imagepicker",
"version": "1.0.2",
"version": "2.0.0",
"cordova_name": "ImagePicker",
"description": "This plugin allows selection of multiple images from the camera roll / gallery in a phonegap app",
"license": "MIT",
Expand Down
54 changes: 4 additions & 50 deletions plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="@spoonconsulting/cordova-plugin-telerik-imagepicker"
version="1.0.2">
version="2.0.0">

<name>ImagePicker</name>

Expand All @@ -17,7 +17,7 @@
</engines>

<js-module src="www/imagepicker.js" name="ImagePicker">
<clobbers target="plugins.imagePicker" />
<clobbers target="ImagePicker" />
</js-module>

<!-- ios -->
Expand Down Expand Up @@ -95,58 +95,12 @@
<platform name="android">
<config-file target="res/xml/config.xml" parent="/*">
<feature name="ImagePicker">
<param name="android-package" value="com.synconset.ImagePicker"/>
<param name="android-package" value="com.spoon.imagepicker.ImagePicker"/>
</feature>
</config-file>

<config-file target="AndroidManifest.xml" parent="/manifest/application">
<activity android:label="@string/multi_app_name" android:configChanges="orientation|screenSize|keyboardHidden" android:name="com.synconset.MultiImageChooserActivity" android:theme="@style/Theme.AppCompat.Light">
</activity>
</config-file>

<config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</config-file>

<framework src="com.android.support:appcompat-v7:27.1.1" />

<source-file src="src/android/com/synconset/ImagePicker/ImagePicker.java" target-dir="src/com/synconset" />
<source-file src="src/android/com/synconset/ImagePicker/FakeR.java" target-dir="src/com/synconset" />
<source-file src="src/android/com/synconset/ImagePicker/ResultIPC.java" target-dir="src/com/synconset" />

<source-file src="src/android/Library/src/ImageFetcher.java" target-dir="src/com/synconset"/>
<source-file src="src/android/Library/src/MultiImageChooserActivity.java" target-dir="src/com/synconset"/>

<resource-file src="src/android/Library/res/anim/image_pop_in.xml" target="res/anim/image_pop_in.xml"/>
<resource-file src="src/android/Library/res/drawable/grid_background.xml" target="res/drawable/grid_background.xml"/>
<resource-file src="src/android/Library/res/drawable-hdpi/image_bg.9.png" target="res/drawable-hdpi/image_bg.9.png"/>
<resource-file src="src/android/Library/res/drawable-hdpi/loading_icon.png" target="res/drawable-hdpi/loading_icon.png"/>
<resource-file src="src/android/Library/res/drawable-mdpi/ic_action_discard_dark.png" target="res/drawable-mdpi/ic_action_discard_dark.png"/>
<resource-file src="src/android/Library/res/drawable-mdpi/ic_action_discard_light.png" target="res/drawable-mdpi/ic_action_discard_light.png"/>
<resource-file src="src/android/Library/res/drawable-mdpi/ic_action_done_dark.png" target="res/drawable-mdpi/ic_action_done_dark.png"/>
<resource-file src="src/android/Library/res/drawable-mdpi/ic_action_done_light.png" target="res/drawable-mdpi/ic_action_done_light.png"/>
<resource-file src="src/android/Library/res/drawable-mdpi/ic_launcher.png" target="res/drawable-mdpi/ic_launcher.png"/>
<resource-file src="src/android/Library/res/drawable-xhdpi/ic_action_discard_dark.png" target="res/drawable-xhdpi/ic_action_discard_dark.png"/>
<resource-file src="src/android/Library/res/drawable-xhdpi/ic_action_discard_light.png" target="res/drawable-xhdpi/ic_action_discard_light.png"/>
<resource-file src="src/android/Library/res/drawable-xhdpi/ic_action_done_dark.png" target="res/drawable-xhdpi/ic_action_done_dark.png"/>
<resource-file src="src/android/Library/res/drawable-xhdpi/ic_action_done_light.png" target="res/drawable-xhdpi/ic_action_done_light.png"/>
<resource-file src="src/android/Library/res/drawable-xhdpi/ic_launcher.png" target="res/drawable-xhdpi/ic_launcher.png"/>
<resource-file src="src/android/Library/res/layout/actionbar_custom_view_done_discard.xml" target="res/layout/actionbar_custom_view_done_discard.xml"/>
<resource-file src="src/android/Library/res/layout/actionbar_discard_button.xml" target="res/layout/actionbar_discard_button.xml"/>
<resource-file src="src/android/Library/res/layout/actionbar_done_button.xml" target="res/layout/actionbar_done_button.xml"/>
<resource-file src="src/android/Library/res/layout/multiselectorgrid.xml" target="res/layout/multiselectorgrid.xml"/>
<resource-file src="src/android/Library/res/values/multiimagechooser_strings_en.xml" target="res/values/multiimagechooser_strings_en.xml"/>
<resource-file src="src/android/Library/res/values/themes.xml" target="res/values/themes.xml"/>

<resource-file src="src/android/Library/res/values-de/multiimagechooser_strings_de.xml" target="res/values-de/multiimagechooser_strings_de.xml"/>
<resource-file src="src/android/Library/res/values-es/multiimagechooser_strings_es.xml" target="res/values-es/multiimagechooser_strings_es.xml"/>
<resource-file src="src/android/Library/res/values-fr/multiimagechooser_strings_fr.xml" target="res/values-fr/multiimagechooser_strings_fr.xml"/>
<resource-file src="src/android/Library/res/values-hu/multiimagechooser_strings_hu.xml" target="res/values-hu/multiimagechooser_strings_hu.xml"/>
<resource-file src="src/android/Library/res/values-ja/multiimagechooser_strings_ja.xml" target="res/values-ja/multiimagechooser_strings_ja.xml"/>
<resource-file src="src/android/Library/res/values-ko/multiimagechooser_strings_ko.xml" target="res/values-ko/multiimagechooser_strings_ko.xml"/>
<source-file src="src/android/Library/res/values-pl/multiimagechooser_strings_pl.xml" target-dir="res/values-pl"/>

<framework src="src/android/ignorelinterrors.gradle" custom="true" type="gradleReference"/>
<framework src="src/android/androidtarget.gradle" custom="true" type="gradleReference"/>
<source-file src="src/android/ImagePicker.java" target-dir="src/com/spoon/imagepicker" />
</platform>
</plugin>
204 changes: 204 additions & 0 deletions src/android/ImagePicker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
package com.spoon.imagepicker;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ClipData;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;

import androidx.core.content.ContextCompat;

public class ImagePicker extends CordovaPlugin {
private static final String ACTION_GET_PICTURES = "getPictures";
private static final String ACTION_HAS_READ_PERMISSION = "hasReadPermission";
private static final String ACTION_REQUEST_READ_PERMISSION = "requestReadPermission";

private static final int PERMISSION_REQUEST_CODE = 100;
private static final int SELECT_PICTURE = 200;

private static final String CROSS_USER_PROFILE_ACCESS_DENIED = "Cannot access file. (-1)";

private CallbackContext callbackContext;
private int maxImageCount;

public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
this.callbackContext = callbackContext;
if (ACTION_HAS_READ_PERMISSION.equals(action)) {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, hasReadPermission()));
return true;

} else if (ACTION_REQUEST_READ_PERMISSION.equals(action)) {
requestReadPermission();
return true;

} else if (ACTION_GET_PICTURES.equals(action)) {

final JSONObject params = args.getJSONObject(0);
this.maxImageCount = params.has("maximumImagesCount") ? params.getInt("maximumImagesCount") : 20;

Intent imagePickerIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
imagePickerIntent.setType("image/*");
imagePickerIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

cordova.startActivityForResult(this, imagePickerIntent, SELECT_PICTURE);
this.showMaxLimitWarning();
return true;
}
return false;
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK && data != null) {
ArrayList<String> fileURIs = new ArrayList<String>();
if (requestCode == SELECT_PICTURE) {
if (data.getData() != null) {
Uri uri = data.getData();
String path = this.copyFileToInternalStorage(uri, "");
if (path.equals("-1")) {
callbackContext.error(CROSS_USER_PROFILE_ACCESS_DENIED);
return;
}
fileURIs.add(path);
} else {
ClipData clip = data.getClipData();
for (int i=0; i<clip.getItemCount(); i++) {
Uri uri = clip.getItemAt(i).getUri();
String path = this.copyFileToInternalStorage(uri, "");
if (path.equals("-1")) {
callbackContext.error(CROSS_USER_PROFILE_ACCESS_DENIED);
return;
}
fileURIs.add(path);
if (i + 1 > this.maxImageCount - 1) { break; }
}
}
}
JSONArray res = new JSONArray(fileURIs);
callbackContext.success(res);

} else if (resultCode == Activity.RESULT_CANCELED && data != null) {
String error = data.getStringExtra("ERRORMESSAGE");
callbackContext.error(error);

} else if (resultCode == Activity.RESULT_CANCELED) {
JSONArray res = new JSONArray();
callbackContext.success(res);

} else {
callbackContext.error("No images selected");
}
}

/**
* Choosing a picture launches another Activity, so we need to implement the
* save/restore APIs to handle the case where the CordovaActivity is killed by the OS
* before we get the launched Activity's result.
*
* @see http://cordova.apache.org/docs/en/dev/guide/platforms/android/plugin.html#launching-other-activities
*/
public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) {
this.callbackContext = callbackContext;
}


@Override
public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException {

// For now we just have one permission, so things can be kept simple...
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
callbackContext.success(1);
} else {
callbackContext.success(0);
}
}

@SuppressLint("InlinedApi")
private boolean hasReadPermission() {
return Build.VERSION.SDK_INT < 23 ||
PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(this.cordova.getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE);
}

@SuppressLint("InlinedApi")
private void requestReadPermission() {
if (!hasReadPermission()) {
cordova.requestPermissions(this, PERMISSION_REQUEST_CODE, new String[] {Manifest.permission.READ_EXTERNAL_STORAGE});
return;
}
callbackContext.success(1);
}

private String copyFileToInternalStorage(Uri uri, String newDirName) {
Uri returnUri = uri;
Cursor returnCursor = null;
try {
returnCursor = cordova.getActivity().getContentResolver().query(
returnUri,
new String[] { OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE },
null,
null,
null
);
} catch (SecurityException se) {
String toastMsg = "For the moment cross sharing of media between work profile and personal profile is not supported.";
(Toast.makeText(cordova.getContext(), toastMsg, Toast.LENGTH_LONG)).show();
Log.d("error", se.getMessage());
return "-1";
}

int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
returnCursor.moveToFirst();
String name = returnCursor.getString(nameIndex);

File output;
if (!newDirName.equals("")) {
File dir = new File(cordova.getContext().getFilesDir() + "/" + newDirName);
if (!dir.exists()) { dir.mkdir(); }
output = new File(cordova.getContext().getFilesDir() + "/" + newDirName + "/" + name);
} else {
output = new File(cordova.getContext().getFilesDir() + "/" + name);
}
try {
InputStream inputStream = cordova.getActivity().getContentResolver().openInputStream(uri);
FileOutputStream outputStream = new FileOutputStream(output);
int read = 0;
int bufferSize = 1024;
final byte[] buffers = new byte[bufferSize];
while ((read = inputStream.read(buffers)) != -1) {
outputStream.write(buffers, 0, read);
}
inputStream.close();
outputStream.close();

} catch (Exception e) {
Log.e("copyToInternalStorage ", e.getMessage());
}

return output.getPath();
}

private void showMaxLimitWarning() {
String toastMsg = "Only the first " + this.maxImageCount + " images selected will be taken.";
(Toast.makeText(cordova.getContext(), toastMsg, Toast.LENGTH_LONG)).show();
}
}
11 changes: 0 additions & 11 deletions src/android/Library/res/anim/image_pop_in.xml

This file was deleted.

Binary file removed src/android/Library/res/drawable-hdpi/icon.png
Binary file not shown.
Binary file removed src/android/Library/res/drawable-hdpi/image_bg.9.png
Binary file not shown.
Binary file not shown.
Binary file removed src/android/Library/res/drawable-ldpi/icon.png
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed src/android/Library/res/drawable-mdpi/icon.png
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
12 changes: 0 additions & 12 deletions src/android/Library/res/drawable/grid_background.xml

This file was deleted.

This file was deleted.

Loading