package cn.flightfeather.thirdapp.util.photo;
|
|
import android.app.Activity;
|
import android.content.Intent;
|
import android.graphics.Bitmap;
|
import android.graphics.BitmapFactory;
|
import android.net.Uri;
|
import android.os.Build;
|
import android.provider.MediaStore;
|
import android.support.v4.app.Fragment;
|
import android.support.v4.content.FileProvider;
|
import android.view.View;
|
import android.view.ViewGroup;
|
import android.widget.ImageView;
|
import android.widget.PopupWindow;
|
import android.widget.Toast;
|
|
import com.google.gson.Gson;
|
import com.google.gson.GsonBuilder;
|
import com.ping.greendao.gen.MediafileDao;
|
|
import java.io.File;
|
import java.io.Serializable;
|
import java.util.ArrayList;
|
import java.util.List;
|
|
import cn.flightfeather.thirdapp.CommonApplication;
|
import cn.flightfeather.thirdapp.activity.PhotoViewerActivity;
|
import cn.flightfeather.thirdapp.bean.entity.Mediafile;
|
import cn.flightfeather.thirdapp.httpservice.UploadService;
|
import cn.flightfeather.thirdapp.module.common.CameraActivity;
|
import cn.flightfeather.thirdapp.task.CompressPhotoTask;
|
import cn.flightfeather.thirdapp.task.DownloadAndSetImageTask;
|
import cn.flightfeather.thirdapp.task.SetImageTask;
|
import cn.flightfeather.thirdapp.util.DialogUtil2;
|
import cn.flightfeather.thirdapp.util.file.FileUtil;
|
import kotlin.Unit;
|
import kotlin.jvm.functions.Function1;
|
import okhttp3.MediaType;
|
import okhttp3.MultipartBody;
|
import okhttp3.RequestBody;
|
import okhttp3.ResponseBody;
|
import retrofit2.Call;
|
import retrofit2.Callback;
|
import retrofit2.Response;
|
|
|
public class PhotoUtil {
|
|
private int photoUploaded =0;
|
private final int photoTotal;
|
private final MediafileDao mediafileDao;
|
private CommonApplication application;
|
private OnUpLoadListener onUpLoadListener;
|
|
public PhotoUtil(int photoTotal, CommonApplication application, OnUpLoadListener onUpLoadListener) {
|
this.photoTotal = photoTotal;
|
this.application = application;
|
this.mediafileDao = application.getDaoSession().getMediafileDao();
|
this.onUpLoadListener = onUpLoadListener;
|
}
|
|
/**
|
* 绑定ImageView和图片,本地加载或联网加载显示(针对固定数量的ImageView)
|
* @param mediaFiles
|
* @param imageViews
|
* @param activity
|
* @return 实际加载的图片个数
|
*/
|
public static int loadImage(List<Mediafile> mediaFiles, List<ImageView> imageViews, Activity activity){
|
if (mediaFiles!=null){
|
int count = Math.min(mediaFiles.size(), imageViews.size());
|
|
for (int i = 0; i < count; i++) {
|
Mediafile mediaFileTmp = mediaFiles.get(i);
|
File file = FileUtil.getFileFromMediaFile(mediaFileTmp);
|
if (file.exists()) {
|
SetImageTask task1 = new SetImageTask(file, imageViews.get(i), (Activity) activity);
|
task1.execute();
|
} else {
|
DownloadAndSetImageTask task = new DownloadAndSetImageTask(mediaFileTmp, imageViews.get(i), activity);
|
task.execute();
|
}
|
}
|
return count;
|
}
|
return 0;
|
}
|
|
/**
|
* 获取查看图片的点击事件
|
* @param activity
|
* @param files
|
* @param position
|
* @param mediafiles
|
* @param type 参数为{@link PhotoViewerActivity#PROBLEM_PHOTO} 和{@link PhotoViewerActivity#CHANGE_PHOTO }
|
* @param editable 是否可编辑
|
* @return
|
*/
|
public static View.OnClickListener OnPhotoViewClickListener(final Activity activity, final List<File> files, final int position, final List<Mediafile> mediafiles, final int type, final boolean editable){
|
View.OnClickListener listener = new View.OnClickListener() {
|
@Override
|
public void onClick(View view) {
|
Intent intent = new Intent(activity, PhotoViewerActivity.class);
|
intent.putExtra("position",position);
|
intent.putExtra("deletable",editable);
|
intent.putExtra(PhotoViewerActivity.PARA_MEDIAS, (Serializable) mediafiles);
|
intent.putExtra(PhotoViewerActivity.PARA_FILES, (Serializable) files);
|
intent.putExtra("type",type);
|
activity.startActivityForResult(intent,type);
|
}
|
};
|
return listener;
|
}
|
|
/**
|
* 拍照功能
|
* 启动的activity会返回一个{@link Uri}, 标签为{@link MediaStore#EXTRA_OUTPUT}
|
* @param activity
|
* @param requestCode
|
* @param dirPath
|
*/
|
public static void takePhoto(Activity activity, int requestCode, File dirPath) {
|
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
//判断要跳转的目的地是否为空
|
if (intent.resolveActivity(activity.getPackageManager()) != null) {
|
if (dirPath!=null){
|
//安卓7.0适配
|
Uri uri;
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
uri = FileProvider.getUriForFile(activity, "cn.flightfeather.thirdapp.fileProvider", dirPath);
|
} else {
|
uri = Uri.fromFile(dirPath);
|
}
|
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
|
activity.startActivityForResult(intent, requestCode);
|
}else {
|
Toast.makeText(activity, "拍照启动错误", Toast.LENGTH_SHORT).show();
|
}
|
|
}
|
}
|
|
/**
|
* 从相册中选择图片
|
* @param activity
|
* @param requestCode
|
* @param num 图片数
|
*/
|
public static void pickPhoto(Activity activity, int requestCode, int num) {
|
View view = ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
|
List<String> textList = new ArrayList<>();
|
textList.add("相册");
|
textList.add("拍照");
|
List<Function1<PopupWindow, Unit>> function1List = new ArrayList<>();
|
function1List.add(popupWindow -> {
|
ImagePicker2.getInstance()
|
.setTitle("选择图片")//设置标题
|
.showCamera(false)//设置是否显示拍照按钮
|
.showImage(true)//设置是否展示图片
|
.showVideo(false)//设置是否展示视频
|
.setMaxCount(num)//设置最大选择图片数目(默认为1,单选)
|
.setSingleType(true)//设置图片视频不能同时选择
|
// .setImagePaths(mImagePaths)//设置历史选择记录
|
.setImageLoader(new GlideLoader())//设置自定义图片加载器
|
.start(activity, requestCode);
|
popupWindow.dismiss();
|
return null;
|
});
|
function1List.add(popupWindow -> {
|
Intent intent = new Intent(activity, CameraActivity.class);
|
activity.startActivityForResult(intent, requestCode);
|
popupWindow.dismiss();
|
return null;
|
});
|
DialogUtil2.INSTANCE.showBottomDialog(activity, view, textList, function1List, popupWindow -> null);
|
}
|
|
public static void pickPhoto2(Activity activity, int requestCode, int num) {
|
ImagePicker2.getInstance()
|
.setTitle("选择图片")//设置标题
|
.showCamera(true)//设置是否显示拍照按钮
|
.showImage(true)//设置是否展示图片
|
.showVideo(false)//设置是否展示视频
|
.setMaxCount(num)//设置最大选择图片数目(默认为1,单选)
|
.setSingleType(true)//设置图片视频不能同时选择
|
// .setImagePaths(mImagePaths)//设置历史选择记录
|
.setImageLoader(new GlideLoader())//设置自定义图片加载器
|
.start(activity, requestCode);
|
}
|
|
public static void pickPhoto(Fragment fragment, int requestCode, int num) {
|
ImagePicker2.getInstance()
|
.setTitle("选择图片")//设置标题
|
.showCamera(true)//设置是否显示拍照按钮
|
.showImage(true)//设置是否展示图片
|
.showVideo(false)//设置是否展示视频
|
.setMaxCount(num)//设置最大选择图片数目(默认为1,单选)
|
.setSingleType(true)//设置图片视频不能同时选择
|
// .setImagePaths(mImagePaths)//设置历史选择记录
|
.setImageLoader(new GlideLoader())//设置自定义图片加载器
|
.start(fragment, requestCode);
|
}
|
|
/**
|
* 上传图片
|
* @param mediafileList 图片信息列表
|
*/
|
public void upLoadPhoto(final List<Mediafile> mediafileList) {
|
CompressPhotoTask task = new CompressPhotoTask(mediafileList, new OnCompressListener() {
|
@Override
|
public void onCompressed(List<File> files) {
|
photoUploaded = 0;
|
uploadSinglePhoto(files, mediafileList);
|
}
|
});
|
|
task.execute();
|
}
|
|
|
private void uploadSinglePhoto(final List<File> files, final List<Mediafile> mediafileList){
|
if (files.size()==0) {
|
onUpLoadListener.onSuccess();
|
return;
|
}
|
//当前上传的文件
|
File file = files.get(photoUploaded);
|
|
List<MultipartBody.Part> photoList = new ArrayList<>();
|
//准备图片部分
|
|
// 创建 RequestBody,用于封装构建RequestBody
|
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
|
// MultipartBody.Part 和后端约定好Key,这里的partName是用image
|
MultipartBody.Part body = MultipartBody.Part.createFormData("Photos", file.getName(), requestFile);
|
photoList.add(body);
|
|
List<Mediafile> mediafiles = new ArrayList<>();
|
final Mediafile mediaFile = mediafileList.get(photoUploaded);
|
mediaFile.setRemark("已上传");
|
mediafiles.add(mediaFile);
|
|
//准备mediafile的json
|
Gson gson = new GsonBuilder()
|
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
|
.create();
|
String a =gson.toJson(mediafiles);
|
|
final RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), a);
|
MultipartBody.Part part = MultipartBody.Part.createFormData("mediafileVoList", null, requestBody);
|
photoList.add(part);
|
|
Call<ResponseBody> uploadPhotos =application.getRetrofit().create(UploadService.class).uploadPhotos(photoList);
|
uploadPhotos.enqueue(new Callback<ResponseBody>() {
|
@Override
|
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
|
if (response.body()!=null){
|
mediafileDao.update(mediaFile);
|
photoUploaded++;
|
if (photoUploaded<photoTotal){
|
uploadSinglePhoto(files, mediafileList);
|
}else {
|
if (onUpLoadListener != null) {
|
onUpLoadListener.onSuccess();
|
}
|
clearTemp(files);
|
}
|
|
}else if (response.errorBody()!=null){
|
if (onUpLoadListener != null) {
|
onUpLoadListener.onFail();
|
}
|
}
|
}
|
|
@Override
|
public void onFailure(Call<ResponseBody> call, Throwable t) {
|
if (onUpLoadListener != null) {
|
onUpLoadListener.onFail();
|
}
|
}
|
});
|
}
|
|
//清理缓存
|
private void clearTemp(List<File> outputFileList){
|
if (outputFileList!=null&&outputFileList.size()>0){
|
for (File file:outputFileList){
|
if (file.exists()){
|
file.delete();
|
}
|
}
|
}
|
}
|
|
/**
|
* 根据要求的宽高,计算图片缩放倍数
|
* @param options
|
* @param reqWidth
|
* @param reqHeight
|
* @return
|
*/
|
public static int calculateInSampleSize(BitmapFactory.Options options,
|
int reqWidth, int reqHeight) {
|
// 源图片的高度和宽度
|
final int height = options.outHeight;
|
final int width = options.outWidth;
|
int inSampleSize = 1;
|
if (height > reqHeight || width > reqWidth) {
|
// 计算出实际宽高和目标宽高的比率
|
final int heightRatio = Math.round((float) height / (float) reqHeight);
|
final int widthRatio = Math.round((float) width / (float) reqWidth);
|
// 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
|
// 一定都会大于等于目标的宽和高。
|
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
|
}
|
return inSampleSize;
|
}
|
|
|
public static Bitmap decodeSampledBitmapFromResource(String filePath, int reqWidth, int reqHeight) {
|
// 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
|
final BitmapFactory.Options options = new BitmapFactory.Options();
|
options.inJustDecodeBounds = true;
|
BitmapFactory.decodeFile(filePath, options);
|
// 调用上面定义的方法计算inSampleSize值
|
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
|
// 使用获取到的inSampleSize值再次解析图片
|
options.inJustDecodeBounds = false;
|
options.inPreferredConfig = Bitmap.Config.RGB_565;
|
options.inPurgeable = true;
|
return BitmapFactory.decodeFile(filePath, options);
|
}
|
}
|