├── .gitignore
├── LICENSE
├── README.md
├── demo
├── config.xml
└── www
│ ├── css
│ └── index.css
│ ├── index.html
│ └── js
│ └── index.js
├── dev
├── android
│ ├── .gitignore
│ ├── GalleryPicker.iml
│ ├── android.iml
│ ├── app
│ │ ├── .gitignore
│ │ ├── app.iml
│ │ ├── build.gradle
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── subitolabs
│ │ │ │ └── cordova
│ │ │ │ └── galleryapi
│ │ │ │ └── ApplicationTest.java
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── subitolabs
│ │ │ │ └── cordova
│ │ │ │ └── galleryapi
│ │ │ │ ├── GalleryAPI.java
│ │ │ │ └── MainActivity.java
│ │ │ └── res
│ │ │ ├── drawable-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── drawable-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── drawable-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── drawable-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── layout
│ │ │ └── activity_main.xml
│ │ │ ├── menu
│ │ │ └── menu_main.xml
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── settings.gradle
└── ios
│ └── GalleryAPI
│ ├── NSObject_GalleryAPI.h
│ ├── galleryapi.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcshareddata
│ │ │ └── galleryapi.xccheckout
│ │ └── xcuserdata
│ │ │ └── tom.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcuserdata
│ │ └── tom.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ ├── galleryapi.xcscheme
│ │ └── xcschememanagement.plist
│ ├── galleryapi
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Base.lproj
│ │ ├── LaunchScreen.xib
│ │ └── Main.storyboard
│ ├── GalleryAPI.h
│ ├── GalleryAPI.m
│ ├── Images.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Info.plist
│ ├── ViewController.h
│ ├── ViewController.m
│ └── main.m
│ └── galleryapiTests
│ ├── Info.plist
│ └── galleryapiTests.m
├── plugin.xml
├── src
├── android
│ └── GalleryAPI.java
└── ios
│ ├── GalleryAPI.h
│ └── GalleryAPI.m
└── www
└── gallery-api.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea
3 | .gradle
4 |
5 | /demo/platforms
6 | /demo/plugins
7 |
8 | *.class
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.ear
17 |
18 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
19 | hs_err_pid*
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Subito Labs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # cordova-gallery-api
2 |
3 | This plugin defines a global `galleryAPI` object, which offer methods to query gallery albums and media:
4 |
5 | - getAlbums
6 | - getMedia
7 |
8 | ### Method `getAlbums`
9 |
10 | Returns an array of object `{"id" : ..., "title" : ...}`.
11 |
12 | ### Method `getMedia`
13 |
14 | Returns an array of object with the following fields:
15 |
16 | - id
17 | - title
18 | - lat
19 | - lon
20 | - thumbnail
21 | - data
22 | - width
23 | - height
24 | - size
25 | - date_create
26 |
27 | ### Installation
28 |
29 | cordova plugin add https://github.com/subitolabs/cordova-gallery-api.git
30 |
31 | ### Quick example
32 |
33 | ```js
34 | document.addEventListener('deviceready', function()
35 | {
36 | var $content = document.getElementById("content");
37 |
38 | $content.innerHTML = "Loading albums ...";
39 |
40 | galleryAPI.getAlbums(function(items)
41 | {
42 | var html = "";
43 |
44 | for(var i = 0; i < items.length; i++)
45 | {
46 | var album = items[i];
47 |
48 | html += '' + escape(album.title) + '';
49 | }
50 |
51 | $content.innerHTML = html;
52 |
53 | }, function(error){alert(error);});
54 |
55 | window.loadAlbum = function(albumName)
56 | {
57 | galleryAPI.getMedia(albumName, function(items)
58 | {
59 | var html = "";
60 |
61 | for(var i = 0; i < items.length; i++)
62 | {
63 | var media = items[i];
64 |
65 | html += '
';
66 | }
67 |
68 | $content.innerHTML = html;
69 |
70 | }, function(error){alert(error);});
71 | };
72 |
73 | }, false);
74 | ```
75 |
--------------------------------------------------------------------------------
/demo/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | GalleryAPIDemo
4 |
5 | A sample Apache Cordova application that responds to the deviceready event.
6 |
7 |
8 | Apache Cordova Team
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/demo/www/css/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | -webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */
3 | box-sizing: border-box;
4 | }
5 |
6 | body {
7 | -webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */
8 | -webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */
9 | -webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */
10 | background-color:#E4E4E4;
11 | font-family:'HelveticaNeue-Light', 'HelveticaNeue', Helvetica, Arial, sans-serif;
12 | font-size:12px;
13 | height:100%;
14 | margin:0px;
15 | padding:0px;
16 | width:100%;
17 | }
18 |
19 | a.album
20 | {
21 | display: block;
22 | line-height: 100px;
23 | padding: 10px;
24 | border-bottom:1px solid #D2D2D2;
25 | }
26 |
27 | a.media
28 | {
29 | display: inline-block;
30 | width:50%;
31 | height:150px;
32 | text-align: center;
33 | vertical-align: middle;
34 | }
35 |
36 | a.media > img
37 | {
38 | margin:1%;
39 | width: 100%;
40 | height: 100%;
41 | object-fit: cover;
42 | }
--------------------------------------------------------------------------------
/demo/www/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Hello World
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/demo/www/js/index.js:
--------------------------------------------------------------------------------
1 | document.addEventListener('deviceready', function()
2 | {
3 | var $content = document.getElementById("content");
4 |
5 | $content.innerHTML = "Loading albums ...";
6 |
7 | galleryAPI.getAlbums(function(items)
8 | {
9 | var html = "";
10 |
11 | for(var i = 0; i < items.length; i++)
12 | {
13 | var album = items[i];
14 |
15 | html += '' + escape(album.title) + '';
16 | }
17 |
18 | $content.innerHTML = html;
19 |
20 | }, function(error){alert(error);});
21 |
22 | window.loadAlbum = function(albumName)
23 | {
24 | galleryAPI.getMedia(albumName, function(items)
25 | {
26 | var html = "";
27 |
28 | for(var i = 0; i < items.length; i++)
29 | {
30 | var media = items[i];
31 |
32 | html += '
';
33 | }
34 |
35 | $content.innerHTML = html;
36 |
37 | }, function(error){alert(error);});
38 | };
39 |
40 | function escape(v)
41 | {
42 | return v.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
43 | return ''+i.charCodeAt(0)+';';
44 | });
45 | }
46 |
47 |
48 | }, false);
49 |
--------------------------------------------------------------------------------
/dev/android/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | local.properties
3 | .idea/workspace.xml
4 | .idea/libraries
5 | .DS_Store
6 | build
7 |
--------------------------------------------------------------------------------
/dev/android/GalleryPicker.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/dev/android/android.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/dev/android/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/dev/android/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/dev/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 21
5 | buildToolsVersion "21.1.2"
6 |
7 | defaultConfig {
8 | applicationId "com.subitolabs.android.cordova.gallerypicker"
9 | minSdkVersion 15
10 | targetSdkVersion 21
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | compile 'com.android.support:appcompat-v7:21.0.3'
25 | compile files('libs/cordova-3.7.1.jar')
26 | }
27 |
--------------------------------------------------------------------------------
/dev/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/tom/dev/adt/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/dev/android/app/src/androidTest/java/com/subitolabs/cordova/galleryapi/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.subitolabs.cordova.galleryapi;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/dev/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/dev/android/app/src/main/java/com/subitolabs/cordova/galleryapi/GalleryAPI.java:
--------------------------------------------------------------------------------
1 | package com.subitolabs.cordova.galleryapi;
2 |
3 |
4 | import android.Manifest;
5 | import android.content.Context;
6 | import android.content.pm.PackageManager;
7 | import android.database.Cursor;
8 | import android.graphics.Bitmap;
9 | import android.graphics.BitmapFactory;
10 | import android.graphics.Matrix;
11 | import android.net.Uri;
12 | import android.os.Build;
13 | import android.provider.MediaStore;
14 | import android.support.annotation.NonNull;
15 | import android.support.v4.app.ActivityCompat;
16 | import android.support.v4.content.ContextCompat;
17 | import android.util.Log;
18 | import android.widget.Toast;
19 |
20 | import org.apache.cordova.*;
21 | import org.json.JSONArray;
22 | import org.json.JSONException;
23 | import org.json.JSONObject;
24 |
25 | import java.io.ByteArrayOutputStream;
26 | import java.io.File;
27 | import java.io.FileOutputStream;
28 | import java.io.IOException;
29 | import java.util.ArrayList;
30 | import java.util.Collections;
31 | import java.util.Iterator;
32 | import java.util.List;
33 |
34 | public class GalleryAPI extends CordovaPlugin {
35 | public static final String ACTION_CHECK_PERMISSION = "checkPermission";
36 | public static final String ACTION_GET_MEDIA = "getMedia";
37 | public static final String ACTION_GET_MEDIA_THUMBNAIL = "getMediaThumbnail";
38 | public static final String ACTION_GET_HQ_IMAGE_DATA = "getHQImageData";
39 | public static final String ACTION_GET_ALBUMS = "getAlbums";
40 | public static final String DIR_NAME = ".mendr";
41 | public static final String SUB_DIR_NAME = ".mendr_hq";
42 |
43 | private static final int BASE_SIZE = 300;
44 |
45 | private static BitmapFactory.Options ops = null;
46 |
47 | private static final int STORAGE_PERMISSIONS_REQUEST = 1;
48 |
49 | private CallbackContext cbc = null;
50 |
51 | @Override
52 | public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
53 | try {
54 | if (ACTION_GET_MEDIA.equals(action)) {
55 | cordova.getThreadPool().execute(new Runnable() {
56 | public void run() {
57 | try {
58 | JSONObject object = (JSONObject) args.get(0);
59 | ArrayOfObjects albums = getMedia(object.getString("title"));
60 | callbackContext.success(new JSONArray(albums));
61 | } catch (Exception e) {
62 | e.printStackTrace();
63 | callbackContext.error(e.getMessage());
64 | }
65 | }
66 | });
67 |
68 | return true;
69 | } else if (ACTION_CHECK_PERMISSION.equals(action)) {
70 | cordova.getThreadPool().execute(new Runnable() {
71 | public void run() {
72 | cbc = callbackContext;
73 | checkPermission();
74 | }
75 | });
76 | return true;
77 | } else if (ACTION_GET_MEDIA_THUMBNAIL.equals(action)) {
78 | cordova.getThreadPool().execute(new Runnable() {
79 | public void run() {
80 | try {
81 | JSONObject media = getMediaThumbnail((JSONObject) args.get(0));
82 | callbackContext.success(media);
83 | } catch (Exception e) {
84 | e.printStackTrace();
85 | callbackContext.error(e.getMessage());
86 | }
87 | }
88 | });
89 | return true;
90 | } else if (ACTION_GET_HQ_IMAGE_DATA.equals(action)) {
91 | cordova.getThreadPool().execute(new Runnable() {
92 | public void run() {
93 | try {
94 | File imagePath = getHQImageData((JSONObject) args.get(0));
95 | callbackContext.success(imagePath.toString());
96 | } catch (Exception e) {
97 | e.printStackTrace();
98 | callbackContext.error(e.getMessage());
99 | }
100 | }
101 | });
102 | return true;
103 | } else if (ACTION_GET_ALBUMS.equals(action)) {
104 | cordova.getThreadPool().execute(new Runnable() {
105 | public void run() {
106 | try {
107 | ArrayOfObjects albums = getBuckets();
108 | callbackContext.success(new JSONArray(albums));
109 | } catch (Exception e) {
110 | e.printStackTrace();
111 | callbackContext.error(e.getMessage());
112 | }
113 | }
114 | });
115 |
116 | return true;
117 | }
118 | callbackContext.error("Invalid action");
119 | return false;
120 | } catch (Exception e) {
121 | e.printStackTrace();
122 | callbackContext.error(e.getMessage());
123 | return false;
124 | }
125 | }
126 |
127 | public ArrayOfObjects getBuckets() throws JSONException {
128 | Object columns = new Object() {{
129 | put("id", MediaStore.Images.ImageColumns.BUCKET_ID);
130 | put("title", MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME);
131 | }};
132 |
133 | final ArrayOfObjects results = queryContentProvider(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, "1) GROUP BY 1,(2");
134 |
135 | Object collection = null;
136 | for (int i = 0; i < results.size(); i++) {
137 | collection = results.get(i);
138 | if (collection.getString("title").equals("Camera")) {
139 | results.remove(i);
140 | break;
141 | }
142 | }
143 |
144 | if (collection != null)
145 | results.add(0, collection);
146 |
147 | return results;
148 | }
149 |
150 | private ArrayOfObjects getMedia(String bucket) throws JSONException {
151 | Object columns = new Object() {{
152 | put("int.id", MediaStore.Images.Media._ID);
153 | put("data", MediaStore.MediaColumns.DATA);
154 | put("int.date_added", MediaStore.Images.ImageColumns.DATE_ADDED);
155 | put("title", MediaStore.Images.ImageColumns.DISPLAY_NAME);
156 | put("int.height", MediaStore.Images.ImageColumns.HEIGHT);
157 | put("int.width", MediaStore.Images.ImageColumns.WIDTH);
158 | put("int.orientation", MediaStore.Images.ImageColumns.ORIENTATION);
159 | put("mime_type", MediaStore.Images.ImageColumns.MIME_TYPE);
160 | put("float.lat", MediaStore.Images.ImageColumns.LATITUDE);
161 | put("float.lon", MediaStore.Images.ImageColumns.LONGITUDE);
162 | put("int.size", MediaStore.Images.ImageColumns.SIZE);
163 | put("int.thumbnail_id", MediaStore.Images.ImageColumns.MINI_THUMB_MAGIC);
164 | }};
165 |
166 | final ArrayOfObjects results = queryContentProvider(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, "bucket_display_name = \"" + bucket + "\"");
167 |
168 | ArrayOfObjects temp = new ArrayOfObjects();
169 |
170 |
171 | for (Object media : results) {
172 | media.put("thumbnail", "");
173 | media.put("error", "false");
174 |
175 | if (media.getInt("height") <= 0 || media.getInt("width") <= 0) {
176 | System.err.println(media);
177 | } else {
178 | temp.add(media);
179 | }
180 | }
181 |
182 | Collections.reverse(temp);
183 | return temp;
184 | }
185 |
186 | private void checkPermission() {
187 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
188 | List permissions = new ArrayList();
189 |
190 | boolean isReadDenied = false;
191 | boolean isWriteDenied = false;
192 |
193 | if (ContextCompat.checkSelfPermission(this.getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
194 | if (ActivityCompat.shouldShowRequestPermissionRationale(this.cordova.getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE))
195 | isReadDenied = true;
196 | else
197 | permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
198 | }
199 |
200 | if (ContextCompat.checkSelfPermission(this.getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
201 | if (ActivityCompat.shouldShowRequestPermissionRationale(this.cordova.getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))
202 | isWriteDenied = true;
203 | else
204 | permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
205 | }
206 |
207 | if (isReadDenied || isWriteDenied) {
208 | String message;
209 |
210 | if (isReadDenied && isWriteDenied)
211 | message = "Read and Write permissions are denied";
212 | else if (isReadDenied)
213 | message = "Read permission is denied";
214 | else
215 | message = "Write permission is denied";
216 |
217 | sendCheckPermissionResult(false, message);
218 | } else if (permissions.size() > 0) {
219 | String[] pArray = new String[permissions.size()];
220 | pArray = permissions.toArray(pArray);
221 | ActivityCompat.requestPermissions(this.cordova.getActivity(), pArray, STORAGE_PERMISSIONS_REQUEST);
222 | } else
223 | sendCheckPermissionResult(true, "Authorized");
224 | } else
225 | sendCheckPermissionResult(true, "Authorized");
226 | }
227 |
228 | public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
229 | switch (requestCode) {
230 | case STORAGE_PERMISSIONS_REQUEST: {
231 | if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
232 | sendCheckPermissionResult(true, "Authorized");
233 | else
234 | sendCheckPermissionResult(false, "Denied");
235 | return;
236 | }
237 | }
238 | }
239 |
240 | private void sendCheckPermissionResult(Boolean success, String message) {
241 | try {
242 | JSONObject result = new JSONObject();
243 | result.put("success", success);
244 | result.put("message", message);
245 | cbc.success(result);
246 | } catch (Exception e) {
247 | e.printStackTrace();
248 | cbc.error(e.getMessage());
249 | }
250 | }
251 |
252 | private JSONObject getMediaThumbnail(JSONObject media) throws JSONException {
253 |
254 | File thumbnailPath = thumbnailPathFromMediaId(media.getString("id"));
255 | if (thumbnailPath.exists()) {
256 | System.out.println("Thumbnail Already Exists!!!. Not Creating New One");
257 | media.put("thumbnail", thumbnailPath);
258 | } else {
259 | if (ops == null) {
260 | ops = new BitmapFactory.Options();
261 | ops.inJustDecodeBounds = false;
262 | ops.inSampleSize = 1;
263 | }
264 | media.put("error", "true");
265 |
266 | File image = new File(media.getString("data"));
267 |
268 | int sourceWidth = media.getInt("width");
269 | int sourceHeight = media.getInt("height");
270 |
271 | if (sourceHeight > 0 && sourceWidth > 0) {
272 | int destinationWidth, destinationHeight;
273 |
274 | if (sourceWidth > sourceHeight) {
275 | destinationHeight = BASE_SIZE;
276 | destinationWidth = (int) Math.ceil(destinationHeight * ((double) sourceWidth / sourceHeight));
277 | } else {
278 | destinationWidth = BASE_SIZE;
279 | destinationHeight = (int) Math.ceil(destinationWidth * ((double) sourceHeight / sourceWidth));
280 | }
281 |
282 | if (sourceWidth * sourceHeight > 600000 && sourceWidth * sourceHeight < 1000000) {
283 | ops.inSampleSize = 4;
284 | } else if (sourceWidth * sourceHeight > 1000000) {
285 | ops.inSampleSize = 8;
286 | }
287 |
288 | Bitmap originalImageBitmap = BitmapFactory.decodeFile(image.getAbsolutePath(), ops); //creating bitmap of original image
289 |
290 | if (originalImageBitmap == null) {
291 | ops.inSampleSize = 1;
292 | originalImageBitmap = BitmapFactory.decodeFile(image.getAbsolutePath(), ops);
293 | }
294 |
295 | if (originalImageBitmap != null) {
296 |
297 | if (destinationHeight <= 0 || destinationWidth <= 0) {
298 | System.out.println("destinationHeight: " + destinationHeight + " destinationWidth: " + destinationWidth);
299 | }
300 |
301 | Bitmap thumbnailBitmap = Bitmap.createScaledBitmap(originalImageBitmap, destinationWidth, destinationHeight, true);
302 | originalImageBitmap.recycle();
303 |
304 | if (thumbnailBitmap != null) {
305 | int orientation = media.getInt("orientation");
306 | if (orientation > 0)
307 | thumbnailBitmap = rotate(thumbnailBitmap, orientation);
308 |
309 | byte[] thumbnailData = getBytesFromBitmap(thumbnailBitmap);
310 | thumbnailBitmap.recycle();
311 | if (thumbnailData != null) {
312 | FileOutputStream outStream;
313 | try {
314 | outStream = new FileOutputStream(thumbnailPath);
315 | outStream.write(thumbnailData);
316 | outStream.close();
317 | } catch (IOException e) {
318 | Log.e("Mendr", "Couldn't write the thumbnail image data");
319 | e.printStackTrace();
320 | }
321 |
322 | if (thumbnailPath.exists()) {
323 | System.out.println("Thumbnail didn't Exists!!!. Created New One");
324 | media.put("thumbnail", thumbnailPath);
325 | media.put("error", "false");
326 | }
327 | } else
328 | Log.e("Mendr", "Couldn't convert thumbnail bitmap to byte array");
329 | } else
330 | Log.e("Mendr", "Couldn't create the thumbnail bitmap");
331 | } else
332 | Log.e("Mendr", "Couldn't decode the original image");
333 | } else
334 | Log.e("Mendr", "Invalid Media!!! Image width or height is 0");
335 | }
336 |
337 | return media;
338 | }
339 |
340 | private File getHQImageData(JSONObject media) throws JSONException {
341 | File imagePath = imagePathFromMediaId(media.getString("id"));
342 |
343 | BitmapFactory.Options ops = new BitmapFactory.Options();
344 | ops.inJustDecodeBounds = false;
345 | ops.inSampleSize = 1;
346 |
347 | File image = new File(media.getString("data"));
348 |
349 | int sourceWidth = media.getInt("width");
350 | int sourceHeight = media.getInt("height");
351 |
352 | if (sourceHeight > 0 && sourceWidth > 0) {
353 | Bitmap originalImageBitmap = BitmapFactory.decodeFile(image.getAbsolutePath(), ops); //creating bitmap of original image
354 |
355 | if (originalImageBitmap != null) {
356 | int orientation = media.getInt("orientation");
357 | if (orientation > 0)
358 | originalImageBitmap = rotate(originalImageBitmap, orientation);
359 |
360 | byte[] imageData = getBytesFromBitmap(originalImageBitmap);
361 | originalImageBitmap.recycle();
362 | if (imageData != null) {
363 | FileOutputStream outStream;
364 | try {
365 | outStream = new FileOutputStream(imagePath);
366 | outStream.write(imageData);
367 | outStream.close();
368 | } catch (IOException e) {
369 | Log.e("Mendr", "Couldn't write the image data");
370 | e.printStackTrace();
371 | }
372 | }
373 | } else
374 | Log.e("Mendr", "Couldn't decode the original image");
375 | } else
376 | Log.e("Mendr", "Invalid Media!!! Image width or height is 0");
377 |
378 | return imagePath;
379 | }
380 |
381 | private byte[] getBytesFromBitmap(Bitmap bitmap) {
382 | ByteArrayOutputStream stream = new ByteArrayOutputStream();
383 | bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
384 | return stream.toByteArray();
385 | }
386 |
387 | private static Bitmap rotate(Bitmap source, int orientation) {
388 | Matrix matrix = new Matrix();
389 | matrix.postRotate((float) orientation);
390 | return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, false);
391 | }
392 |
393 | private File thumbnailPathFromMediaId(String mediaId) {
394 | File thumbnailPath = null;
395 |
396 | String thumbnailName = mediaId + "_mthumb.png";
397 | File dir = new File(this.getContext().getApplicationInfo().dataDir, DIR_NAME);
398 | if (!dir.exists()) {
399 | if (!dir.mkdirs()) {
400 | Log.e("Mendr", "Failed to create storage directory.");
401 | return thumbnailPath;
402 | }
403 | }
404 |
405 | thumbnailPath = new File(dir.getPath() + File.separator + thumbnailName);
406 |
407 | return thumbnailPath;
408 | }
409 |
410 | private File imagePathFromMediaId(String mediaId) {
411 | File imagePath = null;
412 |
413 | File rootDir = new File(this.getContext().getApplicationInfo().dataDir, DIR_NAME);
414 | File dir = new File(rootDir, SUB_DIR_NAME);
415 |
416 | //check if root directory exist
417 | if (rootDir.exists()) {
418 | //root directory exists
419 | if (dir.exists()) {
420 | //dir exists so deleting it
421 | deleteRecursive(dir);
422 | }
423 |
424 | if (!dir.mkdirs()) {
425 | Log.e("Mendr", "Failed to create hq storage directory.");
426 | return imagePath;
427 | } else {
428 | //dir created successfully
429 | }
430 | } else {
431 | //root directory doesn't exist
432 | //trying to create root directory
433 | if (!rootDir.mkdirs()) {
434 | Log.e("Mendr", "Failed to create root storage directory.");
435 | return imagePath;
436 | } else {
437 | //root dir created successfully
438 | if (!dir.mkdirs()) {
439 | Log.e("Mendr", "Failed to create hq storage directory.");
440 | return imagePath;
441 | } else {
442 | //dir created successfully
443 | }
444 | }
445 | }
446 |
447 | String imageName = mediaId + ".png";
448 | imagePath = new File(dir.getPath() + File.separator + imageName);
449 |
450 | return imagePath;
451 | }
452 |
453 | void deleteRecursive(File fileOrDirectory) {
454 | if (fileOrDirectory.isDirectory())
455 | for (File child : fileOrDirectory.listFiles())
456 | deleteRecursive(child);
457 |
458 | fileOrDirectory.delete();
459 | }
460 |
461 | private Context getContext() {
462 | return this.cordova.getActivity().getApplicationContext();
463 | }
464 |
465 | private ArrayOfObjects queryContentProvider(Uri collection, Object columns, String whereClause) throws JSONException {
466 | final ArrayList columnNames = new ArrayList();
467 | final ArrayList columnValues = new ArrayList();
468 |
469 | Iterator iteratorFields = columns.keys();
470 |
471 | while (iteratorFields.hasNext()) {
472 | String column = iteratorFields.next();
473 |
474 | columnNames.add(column);
475 | columnValues.add("" + columns.getString(column));
476 | }
477 |
478 | final Cursor cursor = getContext().getContentResolver().query(collection, columnValues.toArray(new String[columns.length()]), whereClause, null, null);
479 | final ArrayOfObjects buffer = new ArrayOfObjects();
480 |
481 | if (cursor.moveToFirst()) {
482 | do {
483 | Object item = new Object();
484 |
485 | for (String column : columnNames) {
486 | int columnIndex = cursor.getColumnIndex(columns.get(column).toString());
487 |
488 | if (column.startsWith("int.")) {
489 | item.put(column.substring(4), cursor.getInt(columnIndex));
490 | if (column.substring(4).equals("width") && item.getInt("width") == 0) {
491 | System.err.println("cursor: " + cursor.getInt(columnIndex));
492 |
493 | }
494 | } else if (column.startsWith("float.")) {
495 | item.put(column.substring(6), cursor.getFloat(columnIndex));
496 | } else {
497 | item.put(column, cursor.getString(columnIndex));
498 | }
499 | }
500 |
501 | buffer.add(item);
502 | }
503 | while (cursor.moveToNext());
504 | }
505 |
506 | cursor.close();
507 |
508 | return buffer;
509 | }
510 |
511 | private class Object extends JSONObject {
512 |
513 | }
514 |
515 | private class ArrayOfObjects extends ArrayList