Repository: ValuesFeng/AndroidPicturePicker
Branch: master
Commit: 56144fcb4db6
Files: 70
Total size: 127.1 KB
Directory structure:
gitextract_fhdrwt_g/
├── .gitignore
├── README.md
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── io/
│ │ └── valuesfeng/
│ │ └── demo/
│ │ ├── MainActivity.java
│ │ └── MainApp.java
│ └── res/
│ ├── layout/
│ │ └── activity_main.xml
│ ├── menu/
│ │ └── menu_main.xml
│ ├── values/
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── values-w820dp/
│ └── dimens.xml
├── build.gradle
├── gallery/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── io/
│ │ └── valuesfeng/
│ │ └── picker/
│ │ ├── ImageSelectActivity.java
│ │ ├── MimeType.java
│ │ ├── Picker.java
│ │ ├── adapter/
│ │ │ ├── AlbumAdapter.java
│ │ │ └── PictureAdapter.java
│ │ ├── control/
│ │ │ ├── AlbumCollection.java
│ │ │ ├── PictureCollection.java
│ │ │ └── SelectedUriCollection.java
│ │ ├── engine/
│ │ │ ├── GlideEngine.java
│ │ │ ├── ImageLoaderEngine.java
│ │ │ ├── LoadEngine.java
│ │ │ └── PicassoEngine.java
│ │ ├── loader/
│ │ │ ├── AlbumLoader.java
│ │ │ └── PictureLoader.java
│ │ ├── model/
│ │ │ ├── Album.java
│ │ │ ├── Picture.java
│ │ │ └── SelectionSpec.java
│ │ ├── utils/
│ │ │ ├── BundleUtils.java
│ │ │ ├── CloseableUtils.java
│ │ │ ├── ExifInterfaceCompat.java
│ │ │ ├── HandlerUtils.java
│ │ │ ├── MediaStoreCompat.java
│ │ │ ├── ParcelUtils.java
│ │ │ ├── PhotoMetadataUtils.java
│ │ │ └── PicturePickerUtils.java
│ │ └── widget/
│ │ └── GridViewItemRelativeLayout.java
│ └── res/
│ ├── anim/
│ │ ├── listview_down.xml
│ │ ├── listview_fade_in.xml
│ │ ├── listview_fade_out.xml
│ │ └── listview_up.xml
│ ├── drawable/
│ │ └── pick_photo_checkbox.xml
│ ├── layout/
│ │ ├── activity_image_select.xml
│ │ ├── activity_main.xml
│ │ ├── include_select_image_top.xml
│ │ ├── photopick_gridlist_item.xml
│ │ └── photopick_list_item.xml
│ ├── menu/
│ │ └── menu_main.xml
│ ├── values/
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── values-en/
│ │ └── strings.xml
│ ├── values-ja/
│ │ └── strings.xml
│ ├── values-pt/
│ │ └── strings.xml
│ └── values-w820dp/
│ └── dimens.xml
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
#built application files
*.apk
*.ap_
# files for the dex VM
*.dex
# Java class files
*.class
# generated files
bin/
gen/
# Local configuration file (sdk path, etc)
local.properties
# Windows thumbnail db
Thumbs.db
# OSX files
.DS_Store
# Eclipse project files
.classpath
.project
# Android Studio
.idea
#.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
.gradle
build/
/*/out
/*/build
/*/*/build
/*/*/production
*.iws
*.ipr
*~
*.swp
*.iml
# gradle.properties
app/mapping.txt
proguard/lib/proguard.jar
================================================
FILE: README.md
================================================
# AndroidPicturePicker
##Thanks for :
[Laevatein](https://github.com/nohana/Laevatein):Photo image selection activity set library. Currently under development.
[Picasso](https://github.com/square/picasso):A powerful image downloading and caching library for Android
[Glide](https://github.com/bumptech/glide):An image loading and caching library for Android focused on smooth scrolling
[Android-Universal-Image-Loader](https://github.com/nostra13/Android-Universal-Image-Loader):Powerful and flexible library for loading, caching and displaying images on Android.
##Screen Shot


## Usage
Call photo image selection activity by the following code snipet.
```java
public void onClickButton(View view) {
Picker.from(this)
.count(3)
.enableCamera(true)
.setEngine(new GlideEngine())
.forResult(REQUEST_CODE_CHOOSE);
}
```
You can use different Image Loader, Picker provide 3 default Loader Engine:
1.GlideEngine
2.PicassoEngine
3.ImageLoaderEngine
or you can use custom engine , just like
```java
public static class CustomEngine implements LoadEngine {
@Override
public void displayImage(String path, ImageView imageView) {
Log.i("picture", path);
}
@Override
public void displayCameraItem(ImageView imageView) {
}
@Override
public void scrolling(GridView view) {
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
}
public CustomEngine() {
}
protected CustomEngine(Parcel in) {
}
public static final Creator<CustomEngine> CREATOR = new Creator<CustomEngine>() {
public CustomEngine createFromParcel(Parcel source) {
return new CustomEngine(source);
}
public CustomEngine[] newArray(int size) {
return new CustomEngine[size];
}
};
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_CHOOSE && resultCode == RESULT_OK) {
mSelected = PicturePickerUtils.obtainResult(data);
for (Uri u : mSelected) {
Log.i("picture", u.getPath());
}
}
}
```
Please note that LoadEngine is extends Parcelable.
##Download
Gradle
```gradle
repositories {
maven { url "https://jitpack.io" }
}
dependencies {
compile 'com.github.valuesfeng:androidpicturepicker:1.0.0'
}
```
##wait achieve
1. Iamge quality ([quality](https://github.com/ValuesFeng/AndroidPicturePicker/blob/master/gallery%2Fsrc%2Fmain%2Fjava%2Fio%2Fvaluesfeng%2Fpicker%2FPicker.java));
2. Select Type ([MimeType](https://github.com/ValuesFeng/AndroidPicturePicker/blob/master/gallery%2Fsrc%2Fmain%2Fjava%2Fio%2Fvaluesfeng%2Fpicker%2FMimeType.java));
help me……
##License
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.
================================================
FILE: app/.gitignore
================================================
/build
================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "io.valuesfeng.demo"
minSdkVersion 11
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
repositories {
flatDir {
dirs 'libs' //this way we can find the .aar file in libs folder
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.3'
compile 'com.github.bumptech.glide:glide:3.6.1'
compile 'com.squareup.picasso:picasso:2.5.2'
// compile(name: 'gallery-release', ext: 'aar')
compile project(':gallery')
}
================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:\DevelopmentTools\Android\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.valuesfeng.demo" >
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:name=".MainApp"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
================================================
FILE: app/src/main/java/io/valuesfeng/demo/MainActivity.java
================================================
package io.valuesfeng.demo;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
import java.util.List;
import io.valuesfeng.picker.MimeType;
import io.valuesfeng.picker.Picker;
import io.valuesfeng.picker.engine.LoadEngine;
import io.valuesfeng.picker.engine.GlideEngine;
import io.valuesfeng.picker.utils.PicturePickerUtils;
public class MainActivity extends FragmentActivity {
public static final int REQUEST_CODE_CHOOSE = 1;
private List<Uri> mSelected;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_CHOOSE && resultCode == RESULT_OK) {
mSelected = PicturePickerUtils.obtainResult(data);
for (Uri u : mSelected) {
Log.i("picture", u.getPath());
}
}
}
public void onClickButton(View view) {
Picker.from(this)
.count(3)
.enableCamera(true)
.setEngine(new GlideEngine())
// .setEngine(new PicassoEngine())
// .setEngine(new ImageLoaderEngine())
// .setEngine(new CustomEngine())
.forResult(REQUEST_CODE_CHOOSE);
}
static class CustomEngine implements LoadEngine {
@Override
public void displayImage(String path, ImageView imageView) {
Log.i("picture", path);
}
@Override
public void displayCameraItem(ImageView imageView) {
}
@Override
public void scrolling(GridView view) {
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
}
public CustomEngine() {
}
protected CustomEngine(Parcel in) {
}
public static final Creator<CustomEngine> CREATOR = new Creator<CustomEngine>() {
public CustomEngine createFromParcel(Parcel source) {
return new CustomEngine(source);
}
public CustomEngine[] newArray(int size) {
return new CustomEngine[size];
}
};
}
}
================================================
FILE: app/src/main/java/io/valuesfeng/demo/MainApp.java
================================================
package io.valuesfeng.demo;
import android.app.Application;
import android.graphics.Bitmap;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
/**
* Created by laputan on 15-6-8.
*/
public class MainApp extends Application {
@Override
public void onCreate() {
super.onCreate();
DisplayImageOptions userOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true).cacheOnDisk(true).
showImageForEmptyUri(R.drawable.image_not_exist).
showImageOnLoading(R.drawable.image_not_exist).
showImageOnFail(R.drawable.image_not_exist).
imageScaleType(ImageScaleType.EXACTLY).
bitmapConfig(Bitmap.Config.RGB_565).
considerExifParams(true)
.build();
ImageLoaderConfiguration config =
new ImageLoaderConfiguration
.Builder(getApplicationContext())
.diskCacheFileCount(200)
.threadPoolSize(Thread.NORM_PRIORITY)
// .denyCacheImageMultipleSizesInMemory()
// .memoryCacheSize(10 * 1024 * 1024)
.defaultDisplayImageOptions(userOptions)
.build();
ImageLoader.getInstance().init(config);
}
}
================================================
FILE: app/src/main/res/layout/activity_main.xml
================================================
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<Button
android:layout_marginTop="20dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="choose"
android:onClick="onClickButton"/>
</RelativeLayout>
================================================
FILE: app/src/main/res/menu/menu_main.xml
================================================
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="@+id/action_settings" android:title="@string/action_settings"
android:orderInCategory="100" app:showAsAction="never" />
</menu>
================================================
FILE: app/src/main/res/values/dimens.xml
================================================
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>
================================================
FILE: app/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">FotoplaceGallery</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
</resources>
================================================
FILE: app/src/main/res/values/styles.xml
================================================
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
================================================
FILE: app/src/main/res/values-w820dp/dimens.xml
================================================
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>
================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
================================================
FILE: gallery/.gitignore
================================================
/build
================================================
FILE: gallery/build.gradle
================================================
apply plugin: 'com.android.library'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
minSdkVersion 11
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'com.android.support:support-v4:23.1.1'
provided 'com.nostra13.universalimageloader:universal-image-loader:1.9.3'
provided 'com.squareup.picasso:picasso:2.5.2'
provided 'com.github.bumptech.glide:glide:3.6.1'
}
================================================
FILE: gallery/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:\DevelopmentTools\Android\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
================================================
FILE: gallery/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.valuesfeng.picker" >
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application android:allowBackup="true">
<activity android:name=".ImageSelectActivity"/>
</application>
</manifest>
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/ImageSelectActivity.java
================================================
package io.valuesfeng.picker;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Parcelable;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import io.valuesfeng.picker.control.PictureCollection;
import io.valuesfeng.picker.control.AlbumCollection;
import io.valuesfeng.picker.model.Album;
import io.valuesfeng.picker.control.SelectedUriCollection;
import io.valuesfeng.picker.model.SelectionSpec;
import io.valuesfeng.picker.utils.BundleUtils;
import io.valuesfeng.picker.utils.MediaStoreCompat;
public class ImageSelectActivity extends FragmentActivity implements AlbumCollection.OnDirectorySelectListener {
public static final String EXTRA_RESULT_SELECTION = BundleUtils.buildKey(ImageSelectActivity.class, "EXTRA_RESULT_SELECTION");
public static final String EXTRA_SELECTION_SPEC = BundleUtils.buildKey(ImageSelectActivity.class, "EXTRA_SELECTION_SPEC");
public static final String EXTRA_RESUME_LIST = BundleUtils.buildKey(ImageSelectActivity.class, "EXTRA_RESUME_LIST");
// public static final String EXTRA_ENGINE = BundleUtils.buildKey(ImageSelectActivity.class, "EXTRA_ENGINE");
public static final String STATE_CAPTURE_PHOTO_URI = BundleUtils.buildKey(ImageSelectActivity.class, "STATE_CAPTURE_PHOTO_URI");
private RelativeLayout rlTop;
private TextView mFoldName;
private View mListViewGroup;
private ListView mListView;
private GridView mGridView;
public static final int REQUEST_CODE_CAPTURE = 3;
private MediaStoreCompat mMediaStoreCompat;
private Button commit;
private ImageView galleryTip;
private SelectionSpec selectionSpec;
private ImageView btnBack;
private AlbumCollection albumCollection =new AlbumCollection();
private final PictureCollection mPhotoCollection = new PictureCollection();
private final SelectedUriCollection mCollection = new SelectedUriCollection(this);
private String mCapturePhotoUriHolder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_select);
mCapturePhotoUriHolder = savedInstanceState != null ? savedInstanceState.getString(STATE_CAPTURE_PHOTO_URI) : "";
selectionSpec = getIntent().getParcelableExtra(ImageSelectActivity.EXTRA_SELECTION_SPEC);
mMediaStoreCompat = new MediaStoreCompat(this, new Handler(Looper.getMainLooper()));
mCollection.onCreate(savedInstanceState);
mCollection.prepareSelectionSpec(selectionSpec);
mCollection.setDefaultSelection(getIntent().<Uri>getParcelableArrayListExtra(EXTRA_RESUME_LIST));
mCollection.setOnSelectionChange(new SelectedUriCollection.OnSelectionChange() {
@Override
public void onChange(int maxCount, int selectCount) {
commit.setText(getString(R.string.l_album_name_confirm) + "(" + selectCount+"/"+maxCount+")");
}
});
mGridView = (GridView) findViewById(R.id.gridView);
mListView = (ListView) findViewById(R.id.listView);
btnBack = (ImageView) findViewById(R.id.btn_back);
mListViewGroup = findViewById(R.id.listViewParent);
mListViewGroup.setOnClickListener(mOnClickFoldName);
mFoldName = (TextView) findViewById(R.id.foldName);
galleryTip = (ImageView) findViewById(R.id.gallery_tip);
LinearLayout selectFold = (LinearLayout) findViewById(R.id.selectFold);
commit = (Button) findViewById(R.id.commit);
commit.setText(getString(R.string.l_album_name_confirm) + "(0/" + selectionSpec.getMaxSelectable()+")");
if (selectionSpec.isSingleChoose()){
commit.setVisibility(View.GONE);
}
mFoldName.setText(R.string.l_album_name_all);
selectFold.setOnClickListener(mOnClickFoldName);
albumCollection.onCreate(ImageSelectActivity.this,this,selectionSpec,mListView);
albumCollection.loadAlbums();
mPhotoCollection.onCreate(ImageSelectActivity.this,mGridView,mCollection,selectionSpec);
mPhotoCollection.loadAllPhoto();
commit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mCollection.isEmpty()) {
Toast.makeText(getApplicationContext(), getString(R.string.l_album_name_unselected_picture) ,Toast.LENGTH_LONG).show();
}else{
setResult();
}
}
});
btnBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
if (selectionSpec.willStartCamera()) showCameraAction();
}
public void setResult() {
Intent intent = new Intent();
intent.putParcelableArrayListExtra(ImageSelectActivity.EXTRA_RESULT_SELECTION,
(ArrayList<? extends Parcelable>) mCollection.asList());
setResult(Activity.RESULT_OK, intent);
finish();
}
View.OnClickListener mOnClickFoldName = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListViewGroup.getVisibility() == View.VISIBLE) {
hideFolderList();
} else {
showFolderList();
}
}
};
@Override
protected void onSaveInstanceState(Bundle outState) {
mCollection.onSaveInstanceState(outState);
albumCollection.onSaveInstanceState(outState);
outState.putString(STATE_CAPTURE_PHOTO_URI, mCapturePhotoUriHolder);
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
albumCollection.onRestoreInstanceState(savedInstanceState);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_CAPTURE && resultCode == Activity.RESULT_OK) {
Uri captured = mMediaStoreCompat.getCapturedPhotoUri(data, mCapturePhotoUriHolder);
if (captured != null) {
mCollection.add(captured);
mMediaStoreCompat.cleanUp(mCapturePhotoUriHolder);
if(mCollection.isSingleChoose()){
setResult();
}
}
}
}
public void prepareCapture(String uri) {
mCapturePhotoUriHolder = uri;
}
private void showFolderList() {
galleryTip.setImageResource(R.drawable.gallery_up);
mListViewGroup.setVisibility(View.VISIBLE);
mListView.setVisibility(View.VISIBLE);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.listview_up);
Animation fadeIn = AnimationUtils.loadAnimation(this, R.anim.listview_fade_in);
mListView.startAnimation(animation);
mListViewGroup.startAnimation(fadeIn);
//mListViewGroup.setVisibility(View.VISIBLE);
}
private void hideFolderList() {
galleryTip.setImageResource(R.drawable.gallery_down);
Animation animation = AnimationUtils.loadAnimation(ImageSelectActivity.this, R.anim.listview_down);
Animation fadeOut = AnimationUtils.loadAnimation(ImageSelectActivity.this, R.anim.listview_fade_out);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
mListViewGroup.setVisibility(View.INVISIBLE);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
mListView.startAnimation(animation);
mListViewGroup.startAnimation(fadeOut);
}
public MediaStoreCompat getMediaStoreCompat() {
return mMediaStoreCompat;
}
@Override
protected void onDestroy() {
mMediaStoreCompat.destroy();
albumCollection.onDestroy();
mPhotoCollection.onDestroy();
super.onDestroy();
}
@Override
public void onBackPressed() {
if (mCollection.isEmpty()) {
setResult(Activity.RESULT_CANCELED);
super.onBackPressed();
}
}
/**
* 选择相机
*/
public void showCameraAction() {
mCapturePhotoUriHolder = mMediaStoreCompat.invokeCameraCapture(this, ImageSelectActivity.REQUEST_CODE_CAPTURE);
}
@Override
public void onSelect(Album album) {
hideFolderList();
mFoldName.setText(album.getDisplayName(this));
mPhotoCollection.resetLoad(album);
}
@Override
public void onReset(Album album) {
mPhotoCollection.load(album);
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/MimeType.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker;
import android.content.ContentResolver;
import android.net.Uri;
import android.webkit.MimeTypeMap;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import io.valuesfeng.picker.utils.PhotoMetadataUtils;
/**
* MIME Type enumeration to restrict selectable photo on the selection activity.
* @author KeithYokoma
* @since 2014/03/19
* @version 1.0.0
*/
@SuppressWarnings("unused") // public APIs
public enum MimeType {
JPEG("image/jpeg", new HashSet<String>() {{ add("jpg"); add("jpeg"); }}),
PNG("image/png", new HashSet<String>() {{ add("png"); }}),
GIF("image/gif", new HashSet<String>() {{ add("gif"); }});
private final String mMimeTypeName;
private final Set<String> mExtensions;
MimeType(String mimeTypeName, Set<String> extensions) {
mMimeTypeName = mimeTypeName;
mExtensions = extensions;
}
public static Set<MimeType> allOf() {
return EnumSet.allOf(MimeType.class);
}
public static Set<MimeType> of(MimeType type) {
return EnumSet.of(type);
}
public static Set<MimeType> of(MimeType type, MimeType... rest) {
return EnumSet.of(type, rest);
}
@Override
public String toString() {
return mMimeTypeName;
}
public boolean checkType(ContentResolver resolver, Uri uri) {
MimeTypeMap map = MimeTypeMap.getSingleton();
if (uri == null) {
return false;
}
String type = map.getExtensionFromMimeType(resolver.getType(uri));
for (String extension : mExtensions) {
if (extension.equals(type)) {
return true;
}
String path = PhotoMetadataUtils.getPath(resolver, uri);
if (path != null && path.toLowerCase(Locale.US).endsWith(extension)) {
return true;
}
}
return false;
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/Picker.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import com.bumptech.glide.Glide;
import com.squareup.picasso.Picasso;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import io.valuesfeng.picker.engine.LoadEngine;
import io.valuesfeng.picker.model.SelectionSpec;
/**
*
* thanks for:
*
* https://github.com/nohana/Laevatein
*/
public final class Picker {
private static final String INITIALIZE_PICKER_ERROR = "Try to initialize Picker which had already been initialized before";
private static boolean hasInitPicker;
private final WeakReference<Activity> mContext;
private final WeakReference<Fragment> mFragment;
private final Set<MimeType> mMimeType;
private final SelectionSpec mSelectionSpec;
private LoadEngine engine; //图片加载器 glide imageloder picasso
private List<Uri> mResumeList;
Picker(Activity activity, Fragment fragment, Set<MimeType> mimeType) {
mContext = new WeakReference<>(activity);
if (fragment != null)
mFragment = new WeakReference<>(fragment);
else
mFragment = null;
mMimeType = mimeType;
mSelectionSpec = new SelectionSpec();
mResumeList = new ArrayList<>();
}
Picker(Activity activity, Fragment fragment) {
mContext = new WeakReference<>(activity);
if (fragment != null)
mFragment = new WeakReference<>(fragment);
else
mFragment = null;
mMimeType = MimeType.allOf();
mSelectionSpec = new SelectionSpec();
mResumeList = new ArrayList<>();
}
/**
* set iamge load engine
*
* @param engine
* @return
*/
public Picker setEngine(LoadEngine engine) {
this.engine = engine;
return this;
}
/**
* set the first item open camera
*
* @param mEnableCamera
* @return
*/
public Picker enableCamera(boolean mEnableCamera) {
mSelectionSpec.setmEnableCamera(mEnableCamera);
return this;
}
/**
* set if should start the camera by default
*
* @param mStartWithCamera
* @return
*/
public Picker startCamera(boolean mStartWithCamera) {
mSelectionSpec.startWithCamera(mStartWithCamera);
return this;
}
/**
* Sets the limitation of a selectable count within the specified range.
*
* @param min minimum value to select.
* @param max maximum value to select.
* @return the specification builder context.
*/
public Picker count(int min, int max) {
mSelectionSpec.setMinSelectable(min);
mSelectionSpec.setMaxSelectable(max);
return this;
}
/**
* Sets the limitation of a selectable count within the specified range.
*
* @param max maximum value to select.
* @return the specification builder context.
*/
public Picker count(int max) {
mSelectionSpec.setMinSelectable(0);
mSelectionSpec.setMaxSelectable(max);
return this;
}
public Picker singleChoice() {
count(0, 1);
return this;
}
//TODO : Wait achieve
/**
* Sets the limitation of a selectable image quality by pixel count within the specified range.
*
* @param minPixel minimum value to select.
* @param maxPixel maximum value to select.
* @return the specification builder context.
*/
public Picker quality(int minPixel, int maxPixel) {
mSelectionSpec.setMinPixels(minPixel);
mSelectionSpec.setMaxPixels(maxPixel);
return this;
}
/**
* Sets the default selection to resume photo picking activity.
*
* @param uriList to set selected as default.
* @return the specification builder context.
*/
public Picker resume(List<Uri> uriList) {
if (uriList == null) { // nothing to do.
return this;
}
mResumeList.addAll(uriList);
return this;
}
/**
* Start to select photo.
*
* @param requestCode identity of the requester activity.
*/
public void forResult(int requestCode) {
if (engine == null)
throw new ExceptionInInitializerError(LoadEngine.INITIALIZE_ENGINE_ERROR);
Activity activity = getActivity();
if (activity == null) {
return; // cannot continue;
}
mSelectionSpec.setMimeTypeSet(mMimeType);
mSelectionSpec.setEngine(engine);
Intent intent = new Intent(activity, ImageSelectActivity.class);
intent.putExtra(ImageSelectActivity.EXTRA_SELECTION_SPEC, mSelectionSpec);
// intent.putExtra(ImageSelectActivity.EXTRA_ENGINE, (Serializable) engine);
intent.putParcelableArrayListExtra(ImageSelectActivity.EXTRA_RESUME_LIST, (ArrayList<? extends android.os.Parcelable>) mResumeList);
Fragment fragment = getFragment();
if (fragment != null) {
fragment.startActivityForResult(intent, requestCode);
} else {
activity.startActivityForResult(intent, requestCode);
}
hasInitPicker = false;
}
public static Picker from(Activity activity) {
if (hasInitPicker)
throw new ExceptionInInitializerError(INITIALIZE_PICKER_ERROR);
hasInitPicker = true;
return new Picker(activity, null);
}
public static Picker from(Activity activity, Set<MimeType> mimeType) {
if (hasInitPicker)
throw new ExceptionInInitializerError(INITIALIZE_PICKER_ERROR);
hasInitPicker = true;
return new Picker(activity, null, mimeType);
}
public static Picker from(Fragment fragment) {
if (hasInitPicker)
throw new ExceptionInInitializerError(INITIALIZE_PICKER_ERROR);
hasInitPicker = true;
return new Picker(fragment.getActivity(), fragment);
}
public static Picker from(Fragment fragment, Set<MimeType> mimeType) {
if (hasInitPicker)
throw new ExceptionInInitializerError(INITIALIZE_PICKER_ERROR);
hasInitPicker = true;
return new Picker(fragment.getActivity(), fragment, mimeType);
}
/**
* @return the actual requester context.
*/
@Nullable
Activity getActivity() {
return mContext.get();
}
/**
* @return the fragment that is responsible for result handling.
*/
@Nullable
Fragment getFragment() {
return mFragment != null ? mFragment.get() : null;
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/adapter/AlbumAdapter.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker.adapter;
import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.CursorAdapter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.utils.L;
import io.valuesfeng.picker.R;
import io.valuesfeng.picker.model.Album;
/**
*/
public class AlbumAdapter extends CursorAdapter {
LayoutInflater mInflater;
ViewHolder viewHolder;
public AlbumAdapter(Context context, Cursor c) {
super(context, c, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
mInflater = LayoutInflater.from(context);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View convertView = mInflater.inflate(R.layout.photopick_list_item, parent, false);
viewHolder = new ViewHolder();
viewHolder.textView =(TextView) convertView.findViewById(R.id.foldName);
viewHolder.photoCount =(TextView) convertView.findViewById(R.id.photoCount);
convertView.setTag(viewHolder);
return convertView;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
viewHolder = (ViewHolder) view.getTag();
Album album = Album.valueOf(cursor);
viewHolder.textView.setText(album.getDisplayName(context));
viewHolder.photoCount.setText("( "+album.getCount()+" )");
}
static class ViewHolder{
TextView textView;
TextView photoCount;
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/adapter/PictureAdapter.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker.adapter;
import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import java.util.Map;
import io.valuesfeng.picker.R;
import io.valuesfeng.picker.model.Picture;
import io.valuesfeng.picker.control.SelectedUriCollection;
import io.valuesfeng.picker.widget.GridViewItemRelativeLayout;
/**
*/
public class PictureAdapter extends CursorAdapter {
LayoutInflater mInflater;
SelectedUriCollection mCollection;
public PictureAdapter(Context context, Cursor c, SelectedUriCollection mCollection) {
super(context, c, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
mInflater = LayoutInflater.from(context);
this.mCollection = mCollection;
}
private ViewHolder viewHolder;
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View convertView = mInflater.inflate(R.layout.photopick_gridlist_item, parent, false);
viewHolder = new ViewHolder(convertView, mCollection);
return convertView;
}
@Override
public void bindView(View view, final Context context, Cursor cursor) {
viewHolder = (ViewHolder) view.getTag();
viewHolder.itemView.setItem(Picture.valueOf(cursor));
}
static class ViewHolder {
GridViewItemRelativeLayout itemView;
public ViewHolder(View convertView, SelectedUriCollection mCollection) {
itemView = (GridViewItemRelativeLayout) convertView;
itemView.setImageView((ImageView) convertView.findViewById(R.id.thumbnail)
, (ImageView) convertView.findViewById(R.id.check)
, mCollection);
convertView.setTag(this);
}
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/control/AlbumCollection.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker.control;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import java.lang.ref.WeakReference;
import io.valuesfeng.picker.adapter.AlbumAdapter;
import io.valuesfeng.picker.loader.AlbumLoader;
import io.valuesfeng.picker.model.Album;
import io.valuesfeng.picker.model.SelectionSpec;
import io.valuesfeng.picker.utils.BundleUtils;
import io.valuesfeng.picker.utils.HandlerUtils;
/**
* @version 1.0.0
* @hide
*/
public class AlbumCollection implements LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener {
private static final int LOADER_ID = 1;
private static final String STATE_CURRENT_SELECTION = BundleUtils.buildKey(AlbumCollection.class, "STATE_CURRENT_SELECTION");
private WeakReference<Context> mContext;
private LoaderManager mLoaderManager;
private OnDirectorySelectListener directorySelectListener;
private int mCurrentSelection;
private SelectionSpec selectionSpec;
private AlbumAdapter albumAdapter;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Context context = mContext.get();
if (context == null) {
return null;
}
return AlbumLoader.newInstance(context, selectionSpec);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, final Cursor data) {
Context context = mContext.get();
if (context == null) {
return;
}
albumAdapter.swapCursor(data);
HandlerUtils.getMainHandler().post(new Runnable() {
@Override
public void run() {
if (data.getCount() > 0) {
data.moveToFirst();
Album currentAlbum = Album.valueOf(data);
if (directorySelectListener != null) {
directorySelectListener.onReset(currentAlbum);
}
}
}
});
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
Context context = mContext.get();
if (context == null) {
return;
}
albumAdapter.swapCursor(null);
}
public void onCreate(FragmentActivity activity, OnDirectorySelectListener directorySelectListener, SelectionSpec selectionSpec, ListView listView) {
mContext = new WeakReference<Context>(activity);
mLoaderManager = activity.getSupportLoaderManager();
this.directorySelectListener = directorySelectListener;
this.selectionSpec = selectionSpec;
albumAdapter = new AlbumAdapter(activity, null);
listView.setAdapter(albumAdapter);
listView.setOnItemClickListener(this);
}
public void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState == null) {
return;
}
mCurrentSelection = savedInstanceState.getInt(STATE_CURRENT_SELECTION);
}
public void onSaveInstanceState(Bundle outState) {
outState.putInt(STATE_CURRENT_SELECTION, mCurrentSelection);
}
public void onDestroy() {
mLoaderManager.destroyLoader(LOADER_ID);
directorySelectListener = null;
}
public void loadAlbums() {
mLoaderManager.initLoader(LOADER_ID, null, this);
}
public void resetLoadAlbums() {
mLoaderManager.restartLoader(LOADER_ID, null, this);
}
public int getCurrentSelection() {
return mCurrentSelection;
}
public void setStateCurrentSelection(int currentSelection) {
mCurrentSelection = currentSelection;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (directorySelectListener != null) {
Cursor cursor = (Cursor) parent.getItemAtPosition(position);
Album album = Album.valueOf(cursor);
directorySelectListener.onSelect(album);
}
}
public interface OnDirectorySelectListener {
void onSelect(Album album);
void onReset(Album album);
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/control/PictureCollection.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker.control;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.widget.GridView;
import java.lang.ref.WeakReference;
import io.valuesfeng.picker.adapter.PictureAdapter;
import io.valuesfeng.picker.loader.PictureLoader;
import io.valuesfeng.picker.model.Album;
import io.valuesfeng.picker.model.SelectionSpec;
import io.valuesfeng.picker.utils.BundleUtils;
/**
*/
public class PictureCollection implements LoaderManager.LoaderCallbacks<Cursor> {
private static final int LOADER_ID = 2;
private static final String ARGS_ALBUM = BundleUtils.buildKey(PictureCollection.class, "ARGS_ALBUM");
private WeakReference<Context> mContext;
private LoaderManager mLoaderManager;
private PictureAdapter albumPhotoAdapter;
private SelectionSpec selectionSpec;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Context context = mContext.get();
if (context == null) {
return null;
}
Album album = args.getParcelable(ARGS_ALBUM);
if (album == null) {
return null;
}
return PictureLoader.newInstance(context, album, selectionSpec);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
Context context = mContext.get();
if (context == null) {
return;
}
albumPhotoAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
Context context = mContext.get();
if (context == null) {
return;
}
albumPhotoAdapter.swapCursor(null);
}
public void onCreate(@NonNull FragmentActivity context, @NonNull GridView gridView, SelectedUriCollection mCollection, SelectionSpec selectionSpec) {
mContext = new WeakReference<Context>(context);
mLoaderManager = context.getSupportLoaderManager();
this.selectionSpec = selectionSpec;
albumPhotoAdapter = new PictureAdapter(context, null, mCollection);
mCollection.getEngine().scrolling(gridView);
gridView.setAdapter(albumPhotoAdapter);
}
public void onDestroy() {
mLoaderManager.destroyLoader(LOADER_ID);
}
public void loadAllPhoto() {
Album album = new Album(Album.ALBUM_ID_ALL, -1, Album.ALBUM_NAME_ALL, "");
load(album);
}
public void load(@Nullable Album target) {
Bundle args = new Bundle();
args.putParcelable(ARGS_ALBUM, target);
mLoaderManager.initLoader(LOADER_ID, args, this);
}
public void resetLoad(@Nullable Album target) {
Bundle args = new Bundle();
args.putParcelable(ARGS_ALBUM, target);
mLoaderManager.restartLoader(LOADER_ID, args, this);
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/control/SelectedUriCollection.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker.control;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import io.valuesfeng.picker.engine.LoadEngine;
import io.valuesfeng.picker.model.SelectionSpec;
import io.valuesfeng.picker.utils.BundleUtils;
/**
*/
public class SelectedUriCollection {
private static final String STATE_SELECTION = BundleUtils.buildKey(SelectedUriCollection.class, "STATE_SELECTION");
private static final String STATE_SELECTION_POSITION = BundleUtils.buildKey(SelectedUriCollection.class, "STATE_SELECTION_POSITION");
private final WeakReference<Context> mContext;
private Set<Uri> mUris;
private SelectionSpec mSpec;
private OnSelectionChange onSelectionChange;
public SelectedUriCollection(Context context) {
mContext = new WeakReference<>(context);
}
public void onCreate(Bundle savedInstanceState) {
if (savedInstanceState == null) {
mUris = new LinkedHashSet<>();
} else {
List<Uri> saved = savedInstanceState.getParcelableArrayList(STATE_SELECTION);
mUris = new LinkedHashSet<>(saved);
}
}
public void prepareSelectionSpec(SelectionSpec spec) {
mSpec = spec;
}
public void setDefaultSelection(List<Uri> uris) {
mUris.addAll(uris);
}
public void onSaveInstanceState(Bundle outState) {
outState.putParcelableArrayList(STATE_SELECTION, new ArrayList<>(mUris));
}
public boolean add(Uri uri) {
if (onSelectionChange!=null)
onSelectionChange.onChange(maxCount(),count()+1);
return mUris.add(uri);
}
public boolean remove(Uri uri) {
if (onSelectionChange!=null)
onSelectionChange.onChange(maxCount(),count()-1);
return mUris.remove(uri);
}
public List<Uri> asList() {
return new ArrayList<Uri>(mUris);
}
public boolean isEmpty() {
return mUris == null || mUris.isEmpty();
}
public boolean isSelected(Uri uri) {
return mUris.contains(uri);
}
public boolean isCountInRange() {
return mSpec.getMinSelectable() <= mUris.size() && mUris.size() <= mSpec.getMaxSelectable();
}
public boolean isCountOver() {
return mUris.size() >= mSpec.getMaxSelectable();
}
public int count() {
return mUris.size();
}
public int maxCount() {
return mSpec.getMaxSelectable();
}
public boolean isSingleChoose() {
return mSpec.isSingleChoose();
}
public LoadEngine getEngine(){
return mSpec.getEngine();
}
public void setOnSelectionChange(OnSelectionChange onSelectionChange) {
this.onSelectionChange = onSelectionChange;
}
public interface OnSelectionChange{
void onChange(int maxCount,int selectCount);
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/engine/GlideEngine.java
================================================
package io.valuesfeng.picker.engine;
import android.content.Context;
import android.os.Parcel;
import android.widget.GridView;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import io.valuesfeng.picker.R;
/**
* Author: valuesfeng
* Version V1.0
* Date: 16/1/1
* Description:
* Modification History:
* Date Author Version Description
* -----------------------------------------------------------------------------------
* 16/1/1 valuesfeng 1.0 1.0
* Why & What is modified:
*/
public class GlideEngine implements LoadEngine {
private int img_loading;
private int img_camera;
public GlideEngine() {
this(0, 0);
}
public GlideEngine(int img_loading) {
this(img_loading, 0);
}
public GlideEngine(int img_camera, int img_loading) {
if (img_loading == 0)
this.img_loading = R.drawable.image_not_exist;
else
this.img_loading = img_loading;
if (img_camera == 0)
this.img_camera = R.drawable.ic_camera;
else
this.img_camera = img_camera;
}
@Override
public void displayImage(String path, ImageView imageView) {
chargeInit(imageView.getContext());
Glide.with(imageView.getContext())
.load(path)
.centerCrop()
.error(img_loading)
.placeholder(img_loading)
.dontAnimate()
.into(imageView);
}
@Override
public void displayCameraItem(ImageView imageView) {
chargeInit(imageView.getContext());
Glide.with(imageView.getContext())
.load(img_camera)
.centerCrop()
.error(img_camera)
.placeholder(img_camera)
.dontAnimate()
.into(imageView);
}
private void chargeInit(Context context) {
if (Glide.get(context) == null) {
throw new ExceptionInInitializerError(INITIALIZE_ENGINE_ERROR);
}
}
@Override
public void scrolling(GridView view) {
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.img_loading);
dest.writeInt(this.img_camera);
}
protected GlideEngine(Parcel in) {
this.img_loading = in.readInt();
this.img_camera = in.readInt();
}
public static final Creator<GlideEngine> CREATOR = new Creator<GlideEngine>() {
public GlideEngine createFromParcel(Parcel source) {
return new GlideEngine(source);
}
public GlideEngine[] newArray(int size) {
return new GlideEngine[size];
}
};
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/engine/ImageLoaderEngine.java
================================================
package io.valuesfeng.picker.engine;
import android.graphics.Bitmap;
import android.os.Parcel;
import android.widget.GridView;
import android.widget.ImageView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.listener.PauseOnScrollListener;
import io.valuesfeng.picker.R;
/**
* Author: valuesfeng
* Version V1.0
* Date: 16/1/1
* Description:
* Modification History:
* Date Author Version Description
* -----------------------------------------------------------------------------------
* 16/1/1 valuesfeng 1.0 1.0
* Why & What is modified:
*/
public class ImageLoaderEngine implements LoadEngine {
private int img_loading;
private int img_camera;
private DisplayImageOptions displayOptions;
private DisplayImageOptions cameraOptions;
public ImageLoaderEngine() {
this(0, 0);
}
public ImageLoaderEngine(int img_loading) {
this(img_loading,0);
}
public ImageLoaderEngine(int img_loading, int img_camera) {
if (ImageLoader.getInstance() == null) {
throw new ExceptionInInitializerError(INITIALIZE_ENGINE_ERROR);
}
if (img_loading == 0)
this.img_loading = R.drawable.image_not_exist;
else
this.img_loading = img_loading;
if (img_camera == 0)
this.img_camera = R.drawable.ic_camera;
else
this.img_camera = img_camera;
}
@Override
public void displayImage(String path, ImageView imageView) {
ImageLoader.getInstance().displayImage(path, imageView, getPathImageOptions());
}
@Override
public void displayCameraItem(ImageView imageView) {
ImageLoader.getInstance().displayImage("drawable://" + img_camera, imageView, getCameraOptions());
}
@Override
public void scrolling(GridView view) {
view.setOnScrollListener(new PauseOnScrollListener(ImageLoader.getInstance(), false, true));
}
private DisplayImageOptions getPathImageOptions() {
if (displayOptions == null)
displayOptions = new DisplayImageOptions
.Builder()
.showImageOnLoading(img_loading)
.showImageForEmptyUri(img_loading)
.showImageOnFail(img_loading)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.imageScaleType(ImageScaleType.EXACTLY)
.build();
return displayOptions;
}
private DisplayImageOptions getCameraOptions() {
if (cameraOptions == null)
cameraOptions = new DisplayImageOptions
.Builder()
.showImageOnLoading(img_camera)
.showImageForEmptyUri(img_camera)
.showImageOnFail(img_camera)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.build();
return cameraOptions;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.img_loading);
dest.writeInt(this.img_camera);
}
protected ImageLoaderEngine(Parcel in) {
this.img_loading = in.readInt();
this.img_camera = in.readInt();
}
public static final Creator<ImageLoaderEngine> CREATOR = new Creator<ImageLoaderEngine>() {
public ImageLoaderEngine createFromParcel(Parcel source) {
return new ImageLoaderEngine(source);
}
public ImageLoaderEngine[] newArray(int size) {
return new ImageLoaderEngine[size];
}
};
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/engine/LoadEngine.java
================================================
package io.valuesfeng.picker.engine;
import android.os.Parcelable;
import android.widget.GridView;
import android.widget.ImageView;
import java.io.Serializable;
/**
* Author: valuesfeng
* Version V1.0
* Date: 16/1/1
* Description:
* Modification History:
* Date Author Version Description
* -----------------------------------------------------------------------------------
* 16/1/1 valuesfeng 1.0 1.0
* Why & What is modified:
*/
public interface LoadEngine extends Parcelable {
String INITIALIZE_ENGINE_ERROR = "initialize error,image load engine can not be null";
void displayCameraItem(ImageView imageView);
void displayImage(String path, ImageView imageView);
void scrolling(GridView view);
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/engine/PicassoEngine.java
================================================
package io.valuesfeng.picker.engine;
import android.content.Context;
import android.os.Parcel;
import android.widget.AbsListView;
import android.widget.GridView;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import io.valuesfeng.picker.R;
/**
* Author: valuesfeng
* Version V1.0
* Date: 16/1/1
* Description:
* Modification History:
* Date Author Version Description
* -----------------------------------------------------------------------------------
* 16/1/1 valuesfeng 1.0 1.0
* Why & What is modified:
*/
public class PicassoEngine implements LoadEngine {
private int img_loading;
private int img_camera;
public PicassoEngine() {
this(0, 0);
}
public PicassoEngine(int img_loading) {
this(img_loading,0);
}
public PicassoEngine(int img_camera, int img_loading) {
if (img_loading == 0)
this.img_loading = R.drawable.image_not_exist;
else
this.img_loading = img_loading;
if (img_camera == 0)
this.img_camera = R.drawable.ic_camera;
else
this.img_camera = img_camera;
}
@Override
public void displayImage(String path, ImageView imageView) {
chargeInit(imageView.getContext());
Picasso.with(imageView.getContext())
.load(path)
.centerCrop()
.fit()
.placeholder(img_loading)
.error(img_loading)
.into(imageView);
}
@Override
public void displayCameraItem(ImageView imageView) {
chargeInit(imageView.getContext());
Picasso.with(imageView.getContext())
.load(img_camera)
.centerCrop()
.fit()
.placeholder(img_camera)
.error(img_camera)
.into(imageView);
}
@Override
public void scrolling(GridView view) {
view.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
final Picasso picasso = Picasso.with(view.getContext());
if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_TOUCH_SCROLL) {
picasso.resumeTag(view.getContext());
} else {
picasso.pauseTag(view.getContext());
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
}
private void chargeInit(Context context) {
if (Picasso.with(context) == null) {
throw new ExceptionInInitializerError(INITIALIZE_ENGINE_ERROR);
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.img_loading);
dest.writeInt(this.img_camera);
}
protected PicassoEngine(Parcel in) {
this.img_loading = in.readInt();
this.img_camera = in.readInt();
}
public static final Creator<PicassoEngine> CREATOR = new Creator<PicassoEngine>() {
public PicassoEngine createFromParcel(Parcel source) {
return new PicassoEngine(source);
}
public PicassoEngine[] newArray(int size) {
return new PicassoEngine[size];
}
};
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/loader/AlbumLoader.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker.loader;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MergeCursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v4.content.CursorLoader;
import io.valuesfeng.picker.model.Album;
import io.valuesfeng.picker.model.SelectionSpec;
import io.valuesfeng.picker.utils.PhotoMetadataUtils;
/**
* Wrapper for {@link android.support.v4.content.CursorLoader} to merge custom cursors.
*
* @author KeithYokoma
* @version 1.0.0
* @hide
* @Modification add picture size charge
* by valuesFeng
* @since 2014/03/26
*/
public class AlbumLoader extends CursorLoader {
private static final String[] PROJECTION = {MediaStore.Images.Media.BUCKET_ID, MediaStore.Images.Media.BUCKET_DISPLAY_NAME, MediaStore.Images.Media._ID, "count(bucket_id) as cou"};
private static final String BUCKET_GROUP_BY = ") GROUP BY 1,(2";
private static final String BUCKET_ORDER_BY = "MAX(datetaken) DESC";
private static final String MEDIA_ID_DUMMY = String.valueOf(-1);
private static final String IS_LARGE_SIZE = " _size > ? or _size is null";
public static CursorLoader newInstance(Context context, SelectionSpec selectionSpec) {
return new AlbumLoader(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, PROJECTION, IS_LARGE_SIZE + BUCKET_GROUP_BY, new String[]{selectionSpec.getMinPixels() + ""}, BUCKET_ORDER_BY,selectionSpec );
}
private AlbumLoader(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, SelectionSpec selectionSpec) {
super(context, uri, projection, selection, selectionArgs, sortOrder);
}
@Override
public Cursor loadInBackground() {
Cursor albums = super.loadInBackground();
MatrixCursor allAlbum = new MatrixCursor(PROJECTION);
long count = 0;
if (albums.getCount() > 0) {
while (albums.moveToNext()) {
count += albums.getLong(3);
}
}
allAlbum.addRow(new String[]{Album.ALBUM_ID_ALL, Album.ALBUM_NAME_ALL, MEDIA_ID_DUMMY, count + ""});
return new MergeCursor(new Cursor[]{allAlbum, albums});
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/loader/PictureLoader.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker.loader;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MergeCursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v4.content.CursorLoader;
import io.valuesfeng.picker.model.Album;
import io.valuesfeng.picker.model.Picture;
import io.valuesfeng.picker.model.SelectionSpec;
import io.valuesfeng.picker.utils.MediaStoreCompat;
/**
* @author KeithYokoma
* @version 1.0.0
* @hide
* @since 2014/03/27
*
* @Modification
* add picture size charge
* by valuesFeng
*/
public class PictureLoader extends CursorLoader {
private static final String[] PROJECTION = {MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME};
private static final String ORDER_BY = MediaStore.Images.Media._ID + " DESC";
private final boolean mEnableCapture;
private static final String IS_LARGE_SIZE = "_size > ? or _size is null";
public PictureLoader(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, boolean capture) {
super(context, uri, projection, selection, selectionArgs, sortOrder);
mEnableCapture = capture;
}
public static CursorLoader newInstance(Context context, Album album, SelectionSpec selectionSpec) {
if (album == null || album.isAll()) {
return new PictureLoader(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, PROJECTION,
IS_LARGE_SIZE, new String[]{selectionSpec.getMinPixels() + ""}, ORDER_BY, selectionSpec.ismEnableCamera());
}
return new PictureLoader(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, PROJECTION,
MediaStore.Images.Media.BUCKET_ID + " = ? and (" + IS_LARGE_SIZE + ")", new String[]{album.getId(), selectionSpec.getMinPixels() + ""}, ORDER_BY, selectionSpec.ismEnableCamera());
}
@Override
public Cursor loadInBackground() {
Cursor result = super.loadInBackground();
if (!mEnableCapture || !MediaStoreCompat.hasCameraFeature(getContext())) {
return result;
}
MatrixCursor dummy = new MatrixCursor(PROJECTION);
dummy.addRow(new Object[]{Picture.ITEM_ID_CAPTURE, Picture.ITEM_DISPLAY_NAME_CAPTURE});
return new MergeCursor(new Cursor[]{dummy, result});
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/model/Album.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker.model;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import io.valuesfeng.picker.R;
/**
* @author KeithYokoma
* @version 1.0.0
* @hide
* @since 2014/03/20
*/
public class Album implements Parcelable {
public static final Creator<Album> CREATOR = new Creator<Album>() {
@Nullable
@Override
public Album createFromParcel(Parcel source) {
return new Album(source);
}
@Override
public Album[] newArray(int size) {
return new Album[size];
}
};
public static final String ALBUM_ID_ALL = String.valueOf(-1);
public static final String ALBUM_NAME_ALL = "All";
public static final String ALBUM_NAME_CAMERA = "Camera";
public static final String ALBUM_NAME_DOWNLOAD = "Download";
public static final String ALBUM_NAME_SCREEN_SHOT = "Screenshots";
private final String mId; //BUCKET_ID
private final long mCoverId; //Media_ID
private final String mDisplayName;//BUCKET_DISPLAY_NAME
private final String mCount; // photo count
/* package */
public Album(String id, long coverId, String albumName, String count) {
mId = id;
mCoverId = coverId;
mDisplayName = albumName;
mCount = count;
}
/* package */ Album(Parcel source) {
mId = source.readString();
mCoverId = source.readLong();
mDisplayName = source.readString();
mCount = source.readString();
}
/**
* This method is not responsible for managing cursor resource, such as close, iterate, and so on.
*
* @param cursor to be converted.
*/
public static Album valueOf(Cursor cursor) {
return new Album(
cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID)),
cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID)),
cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)),
cursor.getLong(3) + ""
);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mId);
dest.writeLong(mCoverId);
dest.writeString(mDisplayName);
dest.writeString(mCount);
}
public String getId() {
return mId;
}
public long getCoverId() {
return mCoverId;
}
public String getDisplayName(Context context) {
if (isAll()) {
return context.getString(R.string.l_album_name_all);
}
if (isCamera()) {
return context.getString(R.string.l_album_name_camera);
}
if (ALBUM_NAME_DOWNLOAD.equals(mDisplayName)) {
return context.getString(R.string.l_album_name_download);
}
if (ALBUM_NAME_SCREEN_SHOT.equals(mDisplayName)) {
return context.getString(R.string.l_album_name_screen_shot);
}
return mDisplayName;
}
public Uri buildContentUri() {
return ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mCoverId);
}
public boolean isAll() {
return ALBUM_ID_ALL.equals(mId);
}
public boolean isCamera() {
return ALBUM_NAME_CAMERA.equals(mDisplayName);
}
public String getCount() {
return mCount;
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/model/Picture.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker.model;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
/**
* @author KeithYokoma
* @version 1.0.0
* @hide
* @since 2014/03/24
*/
public class Picture implements Parcelable {
public static final Creator<Picture> CREATOR = new Creator<Picture>() {
@Override
@Nullable
public Picture createFromParcel(Parcel source) {
return new Picture(source);
}
@Override
public Picture[] newArray(int size) {
return new Picture[size];
}
};
public static final long ITEM_ID_CAPTURE = -1;
public static final String ITEM_DISPLAY_NAME_CAPTURE = "Capture";
private final long mId;
private String mDisplayName;
/* package */ Picture(long id,String displayName) {
mId = id;
mDisplayName = displayName;
}
/* package */ Picture(Parcel source) {
mId = source.readLong();
}
public static Picture valueOf(Cursor cursor) {
// return new Picture(cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID)));
return new Picture(cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID)),cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)));
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(mId);
}
public long getId() {
return mId;
}
public Uri buildContentUri() {
return ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mId);
}
public Bitmap getThumbnail(Context context) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
ContentResolver contentResolver = context.getContentResolver();
return MediaStore.Images.Thumbnails.getThumbnail(contentResolver, mId, MediaStore.Images.Thumbnails.MICRO_KIND, options);
}
public boolean isCapture() {
return mId == ITEM_ID_CAPTURE;
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/model/SelectionSpec.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker.model;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import io.valuesfeng.picker.MimeType;
import io.valuesfeng.picker.engine.LoadEngine;
import io.valuesfeng.picker.utils.ParcelUtils;
/**
*/
public final class SelectionSpec implements Parcelable {
public static final Creator<SelectionSpec> CREATOR = new Creator<SelectionSpec>() {
@Override
public SelectionSpec createFromParcel(Parcel source) {
return new SelectionSpec(source);
}
@Override
public SelectionSpec[] newArray(int size) {
return new SelectionSpec[size];
}
};
private int mMaxSelectable; // 最大选择数量
private int mMinSelectable; // 最小选择数量
private long mMinPixels; //最小size
private long mMaxPixels; //最大size
private boolean mEnableCamera;//是否可用相机
private boolean mStartWithCamera;
private LoadEngine engine; //图片加载器 glide imageloder picasso
private Set<MimeType> mMimeTypeSet;
public SelectionSpec() {
mMinSelectable = 0;
mMaxSelectable = 1;
mMinPixels = 0L;
mMaxPixels = Long.MAX_VALUE;
mEnableCamera = false;
mStartWithCamera = false;
}
SelectionSpec(Parcel source) {
mMinSelectable = source.readInt();
mMaxSelectable = source.readInt();
mMinPixels = source.readLong();
mMaxPixels = source.readLong();
mEnableCamera = ParcelUtils.readBoolean(source);
mStartWithCamera = ParcelUtils.readBoolean(source);
this.engine = source.readParcelable(LoadEngine.class.getClassLoader());
List<MimeType> list = new ArrayList<>();
source.readList(list, MimeType.class.getClassLoader());
mMimeTypeSet = EnumSet.copyOf(list);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mMinSelectable);
dest.writeInt(mMaxSelectable);
dest.writeLong(mMinPixels);
dest.writeLong(mMaxPixels);
ParcelUtils.writeBoolean(dest, mEnableCamera);
ParcelUtils.writeBoolean(dest, mStartWithCamera);
dest.writeParcelable(this.engine, 0);
dest.writeList(new ArrayList<>(mMimeTypeSet));
}
public boolean ismEnableCamera() {
return mEnableCamera;
}
public boolean willStartCamera() { return mStartWithCamera; }
public void setmEnableCamera(boolean mEnableCamera) {
this.mEnableCamera = mEnableCamera;
}
public void startWithCamera(boolean mStartWithCamera) { this.mStartWithCamera = mStartWithCamera; }
public void setMaxSelectable(int maxSelectable) {
mMaxSelectable = maxSelectable;
}
public void setMinSelectable(int minSelectable) {
mMinSelectable = minSelectable;
}
public void setMinPixels(long minPixels) {
mMinPixels = minPixels;
}
public void setMaxPixels(long maxPixels) {
mMaxPixels = maxPixels;
}
public void setMimeTypeSet(Set<MimeType> set) {
mMimeTypeSet = set;
}
public int getMinSelectable() {
return mMinSelectable;
}
public int getMaxSelectable() {
return mMaxSelectable;
}
public long getMinPixels() {
return mMinPixels;
}
public LoadEngine getEngine() {
return engine;
}
public void setEngine(LoadEngine engine) {
this.engine = engine;
}
public boolean isSingleChoose() {
if (mMinSelectable == 0 && mMaxSelectable == 1) {
return true;
} else {
return false;
}
}
public long getMaxPixels() {
return mMaxPixels;
}
public Set<MimeType> getMimeTypeSet() {
return mMimeTypeSet;
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/BundleUtils.java
================================================
package io.valuesfeng.picker.utils;
/**
* Created by zaiyong on 2015/6/6.
*/
public class BundleUtils {
private BundleUtils() {
}
public static String buildKey(Class<?> clazz, String name) {
return clazz.getCanonicalName() + "." + name;
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/CloseableUtils.java
================================================
package io.valuesfeng.picker.utils;
import android.util.Log;
import java.io.Closeable;
import java.io.IOException;
/**
* Created by laputan on 15-6-8.
*/
public class CloseableUtils {
private static final String TAG = CloseableUtils.class.getSimpleName();
private CloseableUtils() {
}
public static final void close(Closeable closeable) {
if(closeable != null) {
try {
closeable.close();
} catch (IOException var2) {
Log.e(TAG, "something went wrong on close", var2);
}
}
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/ExifInterfaceCompat.java
================================================
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package io.valuesfeng.picker.utils;
import android.media.ExifInterface;
import android.text.TextUtils;
import android.util.Log;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public final class ExifInterfaceCompat {
public static final String TAG = ExifInterfaceCompat.class.getSimpleName();
private ExifInterfaceCompat() {
}
public static final ExifInterface newInstance(String filename) throws IOException {
if(filename == null) {
throw new NullPointerException("filename should not be null");
} else {
return new ExifInterface(filename);
}
}
public static final Date getExifDateTime(String filepath) {
ExifInterface exif;
try {
exif = newInstance(filepath);
} catch (IOException var5) {
Log.e(TAG, "cannot read exif", var5);
return null;
}
String date = exif.getAttribute("DateTime");
if(TextUtils.isEmpty(date)) {
return null;
} else {
try {
SimpleDateFormat e = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
e.setTimeZone(TimeZone.getTimeZone("UTC"));
return e.parse(date);
} catch (ParseException var4) {
Log.d(TAG, "failed to parse date taken", var4);
return null;
}
}
}
public static final long getExifDateTimeInMillis(String filepath) {
Date datetime = getExifDateTime(filepath);
return datetime == null?-1L:datetime.getTime();
}
public static final int getExifOrientation(String filepath) {
ExifInterface exif = null;
try {
exif = newInstance(filepath);
} catch (IOException var3) {
Log.e(TAG, "cannot read exif", var3);
return -1;
}
int orientation = exif.getAttributeInt("Orientation", -1);
if(orientation == -1) {
return 0;
} else {
switch(orientation) {
case 3:
return 180;
case 6:
return 90;
case 8:
return 270;
default:
return 0;
}
}
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/HandlerUtils.java
================================================
package io.valuesfeng.picker.utils;
import android.os.Handler;
import android.os.Looper;
/**
*/
public class HandlerUtils {
private HandlerUtils() {
}
public static Handler getMainHandler() {
return new Handler(Looper.getMainLooper());
}
public static void postOnMain(Runnable message) {
getMainHandler().post(message);
}
public static void postOnMainWithDelay(Runnable message, long delayMillis) {
getMainHandler().postDelayed(message, delayMillis);
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/MediaStoreCompat.java
================================================
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package io.valuesfeng.picker.utils;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.BitmapFactory.Options;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore.Images.Media;
import android.provider.MediaStore.Images.Thumbnails;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
public class MediaStoreCompat {
public static final String TAG = MediaStoreCompat.class.getSimpleName();
private static final String MEDIA_FILE_NAME_FORMAT = "yyyyMMdd_HHmmss";
private static final String MEDIA_FILE_EXTENSION = ".jpg";
private static final String MEDIA_FILE_PREFIX = "IMG_";
private final String MEDIA_FILE_DIRECTORY;
private Context mContext;
private ContentObserver mObserver;
private ArrayList<MediaStoreCompat.PhotoContent> mRecentlyUpdatedPhotos;
public MediaStoreCompat(Context context, final Handler handler) {
this.mContext = context;
this.MEDIA_FILE_DIRECTORY = context.getPackageName();
this.mObserver = new ContentObserver(handler) {
public void onChange(boolean selfChange) {
super.onChange(selfChange);
MediaStoreCompat.this.updateLatestPhotos();
}
};
this.mContext.getContentResolver().registerContentObserver(Media.EXTERNAL_CONTENT_URI, true, this.mObserver);
}
public static final boolean hasCameraFeature(Context context) {
PackageManager pm = context.getApplicationContext().getPackageManager();
return pm.hasSystemFeature("android.hardware.camera");
}
public String invokeCameraCapture(Activity activity, int requestCode) {
if(!hasCameraFeature(this.mContext)) {
return null;
} else {
File toSave = this.getOutputFileUri();
if(toSave == null) {
return null;
} else {
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.addCategory("android.intent.category.DEFAULT");
intent.putExtra("output", Uri.fromFile(toSave));
intent.putExtra("android.intent.extra.videoQuality", 1);
activity.startActivityForResult(intent, requestCode);
return toSave.toString();
}
}
}
public void destroy() {
this.mContext.getContentResolver().unregisterContentObserver(this.mObserver);
}
public Uri getCapturedPhotoUri(Intent data, String preparedUri) {
Uri captured = null;
if(data != null) {
captured = data.getData();
if(captured == null) {
data.getParcelableExtra("android.intent.extra.STREAM");
}
}
File prepared = new File(preparedUri.toString());
if(captured == null || captured.equals(Uri.fromFile(prepared))) {
captured = this.findPhotoFromRecentlyTaken(prepared);
if(captured == null) {
captured = this.storeImage(prepared);
prepared.delete();
} else {
String realPath = getPathFromUri(this.mContext.getContentResolver(), captured);
if(realPath != null && !prepared.equals(new File(realPath))) {
prepared.delete();
}
}
}
return captured;
}
public void cleanUp(String uri) {
File file = new File(uri.toString());
if(file.exists()) {
file.delete();
}
}
public static String getPathFromUri(ContentResolver resolver, Uri contentUri) {
String dataColumn = "_data";
Cursor cursor = null;
String var5;
try {
cursor = resolver.query(contentUri, new String[]{"_data"}, (String)null, (String[])null, (String)null);
if(cursor == null || !cursor.moveToFirst()) {
Object index1 = null;
return (String)index1;
}
int index = cursor.getColumnIndex("_data");
var5 = cursor.getString(index);
} finally {
if(cursor != null) {
cursor.close();
}
}
return var5;
}
public static long copyFileStream(FileInputStream is, FileOutputStream os) throws IOException {
FileChannel srcChannel = null;
FileChannel destChannel = null;
long length;
try {
srcChannel = is.getChannel();
destChannel = os.getChannel();
length = srcChannel.transferTo(0L, srcChannel.size(), destChannel);
} finally {
if(srcChannel != null) {
srcChannel.close();
}
if(destChannel != null) {
destChannel.close();
}
}
return length;
}
private Uri findPhotoFromRecentlyTaken(File file) {
if(this.mRecentlyUpdatedPhotos == null) {
this.updateLatestPhotos();
}
long fileSize = file.length();
long taken = ExifInterfaceCompat.getExifDateTimeInMillis(file.getAbsolutePath());
int maxPoint = 0;
MediaStoreCompat.PhotoContent maxItem = null;
Iterator i$ = this.mRecentlyUpdatedPhotos.iterator();
while(i$.hasNext()) {
MediaStoreCompat.PhotoContent item = (MediaStoreCompat.PhotoContent)i$.next();
int point = 0;
if((long)item.size == fileSize) {
++point;
}
if(item.taken == taken) {
++point;
}
if(point > maxPoint) {
maxPoint = point;
maxItem = item;
}
}
if(maxItem != null) {
this.generateThumbnails(maxItem.id);
return ContentUris.withAppendedId(Media.EXTERNAL_CONTENT_URI, maxItem.id);
} else {
return null;
}
}
private Uri storeImage(File file) {
try {
ContentValues e = new ContentValues();
e.put("title", file.getName());
e.put("mime_type", "image/jpeg");
e.put("description", "mixi Photo");
e.put("orientation", Integer.valueOf(ExifInterfaceCompat.getExifOrientation(file.getAbsolutePath())));
long date = ExifInterfaceCompat.getExifDateTimeInMillis(file.getAbsolutePath());
if(date != -1L) {
e.put("datetaken", Long.valueOf(date));
}
Uri imageUri = this.mContext.getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, e);
FileOutputStream fos = (FileOutputStream)this.mContext.getContentResolver().openOutputStream(imageUri);
FileInputStream fis = new FileInputStream(file);
copyFileStream(fis, fos);
fos.close();
fis.close();
this.generateThumbnails(ContentUris.parseId(imageUri));
return imageUri;
} catch (Exception e) {
Log.w(TAG, "cannot insert", e);
return null;
}
}
private void updateLatestPhotos() {
Cursor c = Media.query(this.mContext.getContentResolver(), Media.EXTERNAL_CONTENT_URI, new String[]{"_id", "datetaken", "_size"}, (String)null, (String[])null, "date_added DESC");
if(c != null) {
try {
int count = 0;
this.mRecentlyUpdatedPhotos = new ArrayList();
while(c.moveToNext()) {
MediaStoreCompat.PhotoContent item = new MediaStoreCompat.PhotoContent();
item.id = c.getLong(0);
item.taken = c.getLong(1);
item.size = c.getInt(2);
this.mRecentlyUpdatedPhotos.add(item);
++count;
if(count > 5) {
break;
}
}
} finally {
c.close();
}
}
}
private void generateThumbnails(long imageId) {
try {
Thumbnails.getThumbnail(this.mContext.getContentResolver(), imageId, 1, (Options)null);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
@TargetApi(8)
private File getOutputFileUri() {
File extDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), this.MEDIA_FILE_DIRECTORY);
if(!extDir.exists() && !extDir.mkdirs()) {
return null;
} else {
String timeStamp = (new SimpleDateFormat(MEDIA_FILE_NAME_FORMAT)).format(new Date());
return new File(extDir.getPath() + File.separator + MEDIA_FILE_PREFIX + timeStamp + MEDIA_FILE_EXTENSION);
}
}
private static class PhotoContent {
public long id;
public long taken;
public int size;
private PhotoContent() {
}
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/ParcelUtils.java
================================================
package io.valuesfeng.picker.utils;
import android.os.Parcel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;
/**
*/
public class ParcelUtils {
private static final int FALSE = 0;
private static final int TRUE = 1;
private static final byte MARKER_NO_ELEMENT_STORED = 0;
private static final byte MARKER_AN_ELEMENT_STORED = 1;
private ParcelUtils() {
}
public static void writeBoolean(Parcel dest, boolean bool) {
dest.writeInt(bool ? 1 : 0);
}
public static boolean readBoolean(Parcel source) {
return source.readInt() == 1;
}
public static void writeDate(Parcel parcel, Date date) {
if (parcel != null) {
parcel.writeByte((byte) (date == null ? 0 : 1));
if (date != null) {
parcel.writeLong(date.getTime());
}
}
}
public static Date readDate(Parcel parcel) {
byte isADateStored = parcel.readByte();
return isADateStored == 1 ? new Date(parcel.readLong()) : null;
}
public static java.lang.Object byteToObject(byte[] bytes) {
java.lang.Object obj = null;
try {
//bytearray to object
ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
ObjectInputStream oi = new ObjectInputStream(bi);
obj = oi.readObject();
bi.close();
oi.close();
} catch (Exception e) {
System.out.println("translation" + e.getMessage());
e.printStackTrace();
}
return obj;
}
public byte[] ObjectToByte(java.lang.Object obj)
{
byte[] bytes = null;
try {
//object to bytearray
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(obj);
bytes = bo.toByteArray();
bo.close();
oo.close();
}
catch(Exception e) {
System.out.println("translation"+e.getMessage());
e.printStackTrace();
}
return(bytes);
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/PhotoMetadataUtils.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker.utils;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.media.ExifInterface;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.util.Log;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import io.valuesfeng.picker.MimeType;
import io.valuesfeng.picker.model.SelectionSpec;
/**
*/
public final class PhotoMetadataUtils {
public static final String TAG = PhotoMetadataUtils.class.getSimpleName();
private static final String SCHEME_CONTENT = "content";
private PhotoMetadataUtils() {
throw new AssertionError("oops! the utility class is about to be instantiated...");
}
public static int getPixelsCount(ContentResolver resolver, Uri uri) {
Point size = getBitmapBound(resolver, uri);
return size.x * size.y;
}
public static Point getBitmapSize(ContentResolver resolver, Uri uri, Activity activity) {
Point imageSize = getBitmapBound(resolver, uri);
int w = imageSize.x;
int h = imageSize.y;
if (PhotoMetadataUtils.shouldRotate(resolver, uri)) {
w = imageSize.y;
h = imageSize.x;
}
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
float screenWidth = (float) metrics.widthPixels;
float screenHeight = (float) metrics.heightPixels;
float widthScale = screenWidth / w;
float heightScale = screenHeight / h;
if (widthScale > heightScale) {
return new Point((int) (w * widthScale), (int)(h * heightScale));
}
return new Point((int) (w * widthScale), (int) (h * heightScale));
}
public static Point getBitmapBound(ContentResolver resolver, Uri uri) {
InputStream is = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
is = resolver.openInputStream(uri);
BitmapFactory.decodeStream(is, null, options);
int width = options.outWidth;
int height = options.outHeight;
return new Point(width, height);
} catch (FileNotFoundException e) {
return new Point(0, 0);
} finally {
CloseableUtils.close(is);
}
}
public static String getPath(ContentResolver resolver, Uri uri) {
if (uri == null) {
return null;
}
if (SCHEME_CONTENT.equals(uri.getScheme())) {
Cursor cursor = null;
try {
cursor = resolver.query(uri, new String[] { MediaStore.Images.ImageColumns.DATA }, null, null, null);
if (cursor == null || !cursor.moveToFirst()) {
return null;
}
return cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA));
} finally {
if(cursor != null) {
cursor.close();
}
}
}
return uri.getPath();
}
// public static UncapableCause isAcceptable(Context context, SelectionSpec spec, Uri uri) {
// if (!isSelectableType(context, spec, uri)) {
// return UncapableCause.FILE_TYPE;
// }
// if (!hasUnderAtMostQuality(context, spec, uri)) {
// return UncapableCause.OVER_COUNT;
// }
// if (!hasOverAtLeastQuality(context, spec, uri)) {
// return UncapableCause.UNDER_QUALITY;
// }
// return null;
// }
public static boolean hasOverAtLeastQuality(Context context, SelectionSpec spec, Uri uri) {
if (context == null) {
return false;
}
int pixels = PhotoMetadataUtils.getPixelsCount(context.getContentResolver(), uri);
return spec.getMinPixels() <= pixels;
}
public static boolean hasUnderAtMostQuality(Context context, SelectionSpec spec, Uri uri) {
if (context == null) {
return false;
}
int pixels = PhotoMetadataUtils.getPixelsCount(context.getContentResolver(), uri);
return pixels <= spec.getMaxPixels();
}
public static boolean isSelectableType(Context context, SelectionSpec spec, Uri uri) {
if (context == null) {
return false;
}
ContentResolver resolver = context.getContentResolver();
for (MimeType type : spec.getMimeTypeSet()) {
if (type.checkType(resolver, uri)) {
return true;
}
}
return false;
}
public static boolean shouldRotate(ContentResolver resolver, Uri uri) {
ExifInterface exif;
try {
exif = ExifInterfaceCompat.newInstance(getPath(resolver, uri));
} catch (IOException e) {
Log.e(TAG, "could not read exif info of the image: " + uri);
return false;
}
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
return orientation == ExifInterface.ORIENTATION_ROTATE_90
|| orientation == ExifInterface.ORIENTATION_ROTATE_270;
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/PicturePickerUtils.java
================================================
package io.valuesfeng.picker.utils;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.net.Uri;
import java.util.ArrayList;
import java.util.List;
import io.valuesfeng.picker.ImageSelectActivity;
/**
* Created by zaiyong on 2015/6/6.
*/
public class PicturePickerUtils {
private PicturePickerUtils() {
}
/**
* Obtains the selection result passed to your {@link Activity#onActivityResult(int, int, Intent)}.
*
* @param data the data.
* @return the selected {@link Uri}s.
*/
public static List<Uri> obtainResult(Intent data) {
return data.getParcelableArrayListExtra(ImageSelectActivity.EXTRA_RESULT_SELECTION);
}
public static List<String> obtainResult(ContentResolver resolver, Intent data) {
List<Uri> uris = data.getParcelableArrayListExtra(ImageSelectActivity.EXTRA_RESULT_SELECTION);
List<String> paths = new ArrayList<>();
for (Uri uri : uris) {
paths.add(PhotoMetadataUtils.getPath(resolver, uri));
}
return paths;
}
}
================================================
FILE: gallery/src/main/java/io/valuesfeng/picker/widget/GridViewItemRelativeLayout.java
================================================
/*
* Copyright (C) 2014 nohana, Inc.
*
* 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 io.valuesfeng.picker.widget;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import io.valuesfeng.picker.ImageSelectActivity;
import io.valuesfeng.picker.R;
import io.valuesfeng.picker.control.SelectedUriCollection;
import io.valuesfeng.picker.model.Picture;
/**
* @author KeithYokoma
* @version 1.0.0
* @hide
* @since 2014/03/24
*/
public class GridViewItemRelativeLayout extends RelativeLayout {
private ImageView imageView;
private ImageView imageCheck;
private Picture item;
SelectedUriCollection mCollection;
public GridViewItemRelativeLayout(Context context) {
this(context, null);
}
public GridViewItemRelativeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public GridViewItemRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
public void setImageView(ImageView imageView, ImageView imageCheck, SelectedUriCollection mCollection) {
this.imageView = imageView;
this.imageView.setMinimumWidth(getWidth());
this.imageView.setMinimumHeight(getHeight());
this.imageCheck = imageCheck;
this.mCollection = mCollection;
this.imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (GridViewItemRelativeLayout.this.mCollection.isCountOver()
&& !GridViewItemRelativeLayout.this.mCollection.isSelected(item.buildContentUri())) {
return;
}
if (item.isCapture()) {
((ImageSelectActivity) getContext()).showCameraAction();
return;
} else if (GridViewItemRelativeLayout.this.mCollection.isSingleChoose()) {
GridViewItemRelativeLayout.this.mCollection.add(item.buildContentUri());
((ImageSelectActivity) getContext()).setResult();
return;
}
if (GridViewItemRelativeLayout.this.mCollection.isSelected(item.buildContentUri())) {
GridViewItemRelativeLayout.this.mCollection.remove(item.buildContentUri());
GridViewItemRelativeLayout.this.imageCheck.setImageResource(R.drawable.pick_photo_checkbox_normal);
GridViewItemRelativeLayout.this.imageView.clearColorFilter();
} else {
GridViewItemRelativeLayout.this.mCollection.add(item.buildContentUri());
GridViewItemRelativeLayout.this.imageCheck.setImageResource(R.drawable.pick_photo_checkbox_check);
GridViewItemRelativeLayout.this.imageView.setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
}
}
});
}
public void setItem(Picture item) {
this.item = item;
imageView.clearColorFilter();
imageCheck.setImageResource(R.drawable.pick_photo_checkbox_normal);
if (mCollection.isSelected(item.buildContentUri())) {
imageView.setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
imageCheck.setImageResource(R.drawable.pick_photo_checkbox_check);
}
imageCheck.setVisibility(mCollection.isSingleChoose() || item.isCapture() ? View.GONE : View.VISIBLE);
disPlay();
}
private void disPlay() {
if (item.isCapture()) {
mCollection.getEngine().displayCameraItem(imageView);
// ImageLoader.getInstance().displayImage("drawable://" +, imageView, optionsCameraImage);
} else {
mCollection.getEngine().displayImage(item.buildContentUri().toString(), imageView);
// if (AlbumHelper.getInstance(getContext()).getThumbnail().containsKey(item.getId())) {
// String thumbnailuri = AlbumHelper.getInstance(getContext()).getThumbnail().get(item.getId());
// File file = new File(thumbnailuri);
// thumbnailuri = file.exists() && file.isFile() ? "file://" + thumbnailuri : item.buildContentUri().toString();
// ImageLoader.getInstance().displayImage("file://" + thumbnailuri, imageView, optionsImage);
// } else {
// ImageLoader.getInstance().displayImage(item.buildContentUri().toString(), imageView, optionsImage);
// }
// ImageLoader.getInstance().displayImage(item.buildContentUri().toString(), imageView, optionsImage);
}
}
}
================================================
FILE: gallery/src/main/res/anim/listview_down.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromYDelta="0%"
android:toYDelta="-100%" />
</set>
================================================
FILE: gallery/src/main/res/anim/listview_fade_in.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="200"
android:toAlpha="1"
android:fromAlpha="0" />
</set>
================================================
FILE: gallery/src/main/res/anim/listview_fade_out.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="200"
android:fromAlpha="1"
android:toAlpha="0" />
</set>
================================================
FILE: gallery/src/main/res/anim/listview_up.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromYDelta="-100%"
android:toYDelta="0%" />
</set>
================================================
FILE: gallery/src/main/res/drawable/pick_photo_checkbox.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@drawable/pick_photo_checkbox_check" />
<item android:state_checked="false" android:drawable="@drawable/pick_photo_checkbox_normal" />
<item android:drawable="@drawable/pick_photo_checkbox_normal" />
</selector>
================================================
FILE: gallery/src/main/res/layout/activity_image_select.xml
================================================
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="@+id/top_layout"
layout="@layout/include_select_image_top"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize" />
<GridView
android:id="@+id/gridView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/top_layout"
android:background="@android:color/white"
android:gravity="center"
android:horizontalSpacing="4dip"
android:numColumns="3"
android:padding="4dip"
android:stretchMode="columnWidth"
android:verticalSpacing="4dip" />
<FrameLayout
android:id="@+id/listViewParent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/top_layout"
android:background="#40000000"
android:paddingBottom="45dp"
android:visibility="invisible">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#55666666"
android:divider="@null"
android:dividerHeight="0dp" />
</FrameLayout>
</RelativeLayout>
================================================
FILE: gallery/src/main/res/layout/activity_main.xml
================================================
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView android:text="@string/hello_world" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
================================================
FILE: gallery/src/main/res/layout/include_select_image_top.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rl_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/top_bg">
<ImageView
android:id="@+id/btn_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:paddingLeft="17dp"
android:paddingRight="20dp"
android:scaleType="center"
android:src="@drawable/gallery_back" />
<LinearLayout
android:id="@+id/selectFold"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<TextView
android:id="@+id/foldName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="选择"
android:textColor="#d6d6d6"
android:textSize="14dp" />
<ImageView
android:id="@+id/gallery_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"
android:src="@drawable/gallery_down" />
</LinearLayout>
<Button
android:id="@+id/commit"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"
android:background="@null"
android:minHeight="1dp"
android:minWidth="1dp"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="5dp"
android:text="确定(3/4)"
android:textColor="#d6d6d6"
android:textSize="14dp" />
</RelativeLayout>
================================================
FILE: gallery/src/main/res/layout/photopick_gridlist_item.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<io.valuesfeng.picker.widget.GridViewItemRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rl"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
<ImageView
android:id="@+id/check"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentRight="true"
android:button="@drawable/pick_photo_checkbox" />
</io.valuesfeng.picker.widget.GridViewItemRelativeLayout>
================================================
FILE: gallery/src/main/res/layout/photopick_list_item.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#161616"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="49.5dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="28dp"
android:paddingRight="10dp">
<TextView
android:id="@+id/foldName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14dp"
android:textColor="#a7a7a7"
android:text="相机胶卷" />
<TextView
android:id="@+id/photoCount"
android:textSize="14dp"
android:textColor="#a7a7a7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(100)" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#1d1d1d" />
</LinearLayout>
================================================
FILE: gallery/src/main/res/menu/menu_main.xml
================================================
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="@+id/action_settings" android:title="@string/action_settings"
android:orderInCategory="100" app:showAsAction="never" />
</menu>
================================================
FILE: gallery/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="top_bg">#0f0f0f</color>
</resources>
================================================
FILE: gallery/src/main/res/values/dimens.xml
================================================
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="l_gridItemImageWidth">56dp</dimen>
<dimen name="l_gridItemImageHeight">56dp</dimen>
</resources>
================================================
FILE: gallery/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">gallery</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
<string name="l_album_name_all">最近图片</string>
<string name="l_album_name_selected">选择图片</string>
<string name="l_album_name_camera">相机</string>
<string name="l_album_name_download">下载</string>
<string name="l_album_name_screen_shot">屏幕截图</string>
<string name="l_album_name_confirm">确定</string>
<string name="l_album_name_unselected_picture">未选择图片</string>
<string name="l_confirm_dialog_title">提示</string>
<string name="l_confirm_dialog_message">您确定要放弃本次选择的图片吗?</string>
</resources>
================================================
FILE: gallery/src/main/res/values/styles.xml
================================================
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
================================================
FILE: gallery/src/main/res/values-en/strings.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">gallery</string>
<string name="action_settings">Settings</string>
<string name="l_album_name_all">All</string>
<string name="l_album_name_camera">Camera</string>
<string name="l_album_name_download">Downloads</string>
<string name="l_album_name_screen_shot">Screenshot</string>
<string name="l_album_name_selected">Selected</string>
<string name="l_album_name_confirm">Confirm</string>
<string name="l_album_name_unselected_picture">Unselected</string>
<string name="l_confirm_dialog_message">Do you want to give up this image selection?</string>
<string name="l_confirm_dialog_title">Done</string>
</resources>
================================================
FILE: gallery/src/main/res/values-ja/strings.xml
================================================
<resources>
<string name="app_name">gallery</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
<string name="l_album_name_all">最近の写真</string>
<string name="l_album_name_selected">画像を選択</string>
<string name="l_album_name_camera">カメラ</string>
<string name="l_album_name_download">ダウンロード</string>
<string name="l_album_name_screen_shot">スクリーンショット</string>
<string name="l_album_name_confirm">確定する</string>
<string name="l_album_name_unselected_picture">画像を選択していない</string>
<string name="l_confirm_dialog_title">ヒント</string>
<string name="l_confirm_dialog_message">あなたは今回選択した画像を放棄することを決定しますか?</string>
</resources>
================================================
FILE: gallery/src/main/res/values-pt/strings.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">galeria</string>
<string name="action_settings">Configurações</string>
<string name="l_album_name_all">Todos</string>
<string name="l_album_name_camera">Camera</string>
<string name="l_album_name_download">Downloads</string>
<string name="l_album_name_screen_shot">Capturas de tela</string>
<string name="l_album_name_selected">Selecionadas</string>
<string name="l_confirm_dialog_message">Deseja desistir da seleção de imagens?</string>
<string name="l_confirm_dialog_title">Concluir</string>
</resources>
================================================
FILE: gallery/src/main/res/values-w820dp/dimens.xml
================================================
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
================================================
FILE: gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: settings.gradle
================================================
include ':app', ':gallery'
gitextract_fhdrwt_g/ ├── .gitignore ├── README.md ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── io/ │ │ └── valuesfeng/ │ │ └── demo/ │ │ ├── MainActivity.java │ │ └── MainApp.java │ └── res/ │ ├── layout/ │ │ └── activity_main.xml │ ├── menu/ │ │ └── menu_main.xml │ ├── values/ │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── values-w820dp/ │ └── dimens.xml ├── build.gradle ├── gallery/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── io/ │ │ └── valuesfeng/ │ │ └── picker/ │ │ ├── ImageSelectActivity.java │ │ ├── MimeType.java │ │ ├── Picker.java │ │ ├── adapter/ │ │ │ ├── AlbumAdapter.java │ │ │ └── PictureAdapter.java │ │ ├── control/ │ │ │ ├── AlbumCollection.java │ │ │ ├── PictureCollection.java │ │ │ └── SelectedUriCollection.java │ │ ├── engine/ │ │ │ ├── GlideEngine.java │ │ │ ├── ImageLoaderEngine.java │ │ │ ├── LoadEngine.java │ │ │ └── PicassoEngine.java │ │ ├── loader/ │ │ │ ├── AlbumLoader.java │ │ │ └── PictureLoader.java │ │ ├── model/ │ │ │ ├── Album.java │ │ │ ├── Picture.java │ │ │ └── SelectionSpec.java │ │ ├── utils/ │ │ │ ├── BundleUtils.java │ │ │ ├── CloseableUtils.java │ │ │ ├── ExifInterfaceCompat.java │ │ │ ├── HandlerUtils.java │ │ │ ├── MediaStoreCompat.java │ │ │ ├── ParcelUtils.java │ │ │ ├── PhotoMetadataUtils.java │ │ │ └── PicturePickerUtils.java │ │ └── widget/ │ │ └── GridViewItemRelativeLayout.java │ └── res/ │ ├── anim/ │ │ ├── listview_down.xml │ │ ├── listview_fade_in.xml │ │ ├── listview_fade_out.xml │ │ └── listview_up.xml │ ├── drawable/ │ │ └── pick_photo_checkbox.xml │ ├── layout/ │ │ ├── activity_image_select.xml │ │ ├── activity_main.xml │ │ ├── include_select_image_top.xml │ │ ├── photopick_gridlist_item.xml │ │ └── photopick_list_item.xml │ ├── menu/ │ │ └── menu_main.xml │ ├── values/ │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ ├── values-en/ │ │ └── strings.xml │ ├── values-ja/ │ │ └── strings.xml │ ├── values-pt/ │ │ └── strings.xml │ └── values-w820dp/ │ └── dimens.xml ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle
SYMBOL INDEX (279 symbols across 28 files)
FILE: app/src/main/java/io/valuesfeng/demo/MainActivity.java
class MainActivity (line 21) | public class MainActivity extends FragmentActivity {
method onCreate (line 25) | @Override
method onActivityResult (line 31) | @Override
method onClickButton (line 42) | public void onClickButton(View view) {
class CustomEngine (line 53) | static class CustomEngine implements LoadEngine {
method displayImage (line 54) | @Override
method displayCameraItem (line 59) | @Override
method scrolling (line 64) | @Override
method describeContents (line 69) | @Override
method writeToParcel (line 74) | @Override
method CustomEngine (line 78) | public CustomEngine() {
method CustomEngine (line 82) | protected CustomEngine(Parcel in) {
method createFromParcel (line 86) | public CustomEngine createFromParcel(Parcel source) {
method newArray (line 90) | public CustomEngine[] newArray(int size) {
FILE: app/src/main/java/io/valuesfeng/demo/MainApp.java
class MainApp (line 16) | public class MainApp extends Application {
method onCreate (line 17) | @Override
FILE: gallery/src/main/java/io/valuesfeng/picker/ImageSelectActivity.java
class ImageSelectActivity (line 35) | public class ImageSelectActivity extends FragmentActivity implements Alb...
method onCreate (line 60) | @Override
method setResult (line 120) | public void setResult() {
method onClick (line 129) | @Override
method onSaveInstanceState (line 139) | @Override
method onRestoreInstanceState (line 147) | @Override
method onActivityResult (line 153) | @Override
method prepareCapture (line 168) | public void prepareCapture(String uri) {
method showFolderList (line 172) | private void showFolderList() {
method hideFolderList (line 184) | private void hideFolderList() {
method getMediaStoreCompat (line 207) | public MediaStoreCompat getMediaStoreCompat() {
method onDestroy (line 211) | @Override
method onBackPressed (line 218) | @Override
method showCameraAction (line 228) | public void showCameraAction() {
method onSelect (line 232) | @Override
method onReset (line 239) | @Override
FILE: gallery/src/main/java/io/valuesfeng/picker/MimeType.java
type MimeType (line 36) | @SuppressWarnings("unused") // public APIs
method MimeType (line 45) | MimeType(String mimeTypeName, Set<String> extensions) {
method allOf (line 50) | public static Set<MimeType> allOf() {
method of (line 54) | public static Set<MimeType> of(MimeType type) {
method of (line 58) | public static Set<MimeType> of(MimeType type, MimeType... rest) {
method toString (line 62) | @Override
method checkType (line 67) | public boolean checkType(ContentResolver resolver, Uri uri) {
FILE: gallery/src/main/java/io/valuesfeng/picker/Picker.java
class Picker (line 43) | public final class Picker {
method Picker (line 53) | Picker(Activity activity, Fragment fragment, Set<MimeType> mimeType) {
method Picker (line 64) | Picker(Activity activity, Fragment fragment) {
method setEngine (line 82) | public Picker setEngine(LoadEngine engine) {
method enableCamera (line 93) | public Picker enableCamera(boolean mEnableCamera) {
method startCamera (line 104) | public Picker startCamera(boolean mStartWithCamera) {
method count (line 116) | public Picker count(int min, int max) {
method count (line 128) | public Picker count(int max) {
method singleChoice (line 134) | public Picker singleChoice() {
method quality (line 147) | public Picker quality(int minPixel, int maxPixel) {
method resume (line 159) | public Picker resume(List<Uri> uriList) {
method forResult (line 172) | public void forResult(int requestCode) {
method from (line 196) | public static Picker from(Activity activity) {
method from (line 203) | public static Picker from(Activity activity, Set<MimeType> mimeType) {
method from (line 210) | public static Picker from(Fragment fragment) {
method from (line 217) | public static Picker from(Fragment fragment, Set<MimeType> mimeType) {
method getActivity (line 227) | @Nullable
method getFragment (line 235) | @Nullable
FILE: gallery/src/main/java/io/valuesfeng/picker/adapter/AlbumAdapter.java
class AlbumAdapter (line 37) | public class AlbumAdapter extends CursorAdapter {
method AlbumAdapter (line 41) | public AlbumAdapter(Context context, Cursor c) {
method newView (line 46) | @Override
method bindView (line 56) | @Override
class ViewHolder (line 64) | static class ViewHolder{
FILE: gallery/src/main/java/io/valuesfeng/picker/adapter/PictureAdapter.java
class PictureAdapter (line 35) | public class PictureAdapter extends CursorAdapter {
method PictureAdapter (line 39) | public PictureAdapter(Context context, Cursor c, SelectedUriCollection...
method newView (line 47) | @Override
method bindView (line 54) | @Override
class ViewHolder (line 60) | static class ViewHolder {
method ViewHolder (line 63) | public ViewHolder(View convertView, SelectedUriCollection mCollectio...
FILE: gallery/src/main/java/io/valuesfeng/picker/control/AlbumCollection.java
class AlbumCollection (line 44) | public class AlbumCollection implements LoaderManager.LoaderCallbacks<Cu...
method onCreateLoader (line 54) | @Override
method onLoadFinished (line 63) | @Override
method onLoaderReset (line 84) | @Override
method onCreate (line 93) | public void onCreate(FragmentActivity activity, OnDirectorySelectListe...
method onRestoreInstanceState (line 103) | public void onRestoreInstanceState(Bundle savedInstanceState) {
method onSaveInstanceState (line 110) | public void onSaveInstanceState(Bundle outState) {
method onDestroy (line 114) | public void onDestroy() {
method loadAlbums (line 119) | public void loadAlbums() {
method resetLoadAlbums (line 123) | public void resetLoadAlbums() {
method getCurrentSelection (line 128) | public int getCurrentSelection() {
method setStateCurrentSelection (line 132) | public void setStateCurrentSelection(int currentSelection) {
method onItemClick (line 136) | @Override
type OnDirectorySelectListener (line 145) | public interface OnDirectorySelectListener {
method onSelect (line 146) | void onSelect(Album album);
method onReset (line 148) | void onReset(Album album);
FILE: gallery/src/main/java/io/valuesfeng/picker/control/PictureCollection.java
class PictureCollection (line 38) | public class PictureCollection implements LoaderManager.LoaderCallbacks<...
method onCreateLoader (line 46) | @Override
method onLoadFinished (line 59) | @Override
method onLoaderReset (line 68) | @Override
method onCreate (line 77) | public void onCreate(@NonNull FragmentActivity context, @NonNull GridV...
method onDestroy (line 86) | public void onDestroy() {
method loadAllPhoto (line 90) | public void loadAllPhoto() {
method load (line 95) | public void load(@Nullable Album target) {
method resetLoad (line 101) | public void resetLoad(@Nullable Album target) {
FILE: gallery/src/main/java/io/valuesfeng/picker/control/SelectedUriCollection.java
class SelectedUriCollection (line 35) | public class SelectedUriCollection {
method SelectedUriCollection (line 43) | public SelectedUriCollection(Context context) {
method onCreate (line 47) | public void onCreate(Bundle savedInstanceState) {
method prepareSelectionSpec (line 56) | public void prepareSelectionSpec(SelectionSpec spec) {
method setDefaultSelection (line 60) | public void setDefaultSelection(List<Uri> uris) {
method onSaveInstanceState (line 64) | public void onSaveInstanceState(Bundle outState) {
method add (line 68) | public boolean add(Uri uri) {
method remove (line 74) | public boolean remove(Uri uri) {
method asList (line 80) | public List<Uri> asList() {
method isEmpty (line 84) | public boolean isEmpty() {
method isSelected (line 88) | public boolean isSelected(Uri uri) {
method isCountInRange (line 92) | public boolean isCountInRange() {
method isCountOver (line 96) | public boolean isCountOver() {
method count (line 100) | public int count() {
method maxCount (line 104) | public int maxCount() {
method isSingleChoose (line 108) | public boolean isSingleChoose() {
method getEngine (line 112) | public LoadEngine getEngine(){
method setOnSelectionChange (line 116) | public void setOnSelectionChange(OnSelectionChange onSelectionChange) {
type OnSelectionChange (line 120) | public interface OnSelectionChange{
method onChange (line 121) | void onChange(int maxCount,int selectCount);
FILE: gallery/src/main/java/io/valuesfeng/picker/engine/GlideEngine.java
class GlideEngine (line 23) | public class GlideEngine implements LoadEngine {
method GlideEngine (line 28) | public GlideEngine() {
method GlideEngine (line 32) | public GlideEngine(int img_loading) {
method GlideEngine (line 36) | public GlideEngine(int img_camera, int img_loading) {
method displayImage (line 47) | @Override
method displayCameraItem (line 59) | @Override
method chargeInit (line 71) | private void chargeInit(Context context) {
method scrolling (line 77) | @Override
method describeContents (line 82) | @Override
method writeToParcel (line 87) | @Override
method GlideEngine (line 93) | protected GlideEngine(Parcel in) {
method createFromParcel (line 99) | public GlideEngine createFromParcel(Parcel source) {
method newArray (line 103) | public GlideEngine[] newArray(int size) {
FILE: gallery/src/main/java/io/valuesfeng/picker/engine/ImageLoaderEngine.java
class ImageLoaderEngine (line 26) | public class ImageLoaderEngine implements LoadEngine {
method ImageLoaderEngine (line 34) | public ImageLoaderEngine() {
method ImageLoaderEngine (line 38) | public ImageLoaderEngine(int img_loading) {
method ImageLoaderEngine (line 42) | public ImageLoaderEngine(int img_loading, int img_camera) {
method displayImage (line 56) | @Override
method displayCameraItem (line 61) | @Override
method scrolling (line 66) | @Override
method getPathImageOptions (line 71) | private DisplayImageOptions getPathImageOptions() {
method getCameraOptions (line 89) | private DisplayImageOptions getCameraOptions() {
method describeContents (line 104) | @Override
method writeToParcel (line 109) | @Override
method ImageLoaderEngine (line 115) | protected ImageLoaderEngine(Parcel in) {
method createFromParcel (line 121) | public ImageLoaderEngine createFromParcel(Parcel source) {
method newArray (line 125) | public ImageLoaderEngine[] newArray(int size) {
FILE: gallery/src/main/java/io/valuesfeng/picker/engine/LoadEngine.java
type LoadEngine (line 20) | public interface LoadEngine extends Parcelable {
method displayCameraItem (line 23) | void displayCameraItem(ImageView imageView);
method displayImage (line 25) | void displayImage(String path, ImageView imageView);
method scrolling (line 27) | void scrolling(GridView view);
FILE: gallery/src/main/java/io/valuesfeng/picker/engine/PicassoEngine.java
class PicassoEngine (line 24) | public class PicassoEngine implements LoadEngine {
method PicassoEngine (line 29) | public PicassoEngine() {
method PicassoEngine (line 33) | public PicassoEngine(int img_loading) {
method PicassoEngine (line 37) | public PicassoEngine(int img_camera, int img_loading) {
method displayImage (line 48) | @Override
method displayCameraItem (line 60) | @Override
method scrolling (line 72) | @Override
method chargeInit (line 93) | private void chargeInit(Context context) {
method describeContents (line 99) | @Override
method writeToParcel (line 104) | @Override
method PicassoEngine (line 110) | protected PicassoEngine(Parcel in) {
method createFromParcel (line 116) | public PicassoEngine createFromParcel(Parcel source) {
method newArray (line 120) | public PicassoEngine[] newArray(int size) {
FILE: gallery/src/main/java/io/valuesfeng/picker/loader/AlbumLoader.java
class AlbumLoader (line 41) | public class AlbumLoader extends CursorLoader {
method newInstance (line 48) | public static CursorLoader newInstance(Context context, SelectionSpec ...
method AlbumLoader (line 52) | private AlbumLoader(Context context, Uri uri, String[] projection, Str...
method loadInBackground (line 56) | @Override
FILE: gallery/src/main/java/io/valuesfeng/picker/loader/PictureLoader.java
class PictureLoader (line 42) | public class PictureLoader extends CursorLoader {
method PictureLoader (line 48) | public PictureLoader(Context context, Uri uri, String[] projection, St...
method newInstance (line 53) | public static CursorLoader newInstance(Context context, Album album, S...
method loadInBackground (line 62) | @Override
FILE: gallery/src/main/java/io/valuesfeng/picker/model/Album.java
class Album (line 36) | public class Album implements Parcelable {
method createFromParcel (line 38) | @Nullable
method newArray (line 44) | @Override
method Album (line 61) | public Album(String id, long coverId, String albumName, String count) {
method Album (line 68) | Album(Parcel source) {
method valueOf (line 80) | public static Album valueOf(Cursor cursor) {
method describeContents (line 89) | @Override
method writeToParcel (line 94) | @Override
method getId (line 102) | public String getId() {
method getCoverId (line 106) | public long getCoverId() {
method getDisplayName (line 110) | public String getDisplayName(Context context) {
method buildContentUri (line 126) | public Uri buildContentUri() {
method isAll (line 130) | public boolean isAll() {
method isCamera (line 134) | public boolean isCamera() {
method getCount (line 138) | public String getCount() {
FILE: gallery/src/main/java/io/valuesfeng/picker/model/Picture.java
class Picture (line 36) | public class Picture implements Parcelable {
method createFromParcel (line 38) | @Override
method newArray (line 44) | @Override
method Picture (line 54) | Picture(long id,String displayName) {
method Picture (line 59) | Picture(Parcel source) {
method valueOf (line 63) | public static Picture valueOf(Cursor cursor) {
method describeContents (line 68) | @Override
method writeToParcel (line 73) | @Override
method getId (line 78) | public long getId() {
method buildContentUri (line 82) | public Uri buildContentUri() {
method getThumbnail (line 86) | public Bitmap getThumbnail(Context context) {
method isCapture (line 94) | public boolean isCapture() {
FILE: gallery/src/main/java/io/valuesfeng/picker/model/SelectionSpec.java
class SelectionSpec (line 33) | public final class SelectionSpec implements Parcelable {
method createFromParcel (line 35) | @Override
method newArray (line 40) | @Override
method SelectionSpec (line 54) | public SelectionSpec() {
method SelectionSpec (line 63) | SelectionSpec(Parcel source) {
method describeContents (line 76) | @Override
method writeToParcel (line 81) | @Override
method ismEnableCamera (line 93) | public boolean ismEnableCamera() {
method willStartCamera (line 97) | public boolean willStartCamera() { return mStartWithCamera; }
method setmEnableCamera (line 99) | public void setmEnableCamera(boolean mEnableCamera) {
method startWithCamera (line 103) | public void startWithCamera(boolean mStartWithCamera) { this.mStartWit...
method setMaxSelectable (line 105) | public void setMaxSelectable(int maxSelectable) {
method setMinSelectable (line 109) | public void setMinSelectable(int minSelectable) {
method setMinPixels (line 113) | public void setMinPixels(long minPixels) {
method setMaxPixels (line 117) | public void setMaxPixels(long maxPixels) {
method setMimeTypeSet (line 121) | public void setMimeTypeSet(Set<MimeType> set) {
method getMinSelectable (line 125) | public int getMinSelectable() {
method getMaxSelectable (line 129) | public int getMaxSelectable() {
method getMinPixels (line 133) | public long getMinPixels() {
method getEngine (line 137) | public LoadEngine getEngine() {
method setEngine (line 141) | public void setEngine(LoadEngine engine) {
method isSingleChoose (line 145) | public boolean isSingleChoose() {
method getMaxPixels (line 153) | public long getMaxPixels() {
method getMimeTypeSet (line 157) | public Set<MimeType> getMimeTypeSet() {
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/BundleUtils.java
class BundleUtils (line 6) | public class BundleUtils {
method BundleUtils (line 7) | private BundleUtils() {
method buildKey (line 10) | public static String buildKey(Class<?> clazz, String name) {
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/CloseableUtils.java
class CloseableUtils (line 11) | public class CloseableUtils {
method CloseableUtils (line 15) | private CloseableUtils() {
method close (line 18) | public static final void close(Closeable closeable) {
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/ExifInterfaceCompat.java
class ExifInterfaceCompat (line 17) | public final class ExifInterfaceCompat {
method ExifInterfaceCompat (line 20) | private ExifInterfaceCompat() {
method newInstance (line 23) | public static final ExifInterface newInstance(String filename) throws ...
method getExifDateTime (line 31) | public static final Date getExifDateTime(String filepath) {
method getExifDateTimeInMillis (line 56) | public static final long getExifDateTimeInMillis(String filepath) {
method getExifOrientation (line 61) | public static final int getExifOrientation(String filepath) {
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/HandlerUtils.java
class HandlerUtils (line 8) | public class HandlerUtils {
method HandlerUtils (line 9) | private HandlerUtils() {
method getMainHandler (line 12) | public static Handler getMainHandler() {
method postOnMain (line 16) | public static void postOnMain(Runnable message) {
method postOnMainWithDelay (line 20) | public static void postOnMainWithDelay(Runnable message, long delayMil...
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/MediaStoreCompat.java
class MediaStoreCompat (line 36) | public class MediaStoreCompat {
method MediaStoreCompat (line 46) | public MediaStoreCompat(Context context, final Handler handler) {
method hasCameraFeature (line 58) | public static final boolean hasCameraFeature(Context context) {
method invokeCameraCapture (line 63) | public String invokeCameraCapture(Activity activity, int requestCode) {
method destroy (line 81) | public void destroy() {
method getCapturedPhotoUri (line 85) | public Uri getCapturedPhotoUri(Intent data, String preparedUri) {
method cleanUp (line 110) | public void cleanUp(String uri) {
method getPathFromUri (line 118) | public static String getPathFromUri(ContentResolver resolver, Uri cont...
method copyFileStream (line 142) | public static long copyFileStream(FileInputStream is, FileOutputStream...
method findPhotoFromRecentlyTaken (line 161) | private Uri findPhotoFromRecentlyTaken(File file) {
method storeImage (line 193) | private Uri storeImage(File file) {
method updateLatestPhotos (line 219) | private void updateLatestPhotos() {
method generateThumbnails (line 243) | private void generateThumbnails(long imageId) {
method getOutputFileUri (line 251) | @TargetApi(8)
class PhotoContent (line 262) | private static class PhotoContent {
method PhotoContent (line 267) | private PhotoContent() {
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/ParcelUtils.java
class ParcelUtils (line 13) | public class ParcelUtils {
method ParcelUtils (line 19) | private ParcelUtils() {
method writeBoolean (line 22) | public static void writeBoolean(Parcel dest, boolean bool) {
method readBoolean (line 26) | public static boolean readBoolean(Parcel source) {
method writeDate (line 30) | public static void writeDate(Parcel parcel, Date date) {
method readDate (line 39) | public static Date readDate(Parcel parcel) {
method byteToObject (line 44) | public static java.lang.Object byteToObject(byte[] bytes) {
method ObjectToByte (line 61) | public byte[] ObjectToByte(java.lang.Object obj)
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/PhotoMetadataUtils.java
class PhotoMetadataUtils (line 40) | public final class PhotoMetadataUtils {
method PhotoMetadataUtils (line 44) | private PhotoMetadataUtils() {
method getPixelsCount (line 48) | public static int getPixelsCount(ContentResolver resolver, Uri uri) {
method getBitmapSize (line 53) | public static Point getBitmapSize(ContentResolver resolver, Uri uri, A...
method getBitmapBound (line 73) | public static Point getBitmapBound(ContentResolver resolver, Uri uri) {
method getPath (line 90) | public static String getPath(ContentResolver resolver, Uri uri) {
method hasOverAtLeastQuality (line 125) | public static boolean hasOverAtLeastQuality(Context context, Selection...
method hasUnderAtMostQuality (line 134) | public static boolean hasUnderAtMostQuality(Context context, Selection...
method isSelectableType (line 143) | public static boolean isSelectableType(Context context, SelectionSpec ...
method shouldRotate (line 157) | public static boolean shouldRotate(ContentResolver resolver, Uri uri) {
FILE: gallery/src/main/java/io/valuesfeng/picker/utils/PicturePickerUtils.java
class PicturePickerUtils (line 16) | public class PicturePickerUtils {
method PicturePickerUtils (line 18) | private PicturePickerUtils() {
method obtainResult (line 27) | public static List<Uri> obtainResult(Intent data) {
method obtainResult (line 31) | public static List<String> obtainResult(ContentResolver resolver, Inte...
FILE: gallery/src/main/java/io/valuesfeng/picker/widget/GridViewItemRelativeLayout.java
class GridViewItemRelativeLayout (line 42) | public class GridViewItemRelativeLayout extends RelativeLayout {
method GridViewItemRelativeLayout (line 49) | public GridViewItemRelativeLayout(Context context) {
method GridViewItemRelativeLayout (line 53) | public GridViewItemRelativeLayout(Context context, AttributeSet attrs) {
method GridViewItemRelativeLayout (line 57) | public GridViewItemRelativeLayout(Context context, AttributeSet attrs,...
method onMeasure (line 61) | @Override
method setImageView (line 66) | public void setImageView(ImageView imageView, ImageView imageCheck, Se...
method setItem (line 100) | public void setItem(Picture item) {
method disPlay (line 112) | private void disPlay() {
Condensed preview — 70 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (141K chars).
[
{
"path": ".gitignore",
"chars": 538,
"preview": "#built application files\n*.apk\n*.ap_\n\n# files for the dex VM\n*.dex\n\n# Java class files\n*.class\n\n# generated files\nbin/\ng"
},
{
"path": "README.md",
"chars": 3875,
"preview": "# AndroidPicturePicker\n\n\n##Thanks for : \n[Laevatein](https://github.com/nohana/Laevatein):Photo image selection activ"
},
{
"path": "app/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "app/build.gradle",
"chars": 974,
"preview": "apply plugin: 'com.android.application'\n\nandroid {\n compileSdkVersion 23\n buildToolsVersion \"23.0.2\"\n\n defaultC"
},
{
"path": "app/proguard-rules.pro",
"chars": 662,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in D:"
},
{
"path": "app/src/main/AndroidManifest.xml",
"chars": 1089,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package="
},
{
"path": "app/src/main/java/io/valuesfeng/demo/MainActivity.java",
"chars": 2652,
"preview": "package io.valuesfeng.demo;\n\nimport android.content.Intent;\nimport android.net.Uri;\nimport android.os.Bundle;\nimport and"
},
{
"path": "app/src/main/java/io/valuesfeng/demo/MainApp.java",
"chars": 1762,
"preview": "package io.valuesfeng.demo;\n\nimport android.app.Application;\nimport android.graphics.Bitmap;\n\nimport com.nostra13.univer"
},
{
"path": "app/src/main/res/layout/activity_main.xml",
"chars": 702,
"preview": "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:tools=\"http://schemas.android.com/t"
},
{
"path": "app/src/main/res/menu/menu_main.xml",
"chars": 361,
"preview": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:app=\"http://schemas.android.com/apk/res-auto\""
},
{
"path": "app/src/main/res/values/dimens.xml",
"chars": 211,
"preview": "<resources>\n <!-- Default screen margins, per the Android Design guidelines. -->\n <dimen name=\"activity_horizontal"
},
{
"path": "app/src/main/res/values/strings.xml",
"chars": 186,
"preview": "<resources>\n <string name=\"app_name\">FotoplaceGallery</string>\n\n <string name=\"hello_world\">Hello world!</string>\n"
},
{
"path": "app/src/main/res/values/styles.xml",
"chars": 194,
"preview": "<resources>\n\n <!-- Base application theme. -->\n <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
},
{
"path": "app/src/main/res/values-w820dp/dimens.xml",
"chars": 358,
"preview": "<resources>\n <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n (such as s"
},
{
"path": "build.gradle",
"chars": 436,
"preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n r"
},
{
"path": "gallery/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "gallery/build.gradle",
"chars": 827,
"preview": "apply plugin: 'com.android.library'\n\nandroid {\n compileSdkVersion 23\n buildToolsVersion \"23.0.2\"\n\n defaultConfi"
},
{
"path": "gallery/proguard-rules.pro",
"chars": 662,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in D:"
},
{
"path": "gallery/src/main/AndroidManifest.xml",
"chars": 438,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package="
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/ImageSelectActivity.java",
"chars": 9495,
"preview": "package io.valuesfeng.picker;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.net.Uri;\nimpor"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/MimeType.java",
"chars": 2553,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/Picker.java",
"chars": 7341,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/adapter/AlbumAdapter.java",
"chars": 2302,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/adapter/PictureAdapter.java",
"chars": 2497,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/control/AlbumCollection.java",
"chars": 5021,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/control/PictureCollection.java",
"chars": 3661,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/control/SelectedUriCollection.java",
"chars": 3603,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/engine/GlideEngine.java",
"chars": 2838,
"preview": "package io.valuesfeng.picker.engine;\n\nimport android.content.Context;\nimport android.os.Parcel;\nimport android.widget.Gr"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/engine/ImageLoaderEngine.java",
"chars": 4074,
"preview": "package io.valuesfeng.picker.engine;\n\nimport android.graphics.Bitmap;\nimport android.os.Parcel;\nimport android.widget.Gr"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/engine/LoadEngine.java",
"chars": 809,
"preview": "package io.valuesfeng.picker.engine;\n\nimport android.os.Parcelable;\nimport android.widget.GridView;\nimport android.widge"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/engine/PicassoEngine.java",
"chars": 3575,
"preview": "package io.valuesfeng.picker.engine;\n\nimport android.content.Context;\nimport android.os.Parcel;\nimport android.widget.Ab"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/loader/AlbumLoader.java",
"chars": 2872,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/loader/PictureLoader.java",
"chars": 3030,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/model/Album.java",
"chars": 4252,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/model/Picture.java",
"chars": 3068,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/model/SelectionSpec.java",
"chars": 4540,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/utils/BundleUtils.java",
"chars": 269,
"preview": "package io.valuesfeng.picker.utils;\n\n/**\n * Created by zaiyong on 2015/6/6.\n */\npublic class BundleUtils {\n private B"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/utils/CloseableUtils.java",
"chars": 589,
"preview": "package io.valuesfeng.picker.utils;\n\nimport android.util.Log;\n\nimport java.io.Closeable;\nimport java.io.IOException;\n\n/*"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/utils/ExifInterfaceCompat.java",
"chars": 2485,
"preview": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage io.val"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/utils/HandlerUtils.java",
"chars": 517,
"preview": "package io.valuesfeng.picker.utils;\n\nimport android.os.Handler;\nimport android.os.Looper;\n\n/**\n */\npublic class HandlerU"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/utils/MediaStoreCompat.java",
"chars": 9602,
"preview": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage io.val"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/utils/ParcelUtils.java",
"chars": 2248,
"preview": "package io.valuesfeng.picker.utils;\n\nimport android.os.Parcel;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.Byte"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/utils/PhotoMetadataUtils.java",
"chars": 6025,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/utils/PicturePickerUtils.java",
"chars": 1111,
"preview": "package io.valuesfeng.picker.utils;\n\nimport android.app.Activity;\nimport android.content.ContentResolver;\nimport android"
},
{
"path": "gallery/src/main/java/io/valuesfeng/picker/widget/GridViewItemRelativeLayout.java",
"chars": 5696,
"preview": "/*\n * Copyright (C) 2014 nohana, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
},
{
"path": "gallery/src/main/res/anim/listview_down.xml",
"chars": 226,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <translate\n "
},
{
"path": "gallery/src/main/res/anim/listview_fade_in.xml",
"chars": 213,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <alpha\n "
},
{
"path": "gallery/src/main/res/anim/listview_fade_out.xml",
"chars": 213,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <alpha\n "
},
{
"path": "gallery/src/main/res/anim/listview_up.xml",
"chars": 224,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <translate\n "
},
{
"path": "gallery/src/main/res/drawable/pick_photo_checkbox.xml",
"chars": 387,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <item "
},
{
"path": "gallery/src/main/res/layout/activity_image_select.xml",
"chars": 1446,
"preview": "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:layout_width=\"match_parent\"\n a"
},
{
"path": "gallery/src/main/res/layout/activity_main.xml",
"chars": 621,
"preview": "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:tools=\"http://schemas.android.com/t"
},
{
"path": "gallery/src/main/res/layout/include_select_image_top.xml",
"chars": 2220,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n an"
},
{
"path": "gallery/src/main/res/layout/photopick_gridlist_item.xml",
"chars": 728,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<io.valuesfeng.picker.widget.GridViewItemRelativeLayout xmlns:android=\"http://sch"
},
{
"path": "gallery/src/main/res/layout/photopick_list_item.xml",
"chars": 1268,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n andr"
},
{
"path": "gallery/src/main/res/menu/menu_main.xml",
"chars": 361,
"preview": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:app=\"http://schemas.android.com/apk/res-auto\""
},
{
"path": "gallery/src/main/res/values/colors.xml",
"chars": 104,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <color name=\"top_bg\">#0f0f0f</color>\n</resources>"
},
{
"path": "gallery/src/main/res/values/dimens.xml",
"chars": 316,
"preview": "<resources>\n <!-- Default screen margins, per the Android Design guidelines. -->\n <dimen name=\"activity_horizontal"
},
{
"path": "gallery/src/main/res/values/strings.xml",
"chars": 685,
"preview": "<resources>\n <string name=\"app_name\">gallery</string>\n\n <string name=\"hello_world\">Hello world!</string>\n <stri"
},
{
"path": "gallery/src/main/res/values/styles.xml",
"chars": 194,
"preview": "<resources>\n\n <!-- Base application theme. -->\n <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
},
{
"path": "gallery/src/main/res/values-en/strings.xml",
"chars": 730,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <string name=\"app_name\">gallery</string>\n <string name=\"action"
},
{
"path": "gallery/src/main/res/values-ja/strings.xml",
"chars": 716,
"preview": "<resources>\n <string name=\"app_name\">gallery</string>\n <string name=\"hello_world\">Hello world!</string>\n <strin"
},
{
"path": "gallery/src/main/res/values-pt/strings.xml",
"chars": 617,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <string name=\"app_name\">galeria</string>\n <string name=\"action"
},
{
"path": "gallery/src/main/res/values-w820dp/dimens.xml",
"chars": 358,
"preview": "<resources>\n <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n (such as s"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 232,
"preview": "#Wed Apr 10 15:27:10 PDT 2013\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
},
{
"path": "gradle.properties",
"chars": 855,
"preview": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will o"
},
{
"path": "gradlew",
"chars": 5080,
"preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n## Gradle start "
},
{
"path": "gradlew.bat",
"chars": 2314,
"preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
},
{
"path": "settings.gradle",
"chars": 27,
"preview": "include ':app', ':gallery'\n"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the ValuesFeng/AndroidPicturePicker GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 70 files (127.1 KB), approximately 31.1k tokens, and a symbol index with 279 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.