runs in android now but doesn't work yet
2
.gitignore
vendored
@ -11,4 +11,4 @@
|
||||
# Xcode 4
|
||||
xcuserdata/
|
||||
project.xcworkspace/
|
||||
|
||||
tags
|
||||
|
47
plugin.xml
@ -56,5 +56,52 @@
|
||||
|
||||
<!-- android -->
|
||||
<platform name="android">
|
||||
<config-file target="config.xml" parent="/*">
|
||||
<feature name="ImagePicker">
|
||||
<param name="android-package" value="com.synconset.ImagePicker"/>
|
||||
</feature>
|
||||
</config-file>
|
||||
|
||||
<config-file target="AndroidManifest.xml" parent="/manifest/application">
|
||||
<activity android:label="@string/multi_app_name" android:name="com.synconset.MultiImageChooserActivity">
|
||||
<intent-filter>
|
||||
<action android:name="com.synconset.imagepicker.PICK" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</config-file>
|
||||
|
||||
<source-file src="src/Android/com/synconset/ImagePicker/ImagePicker.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"/>
|
||||
|
||||
<source-file src="src/android/Library/res/anim/image_pop_in.xml" target-dir="res/anim"/>
|
||||
<source-file src="src/android/Library/res/drawable/grid_background.xml" target-dir="res/drawable"/>
|
||||
<source-file src="src/android/Library/res/drawable-hdpi/image_bg.9.png" target-dir="res/drawable-hdpi"/>
|
||||
<source-file src="src/android/Library/res/drawable-hdpi/loading_icon.png" target-dir="res/drawable-hdpi"/>
|
||||
<source-file src="src/android/Library/res/drawable-mdpi/ic_action_discard_dark.png" target-dir="res/drawable-mdpi"/>
|
||||
<source-file src="src/android/Library/res/drawable-mdpi/ic_action_discard_light.png" target-dir="res/drawable-mdpi"/>
|
||||
<source-file src="src/android/Library/res/drawable-mdpi/ic_action_done_dark.png" target-dir="res/drawable-mdpi"/>
|
||||
<source-file src="src/android/Library/res/drawable-mdpi/ic_action_done_light.png" target-dir="res/drawable-mdpi"/>
|
||||
<source-file src="src/android/Library/res/drawable-mdpi/ic_launcher.png" target-dir="res/drawable-mdpi"/>
|
||||
<source-file src="src/android/Library/res/drawable-xhdpi/ic_action_discard_dark.png" target-dir="res/drawable-xhdpi"/>
|
||||
<source-file src="src/android/Library/res/drawable-xhdpi/ic_action_discard_light.png" target-dir="res/drawable-xhdpi"/>
|
||||
<source-file src="src/android/Library/res/drawable-xhdpi/ic_action_done_dark.png" target-dir="res/drawable-xhdpi"/>
|
||||
<source-file src="src/android/Library/res/drawable-xhdpi/ic_action_done_light.png" target-dir="res/drawable-xhdpi"/>
|
||||
<source-file src="src/android/Library/res/drawable-xhdpi/ic_launcher.png" target-dir="res/drawable-xhdpi"/>
|
||||
<source-file src="src/android/Library/res/layout/actionbar_custom_view_done_discard.xml" target-dir="res/layout"/>
|
||||
<source-file src="src/android/Library/res/layout/actionbar_discard_button.xml" target-dir="res/layout"/>
|
||||
<source-file src="src/android/Library/res/layout/actionbar_done_button.xml" target-dir="res/layout"/>
|
||||
<source-file src="src/android/Library/res/layout/multiselectorgrid.xml" target-dir="res/layout"/>
|
||||
<source-file src="src/android/Library/res/values/multiimagechooser_strings_en.xml" target-dir="res/values"/>
|
||||
<source-file src="src/android/Library/res/values/themes.xml" target-dir="res/values"/>
|
||||
|
||||
<source-file src="src/android/Library/res/values-de/multiimagechooser_strings_de.xml" target-dir="res/values-de"/>
|
||||
<source-file src="src/android/Library/res/values-es/multiimagechooser_strings_es.xml" target-dir="res/values-es"/>
|
||||
<source-file src="src/android/Library/res/values-fr/multiimagechooser_strings_fr.xml" target-dir="res/values-fr"/>
|
||||
<source-file src="src/android/Library/res/values-hu/multiimagechooser_strings_hu.xml" target-dir="res/values-hu"/>
|
||||
<source-file src="src/android/Library/res/values-ja/multiimagechooser_strings_ja.xml" target-dir="res/values-ja"/>
|
||||
<source-file src="src/android/Library/res/values-ko/multiimagechooser_strings_ko.xml" target-dir="res/values-ko"/>
|
||||
</platform>
|
||||
</plugin>
|
||||
|
11
src/Android/Library/res/anim/image_pop_in.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<scale xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="100"
|
||||
android:fillAfter="false"
|
||||
android:fromXScale="0.5"
|
||||
android:fromYScale="0.5"
|
||||
android:interpolator="@android:anim/overshoot_interpolator"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:toXScale="1"
|
||||
android:toYScale="1" />
|
BIN
src/Android/Library/res/drawable-hdpi/icon.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
src/Android/Library/res/drawable-hdpi/image_bg.9.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
src/Android/Library/res/drawable-hdpi/loading_icon.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
src/Android/Library/res/drawable-ldpi/icon.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
src/Android/Library/res/drawable-mdpi/ic_action_discard_dark.png
Normal file
After Width: | Height: | Size: 415 B |
After Width: | Height: | Size: 386 B |
BIN
src/Android/Library/res/drawable-mdpi/ic_action_done_dark.png
Normal file
After Width: | Height: | Size: 454 B |
BIN
src/Android/Library/res/drawable-mdpi/ic_action_done_light.png
Normal file
After Width: | Height: | Size: 400 B |
BIN
src/Android/Library/res/drawable-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
src/Android/Library/res/drawable-mdpi/icon.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 724 B |
After Width: | Height: | Size: 684 B |
BIN
src/Android/Library/res/drawable-xhdpi/ic_action_done_dark.png
Normal file
After Width: | Height: | Size: 825 B |
BIN
src/Android/Library/res/drawable-xhdpi/ic_action_done_light.png
Normal file
After Width: | Height: | Size: 759 B |
BIN
src/Android/Library/res/drawable-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
12
src/Android/Library/res/drawable/grid_background.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle" >
|
||||
<gradient
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:angle="90"
|
||||
android:centerX="0"
|
||||
android:centerY="0"
|
||||
android:startColor="#FF000000"
|
||||
android:endColor="#FF8E8E8E"
|
||||
android:type="linear" />
|
||||
</shape>
|
@ -0,0 +1,27 @@
|
||||
<!--
|
||||
Copyright 2012 Roman Nurik
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:divider="?android:attr/dividerVertical"
|
||||
android:showDividers="middle"
|
||||
android:dividerPadding="12dp">
|
||||
|
||||
<include layout="@layout/actionbar_discard_button" />
|
||||
<include layout="@layout/actionbar_done_button" />
|
||||
</LinearLayout>
|
33
src/Android/Library/res/layout/actionbar_discard_button.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<!--
|
||||
Copyright 2012 Roman Nurik
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/actionbar_discard"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
style="?android:actionButtonStyle" >
|
||||
<TextView
|
||||
android:drawableLeft="@drawable/ic_action_discard_dark"
|
||||
android:drawablePadding="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:id="@+id/actionbar_discard_textview"
|
||||
android:layout_gravity="center"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:paddingRight="20dp"
|
||||
android:text="@string/discard"
|
||||
style="?android:actionBarTabTextStyle" />
|
||||
</FrameLayout>
|
34
src/Android/Library/res/layout/actionbar_done_button.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<!--
|
||||
Copyright 2012 Roman Nurik
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="?android:actionButtonStyle"
|
||||
android:id="@+id/actionbar_done"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1">
|
||||
|
||||
<TextView style="?android:actionBarTabTextStyle"
|
||||
android:id="@+id/actionbar_done_textview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:paddingRight="20dp"
|
||||
android:drawableLeft="@drawable/ic_action_done_dark"
|
||||
android:drawablePadding="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/done" />
|
||||
</FrameLayout>
|
33
src/Android/Library/res/layout/multiselectorgrid.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_width="fill_parent"
|
||||
android:orientation="vertical" > <!-- android:background="@drawable/image_bg" -->
|
||||
<TextView
|
||||
android:gravity="center"
|
||||
android:id="@+id/label_images_left"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:layout_width="fill_parent"
|
||||
android:paddingBottom="2dip"
|
||||
android:paddingTop="2dip"
|
||||
android:text=""
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone" />
|
||||
<GridView
|
||||
android:fadingEdgeLength="10dip"
|
||||
android:requiresFadingEdge="vertical"
|
||||
android:columnWidth="0dip"
|
||||
android:fastScrollEnabled="true"
|
||||
android:gravity="center"
|
||||
android:horizontalSpacing="8dip"
|
||||
android:id="@+id/gridview"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="fill_parent"
|
||||
android:numColumns="auto_fit"
|
||||
android:scrollingCache="true"
|
||||
android:stretchMode="columnWidth"
|
||||
android:verticalSpacing="8dip" />
|
||||
</LinearLayout>
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="multi_app_name">MultiImageChooser</string>
|
||||
<string name="free_version_label">Free version - Images left: %d</string>
|
||||
<string name="error_database">There was an error opening the images database. Please report the problem.</string>
|
||||
<string name="requesting_thumbnails">Requesting thumbnails, please be patient</string>
|
||||
</resources>
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="multi_app_name">MultiImageChooser</string>
|
||||
<string name="requesting_thumbnails">Solicitando miniaturas. Por favor, espere…</string>
|
||||
<string name="free_version_label">Versión gratuita - Imágenes restantes: %d</string>
|
||||
<string name="error_database">Error al abrir la base de datos de imágenes.</string>
|
||||
</resources>
|
@ -0,0 +1,6 @@
|
||||
<resources>
|
||||
<string name="multi_app_name">"MultiImageChooser"</string>
|
||||
<string name="free_version_label">"La version gratuite - gauche Images:%d"</string>
|
||||
<string name="error_database">"Il y avait une erreur d'ouvrir la base de données images. S'il vous plaît signaler le problème."</string>
|
||||
<string name="requesting_thumbnails">"Demande de vignettes, s'il vous plaît soyez patient"</string>
|
||||
</resources>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="multi_app_name">MultiImageChooser</string>
|
||||
|
||||
<string name="free_version_label">Ingyenes verzió - hátralévő képek: %d</string>
|
||||
<string name="error_database">Képadatbázis megnyitási hiba történt. Kérjük, jelentse a problémát.</string>
|
||||
<string name="requesting_thumbnails">Miniatűrök lekérése, kérjük legyen türelemmel</string>
|
||||
</resources>
|
@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<resources>
|
||||
<string name="multi_app_name">MultiImageChooser</string>
|
||||
<string name="free_version_label">無料版 - 残りの画像: %d</string>
|
||||
<string name="error_database">画像データベースを開く際にエラーがありました。問題を報告してください。</string>
|
||||
<string name="requesting_thumbnails">サムネイルをリクエスト中です。お待ちください。</string>
|
||||
</resources>
|
@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<resources>
|
||||
<string name="multi_app_name">MultiImageChooser</string>
|
||||
<string name="free_version_label">무료 버전 - 남은 이미지: %d</string>
|
||||
<string name="error_database">이미지 데이터베이스를 여는 데 오류가 발생했습니다. 문제를 보고하세요.</string>
|
||||
<string name="requesting_thumbnails">썸네일 요청 중. 기다려주세요</string>
|
||||
</resources>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="multi_app_name">MultiImageChooser</string>
|
||||
<string name="free_version_label">Free version - Images left: %d</string>
|
||||
<string name="error_database">There was an error opening the images database. Please report the problem.</string>
|
||||
<string name="requesting_thumbnails">Requesting thumbnails, please be patient</string>
|
||||
<string name="discard">Cancel</string>
|
||||
<string name="done">OK</string>
|
||||
</resources>
|
5
src/Android/Library/res/values/themes.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="MyTheme" parent="android:Theme.Holo.Light">
|
||||
</style>
|
||||
</resources>
|
368
src/Android/Library/src/ImageFetcher.java
Normal file
@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.synconset;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.ImageView;
|
||||
|
||||
/**
|
||||
* This helper class download images from the Internet and binds those with the
|
||||
* provided ImageView.
|
||||
*
|
||||
* <p>
|
||||
* It requires the INTERNET permission, which should be added to your
|
||||
* application's manifest file.
|
||||
* </p>
|
||||
*
|
||||
* A local cache of downloaded images is maintained internally to improve
|
||||
* performance.
|
||||
*/
|
||||
public class ImageFetcher {
|
||||
|
||||
private int colWidth;
|
||||
private long origId;
|
||||
private ExecutorService executor;
|
||||
|
||||
public ImageFetcher() {
|
||||
executor = Executors.newCachedThreadPool();
|
||||
}
|
||||
|
||||
public void fetch(Integer id, ImageView imageView, int colWidth) {
|
||||
resetPurgeTimer();
|
||||
this.colWidth = colWidth;
|
||||
this.origId = id;
|
||||
Bitmap bitmap = getBitmapFromCache(id);
|
||||
|
||||
if (bitmap == null) {
|
||||
forceDownload(id, imageView);
|
||||
} else {
|
||||
cancelPotentialDownload(id, imageView);
|
||||
imageView.setImageBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as download but the image is always downloaded and the cache is not
|
||||
* used. Kept private at the moment as its interest is not clear.
|
||||
*/
|
||||
private void forceDownload(Integer position, ImageView imageView) {
|
||||
if (position == null) {
|
||||
imageView.setImageDrawable(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cancelPotentialDownload(position, imageView)) {
|
||||
BitmapFetcherTask task = new BitmapFetcherTask(imageView.getContext(), imageView);
|
||||
DownloadedDrawable downloadedDrawable = new DownloadedDrawable(imageView.getContext(), task, origId);
|
||||
imageView.setImageDrawable(downloadedDrawable);
|
||||
imageView.setMinimumHeight(colWidth);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
task.executeOnExecutor(executor, position);
|
||||
} else {
|
||||
try {
|
||||
task.execute(position);
|
||||
} catch (RejectedExecutionException e) {
|
||||
// Oh :(
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current download has been canceled or if there was no
|
||||
* download in progress on this image view. Returns false if the download in
|
||||
* progress deals with the same url. The download is not stopped in that
|
||||
* case.
|
||||
*/
|
||||
private static boolean cancelPotentialDownload(Integer position, ImageView imageView) {
|
||||
BitmapFetcherTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
|
||||
long origId = getOrigId(imageView);
|
||||
|
||||
if (bitmapDownloaderTask != null) {
|
||||
Integer bitmapPosition = bitmapDownloaderTask.position;
|
||||
if ((bitmapPosition == null) || (!bitmapPosition.equals(position))) {
|
||||
Log.d("DAVID", "Canceling...");
|
||||
MediaStore.Images.Thumbnails.cancelThumbnailRequest(imageView.getContext().getContentResolver(),
|
||||
origId, 12345);
|
||||
bitmapDownloaderTask.cancel(true);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param imageView
|
||||
* Any imageView
|
||||
* @return Retrieve the currently active download task (if any) associated
|
||||
* with this imageView. null if there is no such task.
|
||||
*/
|
||||
private static BitmapFetcherTask getBitmapDownloaderTask(ImageView imageView) {
|
||||
if (imageView != null) {
|
||||
Drawable drawable = imageView.getDrawable();
|
||||
if (drawable instanceof DownloadedDrawable) {
|
||||
DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable;
|
||||
return downloadedDrawable.getBitmapDownloaderTask();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static long getOrigId(ImageView imageView) {
|
||||
if (imageView != null) {
|
||||
Drawable drawable = imageView.getDrawable();
|
||||
if (drawable instanceof DownloadedDrawable) {
|
||||
DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable;
|
||||
return downloadedDrawable.getOrigId();
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual AsyncTask that will asynchronously download the image.
|
||||
*/
|
||||
class BitmapFetcherTask extends AsyncTask<Integer, Void, Bitmap> {
|
||||
private Integer position;
|
||||
private final WeakReference<ImageView> imageViewReference;
|
||||
private final Context mContext;
|
||||
|
||||
public BitmapFetcherTask(Context context, ImageView imageView) {
|
||||
imageViewReference = new WeakReference<ImageView>(imageView);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actual download method.
|
||||
*/
|
||||
@Override
|
||||
protected Bitmap doInBackground(Integer... params) {
|
||||
position = params[0];
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
Bitmap thumb = MediaStore.Images.Thumbnails.getThumbnail(mContext.getContentResolver(), position, 12345,
|
||||
MediaStore.Images.Thumbnails.MICRO_KIND, null);
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
if (thumb == null) {
|
||||
return null;
|
||||
} else {
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
} else {
|
||||
return thumb;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setInvisible() {
|
||||
Log.d("COLLAGE", "Setting something invisible...");
|
||||
if (imageViewReference != null) {
|
||||
final ImageView imageView = imageViewReference.get();
|
||||
BitmapFetcherTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
|
||||
if (this == bitmapDownloaderTask) {
|
||||
imageView.setVisibility(View.GONE);
|
||||
imageView.setClickable(false);
|
||||
imageView.setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Once the image is downloaded, associates it to the imageView
|
||||
*/
|
||||
@Override
|
||||
protected void onPostExecute(Bitmap bitmap) {
|
||||
if (isCancelled()) {
|
||||
bitmap = null;
|
||||
}
|
||||
addBitmapToCache(position, bitmap);
|
||||
if (imageViewReference != null) {
|
||||
ImageView imageView = imageViewReference.get();
|
||||
BitmapFetcherTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
|
||||
if (this == bitmapDownloaderTask) {
|
||||
imageView.setImageBitmap(bitmap);
|
||||
Animation anim = AnimationUtils.loadAnimation(imageView.getContext(), android.R.anim.fade_in);
|
||||
imageView.setAnimation(anim);
|
||||
anim.start();
|
||||
}
|
||||
} else {
|
||||
setInvisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A fake Drawable that will be attached to the imageView while the download
|
||||
* is in progress.
|
||||
*
|
||||
* <p>
|
||||
* Contains a reference to the actual download task, so that a download task
|
||||
* can be stopped if a new binding is required, and makes sure that only the
|
||||
* last started download process can bind its result, independently of the
|
||||
* download finish order.
|
||||
* </p>
|
||||
*/
|
||||
static class DownloadedDrawable extends ColorDrawable {
|
||||
private final WeakReference<BitmapFetcherTask> bitmapDownloaderTaskReference;
|
||||
private long origId;
|
||||
|
||||
public DownloadedDrawable(Context mContext, BitmapFetcherTask bitmapDownloaderTask, long origId) {
|
||||
super(Color.TRANSPARENT);
|
||||
bitmapDownloaderTaskReference = new WeakReference<BitmapFetcherTask>(bitmapDownloaderTask);
|
||||
this.origId = origId;
|
||||
}
|
||||
|
||||
public long getOrigId() {
|
||||
return origId;
|
||||
}
|
||||
|
||||
public BitmapFetcherTask getBitmapDownloaderTask() {
|
||||
return bitmapDownloaderTaskReference.get();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Cache-related fields and methods.
|
||||
*
|
||||
* We use a hard and a soft cache. A soft reference cache is too aggressively cleared by the
|
||||
* Garbage Collector.
|
||||
*/
|
||||
|
||||
private static final int HARD_CACHE_CAPACITY = 100;
|
||||
private static final int DELAY_BEFORE_PURGE = 10 * 1000; // in milliseconds
|
||||
|
||||
// Hard cache, with a fixed maximum capacity and a life duration
|
||||
private final HashMap<Integer, Bitmap> sHardBitmapCache = new LinkedHashMap<Integer, Bitmap>(
|
||||
HARD_CACHE_CAPACITY / 2, 0.75f, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(LinkedHashMap.Entry<Integer, Bitmap> eldest) {
|
||||
if (size() > HARD_CACHE_CAPACITY) {
|
||||
// Entries push-out of hard reference cache are transferred to
|
||||
// soft reference cache
|
||||
sSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Soft cache for bitmaps kicked out of hard cache
|
||||
private final static ConcurrentHashMap<Integer, SoftReference<Bitmap>> sSoftBitmapCache = new ConcurrentHashMap<Integer, SoftReference<Bitmap>>(
|
||||
HARD_CACHE_CAPACITY / 2);
|
||||
|
||||
private final Handler purgeHandler = new Handler();
|
||||
|
||||
private final Runnable purger = new Runnable() {
|
||||
public void run() {
|
||||
clearCache();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds this bitmap to the cache.
|
||||
*
|
||||
* @param bitmap
|
||||
* The newly downloaded bitmap.
|
||||
*/
|
||||
private void addBitmapToCache(Integer position, Bitmap bitmap) {
|
||||
if (bitmap != null) {
|
||||
synchronized (sHardBitmapCache) {
|
||||
sHardBitmapCache.put(position, bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param position
|
||||
* The URL of the image that will be retrieved from the cache.
|
||||
* @return The cached bitmap or null if it was not found.
|
||||
*/
|
||||
private Bitmap getBitmapFromCache(Integer position) {
|
||||
// First try the hard reference cache
|
||||
synchronized (sHardBitmapCache) {
|
||||
final Bitmap bitmap = sHardBitmapCache.get(position);
|
||||
if (bitmap != null) {
|
||||
Log.d("CACHE ****** ", "Hard hit!");
|
||||
// Bitmap found in hard cache
|
||||
// Move element to first position, so that it is removed last
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
// Then try the soft reference cache
|
||||
SoftReference<Bitmap> bitmapReference = sSoftBitmapCache.get(position);
|
||||
if (bitmapReference != null) {
|
||||
final Bitmap bitmap = bitmapReference.get();
|
||||
if (bitmap != null) {
|
||||
// Bitmap found in soft cache
|
||||
Log.d("CACHE ****** ", "Soft hit!");
|
||||
return bitmap;
|
||||
} else {
|
||||
// Soft reference has been Garbage Collected
|
||||
sSoftBitmapCache.remove(position);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the image cache used internally to improve performance. Note that
|
||||
* for memory efficiency reasons, the cache will automatically be cleared
|
||||
* after a certain inactivity delay.
|
||||
*/
|
||||
public void clearCache() {
|
||||
// sHardBitmapCache.clear();
|
||||
// sSoftBitmapCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow a new delay before the automatic cache clear is done.
|
||||
*/
|
||||
private void resetPurgeTimer() {
|
||||
// purgeHandler.removeCallbacks(purger);
|
||||
// purgeHandler.postDelayed(purger, DELAY_BEFORE_PURGE);
|
||||
}
|
||||
}
|
395
src/Android/Library/src/MultiImageChooserActivity.java
Normal file
@ -0,0 +1,395 @@
|
||||
package com.synconset;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.wymsee.apps.synconset.R;
|
||||
import android.app.Activity;
|
||||
import android.app.ActionBar;
|
||||
import android.app.LoaderManager;
|
||||
import android.content.Context;
|
||||
import android.content.CursorLoader;
|
||||
import android.content.Intent;
|
||||
import android.content.Loader;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.Display;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.AbsListView.OnScrollListener;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class MultiImageChooserActivity extends Activity implements OnItemClickListener,
|
||||
LoaderManager.LoaderCallbacks<Cursor> {
|
||||
private static final String TAG = "Collage";
|
||||
public static final String COL_WIDTH_KEY = "COL_WIDTH";
|
||||
public static final String FLURRY_EVENT_ADD_MULTIPLE_IMAGES = "Add multiple images";
|
||||
|
||||
// El tamaño por defecto es 100 porque los thumbnails MICRO_KIND son de
|
||||
// 96x96
|
||||
private static final int DEFAULT_COLUMN_WIDTH = 120;
|
||||
|
||||
public static final int NOLIMIT = -1;
|
||||
public static final String MAX_IMAGES_KEY = "MAX_IMAGES";
|
||||
|
||||
private ImageAdapter ia;
|
||||
|
||||
private Cursor imagecursor, actualimagecursor;
|
||||
private int image_column_index, actual_image_column_index;
|
||||
private int colWidth;
|
||||
|
||||
private static final int CURSORLOADER_THUMBS = 0;
|
||||
private static final int CURSORLOADER_REAL = 1;
|
||||
|
||||
private Set<String> fileNames = new HashSet<String>();
|
||||
|
||||
private SparseBooleanArray checkStatus = new SparseBooleanArray();
|
||||
|
||||
private TextView freeLabel = null;
|
||||
private int maxImages;
|
||||
private boolean unlimitedImages = false;
|
||||
|
||||
private GridView gridView;
|
||||
|
||||
private final ImageFetcher fetcher = new ImageFetcher();
|
||||
|
||||
private int selectedColor = Color.GREEN;
|
||||
private boolean shouldRequestThumb = true;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.multiselectorgrid);
|
||||
fileNames.clear();
|
||||
|
||||
maxImages = getIntent().getIntExtra(MAX_IMAGES_KEY, NOLIMIT);
|
||||
|
||||
unlimitedImages = maxImages == NOLIMIT;
|
||||
if (!unlimitedImages) {
|
||||
freeLabel = (TextView) findViewById(R.id.label_images_left);
|
||||
freeLabel.setVisibility(View.VISIBLE);
|
||||
updateLabel();
|
||||
}
|
||||
|
||||
colWidth = getIntent().getIntExtra(COL_WIDTH_KEY, DEFAULT_COLUMN_WIDTH);
|
||||
|
||||
Display display = getWindowManager().getDefaultDisplay();
|
||||
@SuppressWarnings("deprecation")
|
||||
int width = display.getWidth();
|
||||
int testColWidth = width / 3;
|
||||
|
||||
if (testColWidth > colWidth) {
|
||||
colWidth = width / 4;
|
||||
}
|
||||
|
||||
// int bgColor = getIntent().getIntExtra("BG_COLOR", Color.BLACK);
|
||||
|
||||
gridView = (GridView) findViewById(R.id.gridview);
|
||||
gridView.setColumnWidth(colWidth);
|
||||
gridView.setOnItemClickListener(this);
|
||||
gridView.setOnScrollListener(new OnScrollListener() {
|
||||
|
||||
private int lastFirstItem = 0;
|
||||
private long timestamp = System.currentTimeMillis();
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(AbsListView view, int scrollState) {
|
||||
if (scrollState == SCROLL_STATE_IDLE) {
|
||||
Log.d(TAG, "IDLE - Reload!");
|
||||
shouldRequestThumb = true;
|
||||
ia.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||
float dt = System.currentTimeMillis() - timestamp;
|
||||
if (firstVisibleItem != lastFirstItem) {
|
||||
double speed = 1 / dt * 1000;
|
||||
lastFirstItem = firstVisibleItem;
|
||||
timestamp = System.currentTimeMillis();
|
||||
Log.d(TAG, "Speed: " + speed + " elements/second");
|
||||
|
||||
// Limitarlo si vamos a más de una página por segundo...
|
||||
shouldRequestThumb = speed < visibleItemCount;
|
||||
}
|
||||
}
|
||||
});
|
||||
selectedColor = 0xff32b2e1;
|
||||
// selectedColor = Color.RED;
|
||||
|
||||
// gridView.setBackgroundColor(bgColor);
|
||||
// gridView.setBackgroundResource(R.drawable.grid_background);
|
||||
|
||||
ia = new ImageAdapter(this);
|
||||
gridView.setAdapter(ia);
|
||||
|
||||
LoaderManager.enableDebugLogging(false);
|
||||
getLoaderManager().initLoader(CURSORLOADER_THUMBS, null, this);
|
||||
getLoaderManager().initLoader(CURSORLOADER_REAL, null, this);
|
||||
setupHeader();
|
||||
updateAcceptButton();
|
||||
}
|
||||
|
||||
private void setupHeader() {
|
||||
// From Roman Nurik's code
|
||||
// https://plus.google.com/113735310430199015092/posts/R49wVvcDoEW
|
||||
// Inflate a "Done/Discard" custom action bar view.
|
||||
LayoutInflater inflater = (LayoutInflater) getActionBar().getThemedContext().getSystemService(
|
||||
LAYOUT_INFLATER_SERVICE);
|
||||
final View customActionBarView = inflater.inflate(R.layout.actionbar_custom_view_done_discard, null);
|
||||
customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// "Done"
|
||||
selectClicked(null);
|
||||
}
|
||||
});
|
||||
customActionBarView.findViewById(R.id.actionbar_discard).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
|
||||
// Show the custom action bar view and hide the normal Home icon and
|
||||
// title.
|
||||
final ActionBar actionBar = getActionBar();
|
||||
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM
|
||||
| ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);
|
||||
actionBar.setCustomView(customActionBarView, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
}
|
||||
|
||||
private void updateLabel() {
|
||||
if (freeLabel != null) {
|
||||
String text = String.format(getString(R.string.free_version_label), maxImages);
|
||||
freeLabel.setText(text);
|
||||
if (maxImages == 0) {
|
||||
freeLabel.setTextColor(Color.RED);
|
||||
} else {
|
||||
freeLabel.setTextColor(Color.WHITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ImageAdapter extends BaseAdapter {
|
||||
private final Bitmap mPlaceHolderBitmap;
|
||||
|
||||
public ImageAdapter(Context c) {
|
||||
Bitmap tmpHolderBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.loading_icon);
|
||||
mPlaceHolderBitmap = Bitmap.createScaledBitmap(tmpHolderBitmap, colWidth, colWidth, false);
|
||||
if (tmpHolderBitmap != mPlaceHolderBitmap) {
|
||||
tmpHolderBitmap.recycle();
|
||||
tmpHolderBitmap = null;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
if (imagecursor != null) {
|
||||
return imagecursor.getCount();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public Object getItem(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
// create a new ImageView for each item referenced by the Adapter
|
||||
public View getView(int pos, View convertView, ViewGroup parent) {
|
||||
|
||||
if (convertView == null) {
|
||||
convertView = new ImageView(MultiImageChooserActivity.this);
|
||||
}
|
||||
|
||||
ImageView imageView = (ImageView) convertView;
|
||||
imageView.setImageBitmap(null);
|
||||
|
||||
final int position = pos;
|
||||
|
||||
if (!imagecursor.moveToPosition(position)) {
|
||||
return imageView;
|
||||
}
|
||||
|
||||
if (image_column_index == -1) {
|
||||
return imageView;
|
||||
}
|
||||
|
||||
final int id = imagecursor.getInt(image_column_index);
|
||||
if (isChecked(pos)) {
|
||||
imageView.setBackgroundColor(selectedColor);
|
||||
} else {
|
||||
imageView.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
if (shouldRequestThumb) {
|
||||
fetcher.fetch(Integer.valueOf(id), imageView, colWidth);
|
||||
}
|
||||
|
||||
return imageView;
|
||||
}
|
||||
}
|
||||
|
||||
private String getImageName(int position) {
|
||||
actualimagecursor.moveToPosition(position);
|
||||
String name = null;
|
||||
|
||||
try {
|
||||
name = actualimagecursor.getString(actual_image_column_index);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private void setChecked(int position, boolean b) {
|
||||
checkStatus.put(position, b);
|
||||
}
|
||||
|
||||
public boolean isChecked(int position) {
|
||||
boolean ret = checkStatus.get(position);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void cancelClicked(View ignored) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
}
|
||||
|
||||
public void selectClicked(View ignored) {
|
||||
Intent data = new Intent();
|
||||
if (fileNames.isEmpty()) {
|
||||
this.setResult(RESULT_CANCELED);
|
||||
} else {
|
||||
|
||||
ArrayList<String> al = new ArrayList<String>();
|
||||
al.addAll(fileNames);
|
||||
Bundle res = new Bundle();
|
||||
res.putStringArrayList("MULTIPLEFILENAMES", al);
|
||||
if (imagecursor != null) {
|
||||
res.putInt("TOTALFILES", imagecursor.getCount());
|
||||
}
|
||||
|
||||
data.putExtras(res);
|
||||
this.setResult(RESULT_OK, data);
|
||||
}
|
||||
Log.d(TAG, "Returning " + fileNames.size() + " items");
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> arg0, View view, int position, long id) {
|
||||
String name = getImageName(position);
|
||||
|
||||
if (name == null) {
|
||||
return;
|
||||
}
|
||||
boolean isChecked = !isChecked(position);
|
||||
// PhotoMix.Log("DAVID", "Posicion " + position + " isChecked: " +
|
||||
// isChecked);
|
||||
if (!unlimitedImages && maxImages == 0 && isChecked) {
|
||||
// PhotoMix.Log("DAVID", "Aquí no debería entrar...");
|
||||
isChecked = false;
|
||||
}
|
||||
|
||||
if (isChecked) {
|
||||
// Solo se resta un slot si hemos introducido un
|
||||
// filename de verdad...
|
||||
if (fileNames.add(name)) {
|
||||
maxImages--;
|
||||
view.setBackgroundColor(selectedColor);
|
||||
}
|
||||
} else {
|
||||
if (fileNames.remove(name)) {
|
||||
// Solo incrementa los slots libres si hemos
|
||||
// "liberado" uno...
|
||||
maxImages++;
|
||||
view.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
setChecked(position, isChecked);
|
||||
updateAcceptButton();
|
||||
updateLabel();
|
||||
|
||||
}
|
||||
|
||||
private void updateAcceptButton() {
|
||||
((TextView) getActionBar().getCustomView().findViewById(R.id.actionbar_done_textview))
|
||||
.setEnabled(fileNames.size() != 0);
|
||||
getActionBar().getCustomView().findViewById(R.id.actionbar_done).setEnabled(fileNames.size() != 0);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int cursorID, Bundle arg1) {
|
||||
CursorLoader cl = null;
|
||||
|
||||
ArrayList<String> img = new ArrayList<String>();
|
||||
switch (cursorID) {
|
||||
|
||||
case CURSORLOADER_THUMBS:
|
||||
img.add(MediaStore.Images.Media._ID);
|
||||
break;
|
||||
case CURSORLOADER_REAL:
|
||||
img.add(MediaStore.Images.Thumbnails.DATA);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cl = new CursorLoader(MultiImageChooserActivity.this, MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
||||
img.toArray(new String[img.size()]), null, null, null);
|
||||
return cl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||
if (cursor == null) {
|
||||
// NULL cursor. This usually means there's no image database yet....
|
||||
return;
|
||||
}
|
||||
|
||||
switch (loader.getId()) {
|
||||
case CURSORLOADER_THUMBS:
|
||||
imagecursor = cursor;
|
||||
image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Media._ID);
|
||||
ia.notifyDataSetChanged();
|
||||
break;
|
||||
case CURSORLOADER_REAL:
|
||||
actualimagecursor = cursor;
|
||||
actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
if (loader.getId() == CURSORLOADER_THUMBS) {
|
||||
imagecursor = null;
|
||||
} else if (loader.getId() == CURSORLOADER_REAL) {
|
||||
actualimagecursor = null;
|
||||
}
|
||||
}
|
||||
}
|
44
src/Android/com/synconset/ImagePicker/ImagePicker.java
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* An Internal Storage Plugin for Cordova/PhoneGap.
|
||||
*/
|
||||
package com.synconset;
|
||||
|
||||
import org.apache.cordova.CallbackContext;
|
||||
import org.apache.cordova.CordovaPlugin;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
public class ImagePicker extends CordovaPlugin {
|
||||
|
||||
public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
|
||||
if (action.equals("getPictures")) {
|
||||
Intent intent = new Intent(cordova.getActivity(), MultiImageChooserActivity.class);
|
||||
intent.putExtra("MAX_IMAGES", 20);
|
||||
|
||||
if (this.cordova != null) {
|
||||
this.cordova.startActivityForResult((CordovaPlugin) this, intent, 0);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
Log.d("PLUGIN", "result code = " + resultCode);
|
||||
if (resultCode == 1 && data != null) {
|
||||
ArrayList<String> fileNames = data.getStringArrayListExtra("MULTIPLEFILNAMES");
|
||||
for (int i = 0; i < fileNames.size(); i++) {
|
||||
Log.d("PLUGIN", fileNames.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|