images) {
for (TImage image : images) {
if (TImage.FromType.CAMERA == fromType) {
TFileUtils.delete(image.getOriginalPath());
image.setOriginalPath("");
}
}
}
private void handleTakeCallBack(final TResult result, String... message) {
if (message.length > 0) {
listener.takeFail(result, message[0]);
} else if (multipleCrop != null && multipleCrop.hasFailed) {
listener.takeFail(result, contextWrap.getActivity().getResources().getString(org.devio.takephoto.R.string.msg_crop_failed));
} else if (compressConfig != null) {
boolean hasFailed = false;
for (TImage image : result.getImages()) {
if (image == null || !image.isCompressed()) {
hasFailed = true;
break;
}
}
if (hasFailed) {
listener.takeFail(result, contextWrap.getActivity().getString(org.devio.takephoto.R.string.msg_compress_failed));
} else {
listener.takeSuccess(result);
}
} else {
listener.takeSuccess(result);
}
clearParams();
}
private void clearParams() {
compressConfig = null;
takePhotoOptions = null;
cropOptions = null;
multipleCrop = null;
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressConfig.java
================================================
package org.devio.takephoto.compress;
import org.devio.takephoto.model.LubanOptions;
import java.io.Serializable;
/**
* 压缩配置类
* Author: JPH
* Date: 2016/6/7 0007 18:01
*/
public class CompressConfig implements Serializable {
/**
* 长或宽不超过的最大像素,单位px
*/
private int maxPixel = 1200;
/**
* 压缩到的最大大小,单位B
*/
private int maxSize = 100 * 1024;
/**
* 是否启用像素压缩
*/
private boolean enablePixelCompress = true;
/**
* 是否启用质量压缩
*/
private boolean enableQualityCompress = true;
/**
* 是否保留原文件
*/
private boolean enableReserveRaw = true;
/**
* Luban压缩配置
*/
private LubanOptions lubanOptions;
public static CompressConfig ofDefaultConfig() {
return new CompressConfig();
}
public static CompressConfig ofLuban(LubanOptions options) {
return new CompressConfig(options);
}
private CompressConfig() {
}
private CompressConfig(LubanOptions options) {
this.lubanOptions = options;
}
public LubanOptions getLubanOptions() {
return lubanOptions;
}
public int getMaxPixel() {
return maxPixel;
}
public CompressConfig setMaxPixel(int maxPixel) {
this.maxPixel = maxPixel;
return this;
}
public int getMaxSize() {
return maxSize;
}
public void setMaxSize(int maxSize) {
this.maxSize = maxSize;
}
public boolean isEnablePixelCompress() {
return enablePixelCompress;
}
public void enablePixelCompress(boolean enablePixelCompress) {
this.enablePixelCompress = enablePixelCompress;
}
public boolean isEnableQualityCompress() {
return enableQualityCompress;
}
public void enableQualityCompress(boolean enableQualityCompress) {
this.enableQualityCompress = enableQualityCompress;
}
public boolean isEnableReserveRaw() {
return enableReserveRaw;
}
public void enableReserveRaw(boolean enableReserveRaw) {
this.enableReserveRaw = enableReserveRaw;
}
public static class Builder {
private CompressConfig config;
public Builder() {
config = new CompressConfig();
}
public Builder setMaxSize(int maxSize) {
config.setMaxSize(maxSize);
return this;
}
public Builder setMaxPixel(int maxPixel) {
config.setMaxPixel(maxPixel);
return this;
}
public Builder enablePixelCompress(boolean enablePixelCompress) {
config.enablePixelCompress(enablePixelCompress);
return this;
}
public Builder enableQualityCompress(boolean enableQualityCompress) {
config.enableQualityCompress(enableQualityCompress);
return this;
}
public Builder enableReserveRaw(boolean enableReserveRaw) {
config.enableReserveRaw(enableReserveRaw);
return this;
}
public CompressConfig create() {
return config;
}
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressImage.java
================================================
package org.devio.takephoto.compress;
import org.devio.takephoto.model.TImage;
import java.util.ArrayList;
/**
* 压缩照片2.0
*
* Author JPH
* Date 2015-08-26 下午1:44:26
*/
public interface CompressImage {
void compress();
/**
* 压缩结果监听器
*/
interface CompressListener {
/**
* 压缩成功
*
* @param images 已经压缩图片
*/
void onCompressSuccess(ArrayList images);
/**
* 压缩失败
*
* @param images 压缩失败的图片
* @param msg 失败的原因
*/
void onCompressFailed(ArrayList images, String msg);
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressImageImpl.java
================================================
package org.devio.takephoto.compress;
import android.content.Context;
import android.text.TextUtils;
import org.devio.takephoto.model.TImage;
import java.io.File;
import java.util.ArrayList;
/**
* 压缩照片
*
* Date: 2016/9/21 0007 20:10
* Version:3.0.0
* 技术博文:http://www.devio.org
* GitHub:https://github.com/crazycodeboy
* Email:crazycodeboy@gmail.com
*/
public class CompressImageImpl implements CompressImage {
private CompressImageUtil compressImageUtil;
private ArrayList images;
private CompressImage.CompressListener listener;
public static CompressImage of(Context context, CompressConfig config, ArrayList images,
CompressImage.CompressListener listener) {
if (config.getLubanOptions() != null) {
return new CompressWithLuBan(context, config, images, listener);
} else {
return new CompressImageImpl(context, config, images, listener);
}
}
private CompressImageImpl(Context context, CompressConfig config, ArrayList images, CompressImage.CompressListener listener) {
compressImageUtil = new CompressImageUtil(context, config);
this.images = images;
this.listener = listener;
}
@Override
public void compress() {
if (images == null || images.isEmpty()) {
listener.onCompressFailed(images, " images is null");
}
for (TImage image : images) {
if (image == null) {
listener.onCompressFailed(images, " There are pictures of compress is null.");
return;
}
}
compress(images.get(0));
}
private void compress(final TImage image) {
if (TextUtils.isEmpty(image.getOriginalPath())) {
continueCompress(image, false);
return;
}
File file = new File(image.getOriginalPath());
if (file == null || !file.exists() || !file.isFile()) {
continueCompress(image, false);
return;
}
compressImageUtil.compress(image.getOriginalPath(), new CompressImageUtil.CompressListener() {
@Override
public void onCompressSuccess(String imgPath) {
image.setCompressPath(imgPath);
continueCompress(image, true);
}
@Override
public void onCompressFailed(String imgPath, String msg) {
continueCompress(image, false, msg);
}
});
}
private void continueCompress(TImage image, boolean preSuccess, String... message) {
image.setCompressed(preSuccess);
int index = images.indexOf(image);
boolean isLast = index == images.size() - 1;
if (isLast) {
handleCompressCallBack(message);
} else {
compress(images.get(index + 1));
}
}
private void handleCompressCallBack(String... message) {
if (message.length > 0) {
listener.onCompressFailed(images, message[0]);
return;
}
for (TImage image : images) {
if (!image.isCompressed()) {
listener.onCompressFailed(images, image.getCompressPath() + " is compress failures");
return;
}
}
listener.onCompressSuccess(images);
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressImageUtil.java
================================================
package org.devio.takephoto.compress;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.os.Handler;
import org.devio.takephoto.uitl.TFileUtils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
/**
* 压缩照片
*
* @author JPH
* Date 2015-08-26 下午1:44:26
* Version:1.0.3
*/
public class CompressImageUtil {
private CompressConfig config;
private Context context;
Handler mhHandler = new Handler();
public CompressImageUtil(Context context, CompressConfig config) {
this.context = context;
this.config = config == null ? CompressConfig.ofDefaultConfig() : config;
}
public void compress(String imagePath, CompressListener listener) {
if (config.isEnablePixelCompress()) {
try {
compressImageByPixel(imagePath, listener);
} catch (FileNotFoundException e) {
listener.onCompressFailed(imagePath, String.format("图片压缩失败,%s", e.toString()));
e.printStackTrace();
}
} else {
compressImageByQuality(BitmapFactory.decodeFile(imagePath), imagePath, listener);
}
}
/**
* 多线程压缩图片的质量
*
* @param bitmap 内存中的图片
* @param imgPath 图片的保存路径
* @author JPH
* @date 2014-12-5下午11:30:43
*/
private void compressImageByQuality(final Bitmap bitmap, final String imgPath, final CompressListener listener) {
if (bitmap == null) {
sendMsg(false, imgPath, "像素压缩失败,bitmap is null", listener);
return;
}
new Thread(new Runnable() {//开启多线程进行压缩处理
@Override
public void run() {
// TODO Auto-generated method stub
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int options = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//质量压缩方法,把压缩后的数据存放到baos中 (100表示不压缩,0表示压缩到最小)
while (baos.toByteArray().length > config.getMaxSize()) {//循环判断如果压缩后图片是否大于指定大小,大于继续压缩
baos.reset();//重置baos即让下一次的写入覆盖之前的内容
options -= 5;//图片质量每次减少5
if (options <= 5) {
options = 5;//如果图片质量小于5,为保证压缩后的图片质量,图片最底压缩质量为5
}
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//将压缩后的图片保存到baos中
if (options == 5) {
break;//如果图片的质量已降到最低则,不再进行压缩
}
}
// if(bitmap!=null&&!bitmap.isRecycled()){
// bitmap.recycle();//回收内存中的图片
// }
try {
File thumbnailFile = getThumbnailFile(new File(imgPath));
FileOutputStream fos = new FileOutputStream(thumbnailFile);//将压缩后的图片保存的本地上指定路径中
fos.write(baos.toByteArray());
fos.flush();
fos.close();
sendMsg(true, thumbnailFile.getPath(), null, listener);
} catch (Exception e) {
sendMsg(false, imgPath, "质量压缩失败", listener);
e.printStackTrace();
}
}
}).start();
}
/**
* 按比例缩小图片的像素以达到压缩的目的
*
* @param imgPath
* @return
* @author JPH
* @date 2014-12-5下午11:30:59
*/
private void compressImageByPixel(String imgPath, CompressListener listener) throws FileNotFoundException {
if (imgPath == null) {
sendMsg(false, imgPath, "要压缩的文件不存在", listener);
return;
}
BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inJustDecodeBounds = true;//只读边,不读内容
BitmapFactory.decodeFile(imgPath, newOpts);
newOpts.inJustDecodeBounds = false;
int width = newOpts.outWidth;
int height = newOpts.outHeight;
float maxSize = config.getMaxPixel();
int be = 1;
if (width >= height && width > maxSize) {//缩放比,用高或者宽其中较大的一个数据进行计算
be = (int) (newOpts.outWidth / maxSize);
be++;
} else if (width < height && height > maxSize) {
be = (int) (newOpts.outHeight / maxSize);
be++;
}
newOpts.inSampleSize = be;//设置采样率
newOpts.inPreferredConfig = Config.ARGB_8888;//该模式是默认的,可不设
newOpts.inPurgeable = true;// 同时设置才会有效
newOpts.inInputShareable = true;//。当系统内存不够时候图片自动被回收
Bitmap bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
if (config.isEnableQualityCompress()) {
compressImageByQuality(bitmap, imgPath, listener);//压缩好比例大小后再进行质量压缩
} else {
File thumbnailFile = getThumbnailFile(new File(imgPath));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(thumbnailFile));
listener.onCompressSuccess(thumbnailFile.getPath());
}
}
/**
* 发送压缩结果的消息
*
* @param isSuccess 压缩是否成功
* @param imagePath
* @param message
*/
private void sendMsg(final boolean isSuccess, final String imagePath, final String message, final CompressListener listener) {
mhHandler.post(new Runnable() {
@Override
public void run() {
if (isSuccess) {
listener.onCompressSuccess(imagePath);
} else {
listener.onCompressFailed(imagePath, message);
}
}
});
}
private File getThumbnailFile(File file) {
if (file == null || !file.exists()) {
return file;
}
return TFileUtils.getPhotoCacheDir(context, file);
}
/**
* 压缩结果监听器
*/
public interface CompressListener {
/**
* 压缩成功
*
* @param imgPath 压缩图片的路径
*/
void onCompressSuccess(String imgPath);
/**
* 压缩失败
*
* @param imgPath 压缩失败的图片
* @param msg 失败的原因
*/
void onCompressFailed(String imgPath, String msg);
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressWithLuBan.java
================================================
package org.devio.takephoto.compress;
import android.content.Context;
import org.devio.takephoto.model.LubanOptions;
import org.devio.takephoto.model.TImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import me.shaohui.advancedluban.Luban;
import me.shaohui.advancedluban.OnCompressListener;
import me.shaohui.advancedluban.OnMultiCompressListener;
/**
* 压缩照片,采用luban
* Author: crazycodeboy
* Date: 2016/11/5 0007 20:10
* Version:4.0.0
* 技术博文:http://www.devio.org/
* GitHub:https://github.com/crazycodeboy
* Email:crazycodeboy@gmail.com
*/
public class CompressWithLuBan implements CompressImage {
private ArrayList images;
private CompressListener listener;
private Context context;
private LubanOptions options;
private ArrayList files = new ArrayList<>();
public CompressWithLuBan(Context context, CompressConfig config, ArrayList images, CompressListener listener) {
options = config.getLubanOptions();
this.images = images;
this.listener = listener;
this.context = context;
}
@Override
public void compress() {
if (images == null || images.isEmpty()) {
listener.onCompressFailed(images, " images is null");
return;
}
for (TImage image : images) {
if (image == null) {
listener.onCompressFailed(images, " There are pictures of compress is null.");
return;
}
files.add(new File(image.getOriginalPath()));
}
if (images.size() == 1) {
compressOne();
} else {
compressMulti();
}
}
private void compressOne() {
Luban.compress(context, files.get(0))
.putGear(Luban.CUSTOM_GEAR)
.setMaxHeight(options.getMaxHeight())
.setMaxWidth(options.getMaxWidth())
.setMaxSize(options.getMaxSize() / 1000)
.launch(new OnCompressListener() {
@Override
public void onStart() {
}
@Override
public void onSuccess(File file) {
TImage image = images.get(0);
image.setCompressPath(file.getPath());
image.setCompressed(true);
listener.onCompressSuccess(images);
}
@Override
public void onError(Throwable e) {
listener.onCompressFailed(images, e.getMessage() + " is compress failures");
}
});
}
private void compressMulti() {
Luban.compress(context, files)
.putGear(Luban.CUSTOM_GEAR)
.setMaxSize(options.getMaxSize() / 1000) // limit the final image size(unit:Kb)
.setMaxHeight(options.getMaxHeight()) // limit image height
.setMaxWidth(options.getMaxWidth())
.launch(new OnMultiCompressListener() {
@Override
public void onStart() {
}
@Override
public void onSuccess(List fileList) {
handleCompressCallBack(fileList);
}
@Override
public void onError(Throwable e) {
listener.onCompressFailed(images, e.getMessage() + " is compress failures");
}
});
}
private void handleCompressCallBack(List files) {
for (int i = 0, j = images.size(); i < j; i++) {
TImage image = images.get(i);
image.setCompressed(true);
image.setCompressPath(files.get(i).getPath());
}
listener.onCompressSuccess(images);
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/CropOptions.java
================================================
package org.devio.takephoto.model;
import java.io.Serializable;
/**
* 裁剪配置类
* Author: JPH
* Date: 2016/7/27 13:19
*/
public class CropOptions implements Serializable {
/**
* 使用TakePhoto自带的裁切工具进行裁切
*/
private boolean withOwnCrop;
private int aspectX;
private int aspectY;
private int outputX;
private int outputY;
private CropOptions() {
}
public int getAspectX() {
return aspectX;
}
public void setAspectX(int aspectX) {
this.aspectX = aspectX;
}
public int getAspectY() {
return aspectY;
}
public void setAspectY(int aspectY) {
this.aspectY = aspectY;
}
public int getOutputX() {
return outputX;
}
public void setOutputX(int outputX) {
this.outputX = outputX;
}
public int getOutputY() {
return outputY;
}
public void setOutputY(int outputY) {
this.outputY = outputY;
}
public boolean isWithOwnCrop() {
return withOwnCrop;
}
public void setWithOwnCrop(boolean withOwnCrop) {
this.withOwnCrop = withOwnCrop;
}
public static class Builder {
private CropOptions options;
public Builder() {
options = new CropOptions();
}
public Builder setAspectX(int aspectX) {
options.setAspectX(aspectX);
return this;
}
public Builder setAspectY(int aspectY) {
options.setAspectY(aspectY);
return this;
}
public Builder setOutputX(int outputX) {
options.setOutputX(outputX);
return this;
}
public Builder setOutputY(int outputY) {
options.setOutputY(outputY);
return this;
}
public Builder setWithOwnCrop(boolean withOwnCrop) {
options.setWithOwnCrop(withOwnCrop);
return this;
}
public CropOptions create() {
return options;
}
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/InvokeParam.java
================================================
package org.devio.takephoto.model;
import java.lang.reflect.Method;
/**
* Created by penn on 16/9/22.
*/
public class InvokeParam {
private Object proxy;
private Method method;
private Object[] args;
public InvokeParam(Object proxy, Method method, Object[] args) {
this.proxy = proxy;
this.method = method;
this.args = args;
}
public Object getProxy() {
return proxy;
}
public void setProxy(Object proxy) {
this.proxy = proxy;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/LubanOptions.java
================================================
package org.devio.takephoto.model;
import java.io.Serializable;
/**
* Luban配置类
* Author: crazycodeboy
* Date: 2016/11/5 0007 20:10
* Version:4.0.1
* 技术博文:http://www.devio.org/
* GitHub:https://github.com/crazycodeboy
* Email:crazycodeboy@gmail.com
*/
public class LubanOptions implements Serializable {
/**
* 压缩到的最大大小,单位B
*/
private int maxSize;
private int maxHeight;
private int maxWidth;
private LubanOptions() {
}
public int getMaxSize() {
return maxSize;
}
public void setMaxSize(int maxSize) {
this.maxSize = maxSize;
}
public int getMaxHeight() {
return maxHeight;
}
public void setMaxHeight(int maxHeight) {
this.maxHeight = maxHeight;
}
public int getMaxWidth() {
return maxWidth;
}
public void setMaxWidth(int maxWidth) {
this.maxWidth = maxWidth;
}
public static class Builder {
private LubanOptions options;
public Builder() {
options = new LubanOptions();
}
public Builder setMaxSize(int maxSize) {
options.setMaxSize(maxSize);
return this;
}
public Builder setMaxHeight(int maxHeight) {
options.setMaxHeight(maxHeight);
return this;
}
public Builder setMaxWidth(int maxWidth) {
options.setMaxWidth(maxWidth);
return this;
}
public LubanOptions create() {
return options;
}
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/MultipleCrop.java
================================================
package org.devio.takephoto.model;
import android.app.Activity;
import android.net.Uri;
import org.devio.takephoto.uitl.TImageFiles;
import org.devio.takephoto.uitl.TUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* Author: JPH
* Date: 2016/8/11 17:01
*/
public class MultipleCrop {
private ArrayList uris;
private ArrayList outUris;
private ArrayList tImages;
private TImage.FromType fromType;
public boolean hasFailed;//是否有裁切失败的标识
public static MultipleCrop of(ArrayList uris, Activity activity, TImage.FromType fromType) throws TException {
return new MultipleCrop(uris, activity, fromType);
}
public static MultipleCrop of(ArrayList uris, ArrayList outUris, TImage.FromType fromType) {
return new MultipleCrop(uris, outUris, fromType);
}
private MultipleCrop(ArrayList uris, Activity activity, TImage.FromType fromType) throws TException {
this.uris = uris;
ArrayList outUris = new ArrayList<>();
for (Uri uri : uris) {
outUris.add(Uri.fromFile(TImageFiles.getTempFile(activity, uri)));//生成临时裁切输出路径
}
this.outUris = outUris;
this.tImages = TUtils.getTImagesWithUris(outUris, fromType);
this.fromType = fromType;
}
private MultipleCrop(ArrayList uris, ArrayList outUris, TImage.FromType fromType) {
this.uris = uris;
this.outUris = outUris;
this.tImages = TUtils.getTImagesWithUris(outUris, fromType);
this.fromType = fromType;
}
public ArrayList getUris() {
return uris;
}
public void setUris(ArrayList uris) {
this.uris = uris;
}
public ArrayList getOutUris() {
return outUris;
}
public void setOutUris(ArrayList outUris) {
this.outUris = outUris;
}
public ArrayList gettImages() {
return tImages;
}
public void settImages(ArrayList tImages) {
this.tImages = tImages;
}
/**
* 为被裁切的图片设置已被裁切的标识
*
* @param uri 被裁切的图片
* @return 该图片是否是最后一张
*/
public Map setCropWithUri(Uri uri, boolean cropped) {
if (!cropped) {
hasFailed = true;
}
int index = outUris.indexOf(uri);
tImages.get(index).setCropped(cropped);
Map result = new HashMap();
result.put("index", index);
result.put("isLast", index == outUris.size() - 1 ? true : false);
return result;
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TContextWrap.java
================================================
package org.devio.takephoto.model;
import android.app.Activity;
import android.support.v4.app.Fragment;
/**
* Author: JPH
* Date: 2016/8/11 17:01
*/
public class TContextWrap {
private Activity activity;
private Fragment fragment;
public static TContextWrap of(Activity activity) {
return new TContextWrap(activity);
}
public static TContextWrap of(Fragment fragment) {
return new TContextWrap(fragment);
}
private TContextWrap(Activity activity) {
this.activity = activity;
}
private TContextWrap(Fragment fragment) {
this.fragment = fragment;
this.activity = fragment.getActivity();
}
public Activity getActivity() {
return activity;
}
public void setActivity(Activity activity) {
this.activity = activity;
}
public Fragment getFragment() {
return fragment;
}
public void setFragment(Fragment fragment) {
this.fragment = fragment;
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TException.java
================================================
package org.devio.takephoto.model;
/**
* Author: JPH
* Date: 2016/7/26 10:53
*/
public class TException extends Exception {
String detailMessage;
public TException(TExceptionType exceptionType) {
super(exceptionType.getStringValue());
this.detailMessage = exceptionType.getStringValue();
}
public String getDetailMessage() {
return detailMessage;
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TExceptionType.java
================================================
package org.devio.takephoto.model;
/**
* Author: JPH
* Date: 2016/7/26 11:01
*/
public enum TExceptionType {
TYPE_NOT_IMAGE("选择的文件不是图片"), TYPE_WRITE_FAIL("保存选择的的文件失败"), TYPE_URI_NULL("所选照片的Uri 为null"), TYPE_URI_PARSE_FAIL("从Uri中获取文件路径失败"),
TYPE_NO_MATCH_PICK_INTENT("没有匹配到选择图片的Intent"), TYPE_NO_MATCH_CROP_INTENT("没有匹配到裁切图片的Intent"), TYPE_NO_CAMERA("没有相机"),
TYPE_NO_FIND("选择的文件没有找到");
String stringValue;
TExceptionType(String stringValue) {
this.stringValue = stringValue;
}
public String getStringValue() {
return stringValue;
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TImage.java
================================================
package org.devio.takephoto.model;
import android.net.Uri;
import java.io.Serializable;
/**
* TakePhoto 操作成功返回的处理结果
*
* Author: JPH
* Date: 2016/8/11 17:01
*/
public class TImage implements Serializable {
private String originalPath;
private String compressPath;
private FromType fromType;
private boolean cropped;
private boolean compressed;
public static TImage of(String path, FromType fromType) {
return new TImage(path, fromType);
}
public static TImage of(Uri uri, FromType fromType) {
return new TImage(uri, fromType);
}
private TImage(String path, FromType fromType) {
this.originalPath = path;
this.fromType = fromType;
}
private TImage(Uri uri, FromType fromType) {
this.originalPath = uri.getPath();
this.fromType = fromType;
}
public String getOriginalPath() {
return originalPath;
}
public void setOriginalPath(String originalPath) {
this.originalPath = originalPath;
}
public String getCompressPath() {
return compressPath;
}
public void setCompressPath(String compressPath) {
this.compressPath = compressPath;
}
public FromType getFromType() {
return fromType;
}
public void setFromType(FromType fromType) {
this.fromType = fromType;
}
public boolean isCropped() {
return cropped;
}
public void setCropped(boolean cropped) {
this.cropped = cropped;
}
public boolean isCompressed() {
return compressed;
}
public void setCompressed(boolean compressed) {
this.compressed = compressed;
}
public enum FromType {
CAMERA, OTHER
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TIntentWap.java
================================================
package org.devio.takephoto.model;
import android.content.Intent;
/**
* Author: JPH
* Date: 2016/7/26 14:23
*/
public class TIntentWap {
private Intent intent;
private int requestCode;
public TIntentWap() {
}
public TIntentWap(Intent intent, int requestCode) {
this.intent = intent;
this.requestCode = requestCode;
}
public Intent getIntent() {
return intent;
}
public void setIntent(Intent intent) {
this.intent = intent;
}
public int getRequestCode() {
return requestCode;
}
public void setRequestCode(int requestCode) {
this.requestCode = requestCode;
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TResult.java
================================================
package org.devio.takephoto.model;
import java.util.ArrayList;
/**
* TakePhoto 操作成功返回的处理结果
* Author: JPH
* Date: 2016/8/11 17:01
*/
public class TResult {
private ArrayList images;
private TImage image;
public static TResult of(TImage image) {
ArrayList images = new ArrayList<>(1);
images.add(image);
return new TResult(images);
}
public static TResult of(ArrayList images) {
return new TResult(images);
}
private TResult(ArrayList images) {
this.images = images;
if (images != null && !images.isEmpty()) {
this.image = images.get(0);
}
}
public ArrayList getImages() {
return images;
}
public void setImages(ArrayList images) {
this.images = images;
}
public TImage getImage() {
return image;
}
public void setImage(TImage image) {
this.image = image;
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TakePhotoOptions.java
================================================
package org.devio.takephoto.model;
import java.io.Serializable;
/**
* Author: crazycodeboy
* Date: 2016/11/5 0007 20:10
* Version:4.0.0
* 技术博文:http://www.devio.org/
* GitHub:https://github.com/crazycodeboy
* Email:crazycodeboy@gmail.com
*/
public class TakePhotoOptions implements Serializable {
/**
* 是否使用TakePhoto自带的相册进行图片选择,默认不使用,但选择多张图片会使用
*/
private boolean withOwnGallery;
/**
* 是对拍的照片进行旋转角度纠正
*/
private boolean correctImage;
private TakePhotoOptions() {
}
public boolean isWithOwnGallery() {
return withOwnGallery;
}
public void setWithOwnGallery(boolean withOwnGallery) {
this.withOwnGallery = withOwnGallery;
}
public boolean isCorrectImage() {
return correctImage;
}
public void setCorrectImage(boolean correctImage) {
this.correctImage = correctImage;
}
public static class Builder {
private TakePhotoOptions options;
public Builder() {
this.options = new TakePhotoOptions();
}
public Builder setWithOwnGallery(boolean withOwnGallery) {
options.setWithOwnGallery(withOwnGallery);
return this;
}
public Builder setCorrectImage(boolean isCorrectImage) {
options.setCorrectImage(isCorrectImage);
return this;
}
public TakePhotoOptions create() {
return options;
}
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/permission/InvokeListener.java
================================================
package org.devio.takephoto.permission;
import org.devio.takephoto.model.InvokeParam;
/**
* 授权管理回调
*/
public interface InvokeListener {
PermissionManager.TPermissionType invoke(InvokeParam invokeParam);
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/permission/PermissionManager.java
================================================
package org.devio.takephoto.permission;
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.widget.Toast;
import org.devio.takephoto.app.TakePhoto;
import org.devio.takephoto.model.InvokeParam;
import org.devio.takephoto.model.TContextWrap;
import org.devio.takephoto.uitl.TConstant;
import java.lang.reflect.Method;
import java.util.ArrayList;
/**
* Created by penn on 16/9/22.
*/
public class PermissionManager {
public enum TPermission {
STORAGE(Manifest.permission.WRITE_EXTERNAL_STORAGE), CAMERA(Manifest.permission.CAMERA);
String stringValue;
TPermission(String stringValue) {
this.stringValue = stringValue;
}
public String stringValue() {
return stringValue;
}
}
public enum TPermissionType {
GRANTED("已授权"), DENIED("未授权"), WAIT("等待授权"), NOT_NEED("无需授权"), ONLY_CAMERA_DENIED("没有拍照权限"), ONLY_STORAGE_DENIED("没有读写SD卡权限");
String stringValue;
TPermissionType(String stringValue) {
this.stringValue = stringValue;
}
public String stringValue() {
return stringValue;
}
}
private final static String[] methodNames =
{"onPickFromCapture", "onPickFromCaptureWithCrop", "onPickMultiple", "onPickMultipleWithCrop", "onPickFromDocuments",
"onPickFromDocumentsWithCrop", "onPickFromGallery", "onPickFromGalleryWithCrop", "onCrop"};
/**
* 检查当前应用是否被授予相应权限
*
* @param contextWrap
* @param method
* @return
*/
public static TPermissionType checkPermission(@NonNull TContextWrap contextWrap, @NonNull Method method) {
String methodName = method.getName();
boolean contain = false;
for (int i = 0, j = methodNames.length; i < j; i++) {
if (TextUtils.equals(methodName, methodNames[i])) {
contain = true;
break;
}
}
if (!contain) {
return TPermissionType.NOT_NEED;
}
boolean cameraGranted = true, storageGranted =
ContextCompat.checkSelfPermission(contextWrap.getActivity(), TPermission.STORAGE.stringValue())
== PackageManager.PERMISSION_GRANTED ? true : false;
if (TextUtils.equals(methodName, "onPickFromCapture") || TextUtils.equals(methodName, "onPickFromCaptureWithCrop")) {
cameraGranted = ContextCompat.checkSelfPermission(contextWrap.getActivity(), TPermission.CAMERA.stringValue())
== PackageManager.PERMISSION_GRANTED ? true : false;
}
boolean granted = storageGranted && cameraGranted;
if (!granted) {
ArrayList permissions = new ArrayList<>();
if (!storageGranted) {
permissions.add(TPermission.STORAGE.stringValue());
}
if (!cameraGranted) {
permissions.add(TPermission.CAMERA.stringValue());
}
requestPermission(contextWrap, permissions.toArray(new String[permissions.size()]));
}
return granted ? TPermissionType.GRANTED : TPermissionType.WAIT;
}
public static void requestPermission(@NonNull TContextWrap contextWrap, @NonNull String[] permissions) {
if (contextWrap.getFragment() != null) {
contextWrap.getFragment().requestPermissions(permissions, TConstant.PERMISSION_REQUEST_TAKE_PHOTO);
} else {
ActivityCompat.requestPermissions(contextWrap.getActivity(), permissions, TConstant.PERMISSION_REQUEST_TAKE_PHOTO);
}
}
public static TPermissionType onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == TConstant.PERMISSION_REQUEST_TAKE_PHOTO) {
boolean cameraGranted = true, storageGranted = true;
for (int i = 0, j = permissions.length; i < j; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
if (TextUtils.equals(TPermission.STORAGE.stringValue(), permissions[i])) {
storageGranted = false;
} else if (TextUtils.equals(TPermission.CAMERA.stringValue(), permissions[i])) {
cameraGranted = false;
}
}
}
if (cameraGranted && storageGranted) {
return TPermissionType.GRANTED;
}
if (!cameraGranted && storageGranted) {
return TPermissionType.ONLY_CAMERA_DENIED;
}
if (!storageGranted && cameraGranted) {
return TPermissionType.ONLY_STORAGE_DENIED;
}
if (!storageGranted && !cameraGranted) {
return TPermissionType.DENIED;
}
}
return TPermissionType.WAIT;
}
public static void handlePermissionsResult(Activity activity, TPermissionType type, InvokeParam invokeParam,
TakePhoto.TakeResultListener listener) {
String tip = null;
switch (type) {
case DENIED:
listener.takeFail(null, tip = activity.getResources().getString(org.devio.takephoto.R.string.tip_permission_camera_storage));
break;
case ONLY_CAMERA_DENIED:
listener.takeFail(null, tip = activity.getResources().getString(org.devio.takephoto.R.string.tip_permission_camera));
break;
case ONLY_STORAGE_DENIED:
listener.takeFail(null, tip = activity.getResources().getString(org.devio.takephoto.R.string.tip_permission_storage));
break;
case GRANTED:
try {
invokeParam.getMethod().invoke(invokeParam.getProxy(), invokeParam.getArgs());
} catch (Exception e) {
e.printStackTrace();
listener.takeFail(null, tip = activity.getResources().getString(org.devio.takephoto.R.string.tip_permission_camera_storage));
}
break;
default:
break;
}
if (tip != null) {
Toast.makeText(activity, tip, Toast.LENGTH_LONG).show();
}
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/permission/TakePhotoInvocationHandler.java
================================================
package org.devio.takephoto.permission;
import org.devio.takephoto.app.TakePhoto;
import org.devio.takephoto.model.InvokeParam;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class TakePhotoInvocationHandler implements InvocationHandler {
private TakePhoto delegate;
private InvokeListener listener;
public static TakePhotoInvocationHandler of(InvokeListener listener) {
return new TakePhotoInvocationHandler(listener);
}
private TakePhotoInvocationHandler(InvokeListener listener) {
this.listener = listener;
}
/**
* 绑定委托对象并返回一个代理类
*
* @param delegate
* @return
*/
public Object bind(TakePhoto delegate) {
this.delegate = delegate;
return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
PermissionManager.TPermissionType type = listener.invoke(new InvokeParam(proxy, method, args));
if (proxy instanceof TakePhoto) {
if (!PermissionManager.TPermissionType.NOT_NEED.equals(type)) {
((TakePhoto) proxy).permissionNotify(type);
}
}
return method.invoke(delegate, args);
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/ImageRotateUtil.java
================================================
package org.devio.takephoto.uitl;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 图片旋转角度修正工具类
* Author: crazycodeboy
* Date: 2016/9/21 0007 20:10
* Version:3.0.0
* 技术博文:http://www.devio.org
* GitHub:https://github.com/crazycodeboy
* Email:crazycodeboy@gmail.com
*/
public class ImageRotateUtil {
public static ImageRotateUtil of() {
return new ImageRotateUtil();
}
private ImageRotateUtil() {
}
/**
* 纠正照片的旋转角度
*
* @param path
*/
public void correctImage(Context context, Uri path) {
String imagePath = TUriParse.parseOwnUri(context, path);
int degree;
if ((degree = getBitmapDegree(imagePath)) != 0) {
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
if (bitmap == null) {
return;
}
Bitmap resultBitmap = rotateBitmapByDegree(bitmap, degree);
if (resultBitmap == null) {
return;
}
try {
resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File(imagePath)));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
}
}
/**
* 读取图片的旋转的角度
*
* @param path 图片绝对路径
* @return 图片的旋转角度
*/
private int getBitmapDegree(String path) {
int degree = 0;
try {
// 从指定路径下读取图片,并获取其EXIF信息
ExifInterface exifInterface = new ExifInterface(path);
// 获取图片的旋转信息
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}
/**
* 将图片按照某个角度进行旋转
*
* @param bm 需要旋转的图片
* @param degree 旋转角度
* @return 旋转后的图片
*/
private Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
Bitmap returnBm = null;
// 根据旋转角度,生成旋转矩阵
Matrix matrix = new Matrix();
matrix.postRotate(degree);
try {
// 将原始图片按照旋转矩阵进行旋转,并得到新的图片
returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
} catch (OutOfMemoryError e) {
}
if (returnBm == null) {
returnBm = bm;
}
if (bm != returnBm) {
bm.recycle();
}
return returnBm;
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/IntentUtils.java
================================================
package org.devio.takephoto.uitl;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.Log;
import com.darsh.multipleimageselect.activities.AlbumSelectActivity;
import com.darsh.multipleimageselect.helpers.Constants;
import org.devio.takephoto.model.CropOptions;
import org.devio.takephoto.model.TContextWrap;
/**
* Intent工具类用于生成拍照、
* 从相册选择照片,裁剪照片所需的Intent
* Author: JPH
* Date: 2016/6/7 0007 13:41
*/
public class IntentUtils {
private static final String TAG = IntentUtils.class.getName();
/**
* 获取图片多选的Intent
*
* @param limit 最多选择图片张数的限制
*/
public static Intent getPickMultipleIntent(TContextWrap contextWrap, int limit) {
Intent intent = new Intent(contextWrap.getActivity(), AlbumSelectActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_LIMIT, limit > 0 ? limit : 1);
return intent;
}
/**
* 获取裁剪照片的Intent
*
* @param targetUri 要裁剪的照片
* @param outPutUri 裁剪完成的照片
* @param options 裁剪配置
* @return
*/
public static Intent getCropIntentWithOtherApp(Uri targetUri, Uri outPutUri, CropOptions options) {
boolean isReturnData = TUtils.isReturnData();
Log.w(TAG, "getCaptureIntentWithCrop:isReturnData:" + (isReturnData ? "true" : "false"));
Intent intent = new Intent("com.android.camera.action.CROP");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(targetUri, "image/*");
intent.putExtra("crop", "true");
if (options.getAspectX() * options.getAspectY() > 0) {
intent.putExtra("aspectX", options.getAspectX());
intent.putExtra("aspectY", options.getAspectY());
}
if (options.getOutputX() * options.getOutputY() > 0) {
intent.putExtra("outputX", options.getOutputX());
intent.putExtra("outputY", options.getOutputY());
}
intent.putExtra("scale", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri);
intent.putExtra("return-data", isReturnData);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true); // no face detection
return intent;
}
/**
* 获取拍照的Intent
*
* @return
*/
public static Intent getCaptureIntent(Uri outPutUri) {
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照
intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri);//将拍取的照片保存到指定URI
return intent;
}
/**
* 获取选择照片的Intent
*
* @return
*/
public static Intent getPickIntentWithGallery() {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PICK);//Pick an item from the data
intent.setType("image/*");//从所有图片中进行选择
return intent;
}
/**
* 获取从文件中选择照片的Intent
*
* @return
*/
public static Intent getPickIntentWithDocuments() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
return intent;
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TConstant.java
================================================
package org.devio.takephoto.uitl;
import android.content.Context;
/**
* 常量类
*
* @author JPH
* Date 2016/6/7 0007 9:39
*/
public class TConstant {
/**
* request Code 裁剪照片
**/
public final static int RC_CROP = 1001;
/**
* request Code 从相机获取照片并裁剪
**/
public final static int RC_PICK_PICTURE_FROM_CAPTURE_CROP = 1002;
/**
* request Code 从相机获取照片不裁剪
**/
public final static int RC_PICK_PICTURE_FROM_CAPTURE = 1003;
/**
* request Code 从文件中选择照片
**/
public final static int RC_PICK_PICTURE_FROM_DOCUMENTS_ORIGINAL = 1004;
/**
* request Code 从文件中选择照片并裁剪
**/
public final static int RC_PICK_PICTURE_FROM_DOCUMENTS_CROP = 1005;
/**
* request Code 从相册选择照
**/
public final static int RC_PICK_PICTURE_FROM_GALLERY_ORIGINAL = 1006;
/**
* request Code 从相册选择照片并裁剪
**/
public final static int RC_PICK_PICTURE_FROM_GALLERY_CROP = 1007;
/**
* request Code 选择多张照片
**/
public final static int RC_PICK_MULTIPLE = 1008;
/**
* requestCode 请求权限
**/
public final static int PERMISSION_REQUEST_TAKE_PHOTO = 2000;
public final static String getFileProviderName(Context context) {
return context.getPackageName() + ".fileprovider";
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TFileUtils.java
================================================
package org.devio.takephoto.uitl;
import android.content.Context;
import android.util.Log;
import java.io.File;
/**
* Author: crazycodeboy
* Date: 2016/11/5 0007 20:10
* Version:4.0.0
* 技术博文:http://www.devio.org/
* GitHub:https://github.com/crazycodeboy
* Email:crazycodeboy@gmail.com
*/
public class TFileUtils {
private static final String TAG = "TFileUtils";
private static String DEFAULT_DISK_CACHE_DIR = "takephoto_cache";
public static File getPhotoCacheDir(Context context, File file) {
File cacheDir = context.getCacheDir();
if (cacheDir != null) {
File mCacheDir = new File(cacheDir, DEFAULT_DISK_CACHE_DIR);
if (!mCacheDir.mkdirs() && (!mCacheDir.exists() || !mCacheDir.isDirectory())) {
return file;
} else {
return new File(mCacheDir, file.getName());
}
}
if (Log.isLoggable(TAG, Log.ERROR)) {
Log.e(TAG, "default disk cache dir is null");
}
return file;
}
public static void delete(String path) {
try {
if (path == null) {
return;
}
File file = new File(path);
if (!file.delete()) {
file.deleteOnExit();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TImageFiles.java
================================================
package org.devio.takephoto.uitl;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.MimeTypeMap;
import android.widget.Toast;
import org.devio.takephoto.model.TException;
import org.devio.takephoto.model.TExceptionType;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
/**
* ImageFiles工具类
*
* @author JPH
* Date 2016/6/7 0007 9:39
*/
public class TImageFiles {
private static final String TAG = IntentUtils.class.getName();
/**
* 将bitmap写入到文件
*
* @param bitmap
*/
public static void writeToFile(Bitmap bitmap, Uri imageUri) {
if (bitmap == null) {
return;
}
File file = new File(imageUri.getPath());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
fos.write(bos.toByteArray());
bos.flush();
fos.flush();
} catch (java.io.IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* InputStream 转File
*/
public static void inputStreamToFile(InputStream is, File file) throws TException {
if (file == null) {
Log.i(TAG, "inputStreamToFile:file not be null");
throw new TException(TExceptionType.TYPE_WRITE_FAIL);
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
byte[] buffer = new byte[1024 * 10];
int i;
while ((i = is.read(buffer)) != -1) {
fos.write(buffer, 0, i);
}
} catch (IOException e) {
Log.e(TAG, "InputStream 写入文件出错:" + e.toString());
throw new TException(TExceptionType.TYPE_WRITE_FAIL);
} finally {
try {
fos.flush();
fos.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 获取临时文件
*
* @param context
* @param photoUri
* @return
*/
public static File getTempFile(Activity context, Uri photoUri) throws TException {
String minType = getMimeType(context, photoUri);
if (!checkMimeType(context, minType)) {
throw new TException(TExceptionType.TYPE_NOT_IMAGE);
}
File filesDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
if (!filesDir.exists()) {
filesDir.mkdirs();
}
File photoFile = new File(filesDir, UUID.randomUUID().toString() + "." + minType);
return photoFile;
}
/**
* 检查文件类型是否是图片
*
* @param minType
* @return
*/
public static boolean checkMimeType(Context context, String minType) {
boolean isPicture =
TextUtils.isEmpty(minType) ? false : ".jpg|.gif|.png|.bmp|.jpeg|.webp|".contains(minType.toLowerCase()) ? true : false;
if (!isPicture) {
Toast.makeText(context, context.getResources().getText(org.devio.takephoto.R.string.tip_type_not_image), Toast.LENGTH_SHORT).show();
}
return isPicture;
}
/**
* To find out the extension of required object in given uri
* Solution by http://stackoverflow.com/a/36514823/1171484
*/
public static String getMimeType(Activity context, Uri uri) {
String extension;
//Check uri format to avoid null
if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
//If scheme is a content
extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(context.getContentResolver().getType(uri));
if (TextUtils.isEmpty(extension)) {
extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString());
}
} else {
//If scheme is a File
//This will replace white spaces with %20 and also other special characters. This will avoid returning null values on file
// name with spaces and special characters.
extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString());
if (TextUtils.isEmpty(extension)) {
extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(context.getContentResolver().getType(uri));
}
}
if (TextUtils.isEmpty(extension)) {
extension = getMimeTypeByFileName(TUriParse.getFileWithUri(uri, context).getName());
}
return extension;
}
public static String getMimeTypeByFileName(String fileName) {
return fileName.substring(fileName.lastIndexOf("."), fileName.length());
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TUriParse.java
================================================
package org.devio.takephoto.uitl;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import android.util.Log;
import org.devio.takephoto.model.TException;
import org.devio.takephoto.model.TExceptionType;
import java.io.File;
import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* Uri解析工具类
* Author: JPH
* Date: 2015/8/26 0026 16:23
*/
public class TUriParse {
private static final String TAG = IntentUtils.class.getName();
/**
* 将scheme为file的uri转成FileProvider 提供的content uri
*
* @param context
* @param uri
* @return
*/
public static Uri convertFileUriToFileProviderUri(Context context, Uri uri) {
if (uri == null) {
return null;
}
if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
return getUriForFile(context, new File(uri.getPath()));
}
return uri;
}
/**
* 获取一个临时的Uri, 文件名随机生成
*
* @param context
* @return
*/
public static Uri getTempUri(Context context) {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
File file = new File(Environment.getExternalStorageDirectory(), "/images/" + timeStamp + ".jpg");
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
return getUriForFile(context, file);
}
/**
* 获取一个临时的Uri, 通过传入字符串路径
*
* @param context
* @param path
* @return
*/
public static Uri getTempUri(Context context, String path) {
File file = new File(path);
return getTempUri(context, file);
}
/**
* 获取一个临时的Uri, 通过传入File对象
*
* @param context
* @return
*/
public static Uri getTempUri(Context context, File file) {
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
return getUriForFile(context, file);
}
/**
* 创建一个用于拍照图片输出路径的Uri (FileProvider)
*
* @param context
* @return
*/
public static Uri getUriForFile(Context context, File file) {
return FileProvider.getUriForFile(context, TConstant.getFileProviderName(context), file);
}
/**
* 将TakePhoto 提供的Uri 解析出文件绝对路径
*
* @param uri
* @return
*/
public static String parseOwnUri(Context context, Uri uri) {
if (uri == null) {
return null;
}
String path;
if (TextUtils.equals(uri.getAuthority(), TConstant.getFileProviderName(context))) {
path = new File(uri.getPath().replace("camera_photos/", "")).getAbsolutePath();
} else {
path = uri.getPath();
}
return path;
}
/**
* 通过URI获取文件的路径
*
* @param uri
* @param activity
* @return Author JPH
* Date 2016/6/6 0006 20:01
*/
public static String getFilePathWithUri(Uri uri, Activity activity) throws TException {
if (uri == null) {
Log.w(TAG, "uri is null,activity may have been recovered?");
throw new TException(TExceptionType.TYPE_URI_NULL);
}
File picture = getFileWithUri(uri, activity);
String picturePath = picture == null ? null : picture.getPath();
if (TextUtils.isEmpty(picturePath)) {
throw new TException(TExceptionType.TYPE_URI_PARSE_FAIL);
}
if (!TImageFiles.checkMimeType(activity, TImageFiles.getMimeType(activity, uri))) {
throw new TException(TExceptionType.TYPE_NOT_IMAGE);
}
return picturePath;
}
/**
* 通过URI获取文件
*
* @param uri
* @param activity
* @return Author JPH
* Date 2016/10/25
*/
public static File getFileWithUri(Uri uri, Activity activity) {
String picturePath = null;
String scheme = uri.getScheme();
if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = activity.getContentResolver().query(uri, filePathColumn, null, null, null);//从系统表中查询指定Uri对应的照片
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
if (columnIndex >= 0) {
picturePath = cursor.getString(columnIndex); //获取照片路径
} else if (TextUtils.equals(uri.getAuthority(), TConstant.getFileProviderName(activity))) {
picturePath = parseOwnUri(activity, uri);
}
cursor.close();
} else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
picturePath = uri.getPath();
}
return TextUtils.isEmpty(picturePath) ? null : new File(picturePath);
}
/**
* 通过从文件中得到的URI获取文件的路径
*
* @param uri
* @param activity
* @return Author JPH
* Date 2016/6/6 0006 20:01
*/
public static String getFilePathWithDocumentsUri(Uri uri, Activity activity) throws TException {
if (uri == null) {
Log.e(TAG, "uri is null,activity may have been recovered?");
return null;
}
if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) && uri.getPath().contains("document")) {
File tempFile = TImageFiles.getTempFile(activity, uri);
try {
TImageFiles.inputStreamToFile(activity.getContentResolver().openInputStream(uri), tempFile);
return tempFile.getPath();
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new TException(TExceptionType.TYPE_NO_FIND);
}
} else {
return getFilePathWithUri(uri, activity);
}
}
}
================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TUtils.java
================================================
package org.devio.takephoto.uitl;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.darsh.multipleimageselect.models.Image;
import org.devio.takephoto.model.CropOptions;
import org.devio.takephoto.model.TException;
import org.devio.takephoto.model.TExceptionType;
import org.devio.takephoto.model.TImage;
import org.devio.takephoto.model.TIntentWap;
import org.devio.takephoto.R;
import org.devio.takephoto.model.TContextWrap;
import com.soundcloud.android.crop.Crop;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* 工具类
* Author: JPH
* Date: 2016/7/26 10:04
*/
public class TUtils {
private static final String TAG = IntentUtils.class.getName();
/**
* 将Image集合转换成Uri集合
*
* @param images
* @return
*/
public static ArrayList convertImageToUri(Context context, ArrayList images) throws TException {
ArrayList uris = new ArrayList();
for (Image image : images) {
uris.add(FileProvider.getUriForFile(context, TConstant.getFileProviderName(context), new File(image.path)));
}
return uris;
}
/**
* 将Image集合转换成TImage集合
*
* @param images
* @return
*/
public static ArrayList getTImagesWithImages(ArrayList images, TImage.FromType fromType) {
ArrayList tImages = new ArrayList();
for (Image image : images) {
tImages.add(TImage.of(image.path, fromType));
}
return tImages;
}
/**
* 将Uri集合转换成TImage集合
*
* @param uris
* @return
*/
public static ArrayList getTImagesWithUris(ArrayList uris, TImage.FromType fromType) {
ArrayList tImages = new ArrayList();
for (Uri uri : uris) {
tImages.add(TImage.of(uri, fromType));
}
return tImages;
}
/**
* @param contextWrap
* @param intentWap
*/
public static void startActivityForResult(TContextWrap contextWrap, TIntentWap intentWap) {
if (contextWrap.getFragment() != null) {
contextWrap.getFragment().startActivityForResult(intentWap.getIntent(), intentWap.getRequestCode());
} else {
contextWrap.getActivity().startActivityForResult(intentWap.getIntent(), intentWap.getRequestCode());
}
}
/**
* 安全地发送Intent
*
* @param contextWrap
* @param intentWapList 要发送的Intent以及候选Intent
* @param defaultIndex 默认发送的Intent
* @param isCrop 是否为裁切照片的Intent
* @throws TException
*/
public static void sendIntentBySafely(TContextWrap contextWrap, List intentWapList, int defaultIndex, boolean isCrop)
throws TException {
if (defaultIndex + 1 > intentWapList.size()) {
throw new TException(isCrop ? TExceptionType.TYPE_NO_MATCH_PICK_INTENT : TExceptionType.TYPE_NO_MATCH_CROP_INTENT);
}
TIntentWap intentWap = intentWapList.get(defaultIndex);
List result = contextWrap.getActivity().getPackageManager().queryIntentActivities(intentWap.getIntent(), PackageManager.MATCH_ALL);
if (result.isEmpty()) {
sendIntentBySafely(contextWrap, intentWapList, ++defaultIndex, isCrop);
} else {
startActivityForResult(contextWrap, intentWap);
}
}
/**
* 拍照前检查是否有相机
**/
public static void captureBySafely(TContextWrap contextWrap, TIntentWap intentWap) throws TException {
List result = contextWrap.getActivity().getPackageManager().queryIntentActivities(intentWap.getIntent(), PackageManager.MATCH_ALL);
if (result.isEmpty()) {
Toast.makeText(contextWrap.getActivity(), contextWrap.getActivity().getResources().getText(R.string.tip_no_camera),
Toast.LENGTH_SHORT).show();
throw new TException(TExceptionType.TYPE_NO_CAMERA);
} else {
startActivityForResult(contextWrap, intentWap);
}
}
/**
* 通过第三方工具裁切照片,当没有第三方裁切工具时,会自动使用自带裁切工具进行裁切
*
* @param contextWrap
* @param imageUri
* @param outPutUri
* @param options
*/
public static void cropWithOtherAppBySafely(TContextWrap contextWrap, Uri imageUri, Uri outPutUri, CropOptions options) {
Intent nativeCropIntent = IntentUtils.getCropIntentWithOtherApp(imageUri, outPutUri, options);
List result = contextWrap.getActivity().getPackageManager().queryIntentActivities(nativeCropIntent, PackageManager.MATCH_ALL);
if (result.isEmpty()) {
cropWithOwnApp(contextWrap, imageUri, outPutUri, options);
} else {
// try {
// imageUri=Uri.fromFile(new File(TUriParse.getFilePathWithDocumentsUri(imageUri,contextWrap.getActivity())));
// } catch (TException e) {
// e.printStackTrace();
// }
startActivityForResult(contextWrap,
new TIntentWap(IntentUtils.getCropIntentWithOtherApp(imageUri, outPutUri, options), TConstant.RC_CROP));
}
}
/**
* 通过TakePhoto自带的裁切工具裁切图片
*
* @param contextWrap
* @param imageUri
* @param outPutUri
* @param options
*/
public static void cropWithOwnApp(TContextWrap contextWrap, Uri imageUri, Uri outPutUri, CropOptions options) {
if (options.getAspectX() * options.getAspectY() > 0) {
if (contextWrap.getFragment() != null) {
Crop.of(imageUri, outPutUri)
.withAspect(options.getAspectX(), options.getAspectY())
.start(contextWrap.getActivity(), contextWrap.getFragment());
} else {
Crop.of(imageUri, outPutUri).withAspect(options.getAspectX(), options.getAspectY()).start(contextWrap.getActivity());
}
} else if (options.getOutputX() * options.getOutputY() > 0) {
if (contextWrap.getFragment() != null) {
Crop.of(imageUri, outPutUri)
.withMaxSize(options.getOutputX(), options.getOutputY())
.start(contextWrap.getActivity(), contextWrap.getFragment());
} else {
Crop.of(imageUri, outPutUri).withMaxSize(options.getOutputX(), options.getOutputY()).start(contextWrap.getActivity());
}
} else {
if (contextWrap.getFragment() != null) {
Crop.of(imageUri, outPutUri).asSquare().start(contextWrap.getActivity(), contextWrap.getFragment());
} else {
Crop.of(imageUri, outPutUri).asSquare().start(contextWrap.getActivity());
}
}
}
/**
* 是否裁剪之后返回数据
**/
public static boolean isReturnData() {
String release = Build.VERSION.RELEASE;
int sdk = Build.VERSION.SDK_INT;
Log.i(TAG, "release:" + release + "sdk:" + sdk);
String manufacturer = android.os.Build.MANUFACTURER;
if (!TextUtils.isEmpty(manufacturer)) {
if (manufacturer.toLowerCase().contains("lenovo")) {//对于联想的手机返回数据
return true;
}
}
// if (sdk>=21){//5.0或以上版本要求返回数据
// return true;
// }
return false;
}
/**
* 显示圆形进度对话框
*
* @param activity
* @param progressTitle 显示的标题
* @return
* @author JPH
* Date 2014-12-12 下午7:04:09
*/
public static ProgressDialog showProgressDialog(final Activity activity, String... progressTitle) {
if (activity == null || activity.isFinishing()) {
return null;
}
String title = activity.getResources().getString(R.string.tip_tips);
if (progressTitle != null && progressTitle.length > 0) {
title = progressTitle[0];
}
ProgressDialog progressDialog = new ProgressDialog(activity);
progressDialog.setTitle(title);
progressDialog.setCancelable(false);
progressDialog.show();
return progressDialog;
}
}
================================================
FILE: takephoto_library/src/main/res/values/dimens.xml
================================================
16dp
16dp
================================================
FILE: takephoto_library/src/main/res/values/strings.xml
================================================
选择的不是图片
没有相机
提示
正在压缩照片...
"%1$s 图片压缩失败:%2$s picturePath:%3$s"
"有裁切失败的图片"
"有压缩失败的图片"
" 取消裁切"
"操作被取消"
没有使用相机的权限,请在权限管理中开启
没有使用SD卡的权限,请在权限管理中开启
没有使用相机和SD卡的权限,请在权限管理中开启
选择图片
单击选择
确定
已选
最多能选 %d 张
================================================
FILE: takephoto_library/src/main/res/values-en/strings.xml
================================================
Choose not pictures
No camera
Tips
Being compressed...
"%1$s Picture compression failure:%2$s picturePath:%3$s"
"There are pictures of crop failures."
"There are pictures of compress failures."
" canceled crop"
"Operation canceled."
No permission to use the camera, open the rights management
No permission to use the SD card, open the rights management
No permission to use the camera and SD card, open the rights management
================================================
FILE: takephoto_library/src/main/res/values-w820dp/dimens.xml
================================================
64dp
================================================
FILE: takephoto_library/src/main/res/xml/file_paths.xml
================================================