当前位置:   article > 正文

Android 图片裁剪并批量上传视频图片到阿里云OSS

Android 图片裁剪并批量上传视频图片到阿里云OSS

添加依赖:

  1. implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0'
  2. implementation 'com.soundcloud.android:android-crop:1.0.1@aar' //裁剪包,高版本调用手机裁剪功能不行,调用这个包
  3. //glide
  4. implementation 'com.github.bumptech.glide:glide:4.12.0'
  5. annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
  6. //阿里云oss上传
  7. // implementation 'com.aliyun.dpa:oss-android-sdk:+'
  8. implementation 'com.aliyun.dpa:oss-android-sdk:2.9.13'
  9. implementation 'commons-codec:commons-codec:1.4'
  10. //裁剪控件
  11. // api 'com.theartofdev.edmodo:android-image-cropper:2.7.0'
  12. api 'com.theartofdev.edmodo:android-image-cropper:2.8.+'
  13. implementation 'top.zibin:Luban:1.1.8'
  14. //RecyclerViewAdapter
  15. implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.50'

在清单文件AndroidmMainfest中添加权限:

  1. <uses-permission android:name="android.permission.INTERNET" />
  2. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 允许程序读取或写入系统设置 -->
  3. <uses-permission android:name="android.permission.CAMERA" />
  4. <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" /><!-- 10.0访问 图片位置信息 -->

打开相册前动态请求图库权限:

  1. static final String[] PS={
  2. /*Manifest.permission.READ_CONTACTS,*/
  3. /*Manifest.permission.CAMERA,
  4. Manifest.permission.READ_PHONE_STATE,
  5. Manifest.permission.RECORD_AUDIO,*/
  6. Manifest.permission.WRITE_EXTERNAL_STORAGE
  7. };
  8. boolean checkPermission(){
  9. boolean ok=true;
  10. for(String p: PS){
  11. ok=checkCallingOrSelfPermission(p)== PackageManager.PERMISSION_GRANTED;
  12. if(!ok) break;
  13. }
  14. if(!ok) return false;
  15. return true;
  16. }
  17. //判断是否拥有权限:
  18. if(!checkPermission()){
  19. if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
  20. requestPermissions(PS, PS.hashCode());
  21. }
  22. return;
  23. }
  24. startActivity(new Intent(MainActivity.this, SelectPicActivity.class));

 

SelectPicActivity:

  1. package com.example.testcsdnproject.picdemo;
  2. import androidx.annotation.Nullable;
  3. import androidx.appcompat.app.AppCompatActivity;
  4. import androidx.recyclerview.widget.GridLayoutManager;
  5. import androidx.recyclerview.widget.RecyclerView;
  6. import android.content.Intent;
  7. import android.os.Bundle;
  8. import android.view.View;
  9. import android.widget.TextView;
  10. import android.widget.Toast;
  11. import com.example.testcsdnproject.R;
  12. import com.luck.picture.lib.PictureSelector;
  13. import com.luck.picture.lib.animators.AnimationType;
  14. import com.luck.picture.lib.config.PictureConfig;
  15. import com.luck.picture.lib.config.PictureMimeType;
  16. import com.luck.picture.lib.entity.LocalMedia;
  17. import com.luck.picture.lib.language.LanguageConfig;
  18. import com.luck.picture.lib.tools.SdkVersionUtils;
  19. import java.util.ArrayList;
  20. import java.util.List;
  21. //选择相册
  22. public class SelectPicActivity extends AppCompatActivity {
  23. private TextView tv_upload;
  24. private RecyclerView rv_dynamic;
  25. private GridImageAdapter2 gridImageAdapter2;
  26. private List<LocalMedia> selectList = new ArrayList<>();
  27. @Override
  28. protected void onCreate(Bundle savedInstanceState) {
  29. super.onCreate(savedInstanceState);
  30. setContentView(R.layout.activity_select_pic);
  31. tv_upload = findViewById(R.id.tv_upload);
  32. rv_dynamic = findViewById(R.id.rv_dynamic);
  33. GridLayoutManager manager = new GridLayoutManager(this,4,RecyclerView.VERTICAL,false);
  34. rv_dynamic.setLayoutManager(manager);
  35. gridImageAdapter2 = new GridImageAdapter2(this,onAddPicClickListener);
  36. rv_dynamic.setAdapter(gridImageAdapter2);
  37. tv_upload.setOnClickListener(new View.OnClickListener() {
  38. @Override
  39. public void onClick(View view) {
  40. if (selectList.size() == 0){
  41. Toast.makeText(SelectPicActivity.this, "请上传图片视频。", Toast.LENGTH_SHORT).show();
  42. return;
  43. }
  44. uploadFile();
  45. }
  46. });
  47. //添加点击事件
  48. gridImageAdapter2.setOnItemClickListener(new GridImageAdapter2.OnItemClickListener() {
  49. @Override
  50. public void onItemClick(View v, int position) {
  51. if (selectList.size()>0){
  52. LocalMedia media = selectList.get(position);
  53. String pictureType = media.getMimeType();
  54. int mediaType = PictureMimeType.getMimeType(pictureType);
  55. switch (mediaType){
  56. case 1 : //预览图片
  57. PictureSelector.create(SelectPicActivity.this).externalPicturePreview(position,selectList,0);
  58. break;
  59. case 2 : //预览视频
  60. PictureSelector.create(SelectPicActivity.this).externalPictureVideo(media.getPath());
  61. break;
  62. case 3 : //预览音频
  63. PictureSelector.create(SelectPicActivity.this).externalPictureAudio(media.getPath());
  64. break;
  65. }
  66. }
  67. }
  68. });
  69. }
  70. // 从相册返回结果
  71. @Override
  72. protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
  73. super.onActivityResult(requestCode, resultCode, data);
  74. if (resultCode == RESULT_OK){
  75. switch (requestCode){
  76. case PictureConfig.CHOOSE_REQUEST:
  77. selectList = PictureSelector.obtainMultipleResult(data);
  78. gridImageAdapter2.setList(selectList);
  79. gridImageAdapter2.notifyDataSetChanged();
  80. break;
  81. }
  82. }
  83. }
  84. //把图片上传OSS
  85. private String filePath;
  86. private List<String> urls = new ArrayList<>();
  87. private List<String> urlsCallback = new ArrayList<>();
  88. private void uploadFile(){
  89. OssService ossService = new OssService(this, 1);
  90. ossService.initOSSClient();
  91. urls.clear();
  92. for (int i = 0; i<selectList.size();i++){
  93. filePath = selectList.get(i).getRealPath();
  94. // filePath = selectList.get(i).getAndroidQToPath();
  95. urls.add(filePath);
  96. }
  97. /*if (mWaitDialog == null) {
  98. mWaitDialog = new WaitDialog.Builder(PublishDynamicActivity.this)
  99. // 消息文本可以不用填写
  100. .setMessage("正在发布...")
  101. .create();
  102. }
  103. if (!mWaitDialog.isShowing()) {
  104. mWaitDialog.setCanceledOnTouchOutside(true);
  105. mWaitDialog.show();
  106. }*/
  107. if (urls.size() == 0){
  108. // mHandler.sendEmptyMessage(1); //走接口发布动态
  109. return;
  110. }
  111. ossService.ossUploadDynamic(urls);
  112. urlsCallback.clear();
  113. ossService.setCallbackClickListener(new OssService.onCallbackClickListener() {
  114. @Override
  115. public void onCallBack(String imageurl, String json) {
  116. if(imageurl.contains(".mp4")){
  117. // type = "2"; //2为视频
  118. }else{
  119. // type = "1"; //其他都是1 包括图片 文字 音频
  120. }
  121. urlsCallback.add(imageurl);
  122. if (urlsCallback.size() == selectList.size()){
  123. // mHandler.sendEmptyMessage(1);//走接口发布动态
  124. // 图片视频数据从urlsCallback这个列表里面取
  125. }
  126. }
  127. });
  128. }
  129. private GridImageAdapter2.onAddPicClickListener onAddPicClickListener = new GridImageAdapter2.onAddPicClickListener() {
  130. @Override
  131. public void onAddPicClick() {
  132. boolean mode = /*cb_mode.isChecked()*/true;
  133. if (mode) {
  134. // 进入相册 以下是例子:不需要的api可以不写
  135. PictureSelector.create(SelectPicActivity.this)
  136. .openGallery(PictureMimeType.ofAll())// 全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio()
  137. .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎,必传项
  138. // .theme(themeId)// 主题样式设置 具体参考 values/styles 用法:R.style.picture.white.style v2.3.3后 建议使用setPictureStyle()动态方式
  139. .isWeChatStyle(true)// 是否开启微信图片选择风格
  140. .isUseCustomCamera(false)// 是否使用自定义相机
  141. .setLanguage(LanguageConfig.TRADITIONAL_CHINESE)// 设置语言,默认中文
  142. .isPageStrategy(false)// 是否开启分页策略 & 每页多少条;默认开启
  143. // .setPictureStyle(mPictureParameterStyle)// 动态自定义相册主题
  144. // .setPictureCropStyle(mCropParameterStyle)// 动态自定义裁剪主题
  145. // .setPictureWindowAnimationStyle(mWindowAnimationStyle)// 自定义相册启动退出动画
  146. .setRecyclerAnimationMode(AnimationType.ALPHA_IN_ANIMATION)// 列表动画效果
  147. .isWithVideoImage(false)// 图片和视频是否可以同选,只在ofAll模式下有效
  148. .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
  149. //.isAutomaticTitleRecyclerTop(false)// 连续点击标题栏RecyclerView是否自动回到顶部,默认true
  150. //.loadCacheResourcesCallback(GlideCacheEngine.createCacheEngine())// 获取图片资源缓存,主要是解决华为10部分机型在拷贝文件过多时会出现卡的问题,这里可以判断只在会出现一直转圈问题机型上使用
  151. //.setOutputCameraPath()// 自定义相机输出目录,只针对Android Q以下,例如 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + "Camera" + File.separator;
  152. //.setButtonFeatures(CustomCameraView.BUTTON_STATE_BOTH)// 设置自定义相机按钮状态
  153. .maxSelectNum(9)// 最大图片选择数量
  154. // .minSelectNum(1)// 最小选择数量
  155. .maxVideoSelectNum(1) // 视频最大选择数量
  156. //.minVideoSelectNum(1)// 视频最小选择数量
  157. //.closeAndroidQChangeVideoWH(!SdkVersionUtils.checkedAndroid_Q())// 关闭在AndroidQ下获取图片或视频宽高相反自动转换
  158. .imageSpanCount(4)// 每行显示个数
  159. .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
  160. .closeAndroidQChangeWH(true)//如果图片有旋转角度则对换宽高,默认为true
  161. .closeAndroidQChangeVideoWH(!SdkVersionUtils.checkedAndroid_Q())// 如果视频有旋转角度则对换宽高,默认为false
  162. //.isAndroidQTransform(false)// 是否需要处理Android Q 拷贝至应用沙盒的操作,只针对compress(false); && .isEnableCrop(false);有效,默认处理
  163. // .setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)// 设置相册Activity方向,不设置默认使用系统
  164. .isOriginalImageControl(true)// 是否显示原图控制按钮,如果设置为true则用户可以自由选择是否使用原图,压缩、裁剪功能将会失效
  165. // .bindCustomPlayVideoCallback(new MyVideoSelectedPlayCallback(getContext()))// 自定义视频播放回调控制,用户可以使用自己的视频播放界面
  166. //.bindCustomCameraInterfaceListener(new MyCustomCameraInterfaceListener())// 提供给用户的一些额外的自定义操作回调
  167. //.cameraFileName(System.currentTimeMillis() +".jpg") // 重命名拍照文件名、如果是相册拍照则内部会自动拼上当前时间戳防止重复,注意这个只在使用相机时可以使用,如果使用相机又开启了压缩或裁剪 需要配合压缩和裁剪文件名api
  168. //.renameCompressFile(System.currentTimeMillis() +".jpg")// 重命名压缩文件名、 如果是多张压缩则内部会自动拼上当前时间戳防止重复
  169. //.renameCropFileName(System.currentTimeMillis() + ".jpg")// 重命名裁剪文件名、 如果是多张裁剪则内部会自动拼上当前时间戳防止重复
  170. .selectionMode(PictureConfig.MULTIPLE)// 多选 or 单选
  171. // .isSingleDirectReturn(true)// 单选模式下是否直接返回,PictureConfig.SINGLE模式下有效
  172. .isPreviewImage(true)// 是否可预览图片
  173. .isPreviewVideo(true)// 是否可预览视频
  174. //.querySpecifiedFormatSuffix(PictureMimeType.ofJPEG())// 查询指定后缀格式资源
  175. .isEnablePreviewAudio(true) // 是否可播放音频
  176. .isCamera(true)// 是否显示拍照按钮
  177. //.isMultipleSkipCrop(false)// 多图裁剪时是否支持跳过,默认支持
  178. //.isMultipleRecyclerAnimation(false)// 多图裁剪底部列表显示动画效果
  179. .isZoomAnim(true)// 图片列表点击 缩放效果 默认true
  180. //.imageFormat(PictureMimeType.PNG)// 拍照保存图片格式后缀,默认jpeg,Android Q使用PictureMimeType.PNG_Q
  181. .isEnableCrop(false)// 是否裁剪
  182. //.basicUCropConfig()//对外提供所有UCropOptions参数配制,但如果PictureSelector原本支持设置的还是会使用原有的设置
  183. .isCompress(true)// 是否压缩
  184. //.compressQuality(80)// 图片压缩后输出质量 0~ 100
  185. .synOrAsy(true)//同步true或异步false 压缩 默认同步
  186. //.queryMaxFileSize(10)// 只查多少M以内的图片、视频、音频 单位M
  187. //.compressSavePath(getPath())//压缩图片保存地址
  188. //.sizeMultiplier(0.5f)// glide 加载图片大小 0~1之间 如设置 .glideOverride()无效 注:已废弃
  189. //.glideOverride(160, 160)// glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度 注:已废弃
  190. .withAspectRatio(0, 0)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义
  191. .hideBottomControls(false)// 是否显示uCrop工具栏,默认不显示
  192. .isGif(true)// 是否显示gif图片
  193. .freeStyleCropEnabled(true)// 裁剪框是否可拖拽
  194. .circleDimmedLayer(false)// 是否圆形裁剪
  195. //.setCropDimmedColor(ContextCompat.getColor(getContext(), R.color.app_color_white))// 设置裁剪背景色值
  196. //.setCircleDimmedBorderColor(ContextCompat.getColor(getApplicationContext(), R.color.app_color_white))// 设置圆形裁剪边框色值
  197. //.setCircleStrokeWidth(3)// 设置圆形裁剪边框粗细
  198. .showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false
  199. .showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false
  200. .isOpenClickSound(false)// 是否开启点击声音
  201. .selectionData(gridImageAdapter2.getData())// 是否传入已选图片
  202. //.isDragFrame(false)// 是否可拖动裁剪框(固定)
  203. //.videoMinSecond(10)// 查询多少秒以内的视频
  204. //.videoMaxSecond(15)// 查询多少秒以内的视频
  205. //.recordVideoSecond(10)//录制视频秒数 默认60s
  206. //.isPreviewEggs(true)// 预览图片时 是uploadGetPolicy否增强左右滑动图片体验(图片滑动一半即可看到上一张是否选中)
  207. //.cropCompressQuality(90)// 注:已废弃 改用cutOutQuality()
  208. .cutOutQuality(90)// 裁剪输出质量 默认100
  209. .minimumCompressSize(100)// 小于100kb的图片不压缩
  210. //.cropWH()// 裁剪宽高比,设置如果大于图片本身宽高则无效
  211. //.cropImageWideHigh()// 裁剪宽高比,设置如果大于图片本身宽高则无效
  212. //.rotateEnabled(false) // 裁剪是否可旋转图片
  213. //.scaleEnabled(false)// 裁剪是否可放大缩小图片
  214. //.videoQuality()// 视频录制质量 0 or 1
  215. .forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code
  216. // .forResult(new MyResultCallback(gridImageAdapter2));
  217. }
  218. }
  219. };
  220. }

xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:background="#1a1a1a">
  8. <androidx.recyclerview.widget.RecyclerView
  9. android:id="@+id/rv_dynamic"
  10. android:layout_width="match_parent"
  11. android:layout_height="wrap_content"
  12. />
  13. <TextView
  14. android:id="@+id/tv_upload"
  15. android:layout_width="match_parent"
  16. android:layout_height="wrap_content"
  17. android:layout_alignParentBottom="true"
  18. android:layout_centerHorizontal="true"
  19. android:text="上传"
  20. android:textColor="@color/white"
  21. android:textSize="20sp"
  22. android:gravity="center"
  23. android:background="@color/picture_color_blue"
  24. android:layout_marginLeft="20dp"
  25. android:layout_marginRight="20dp"
  26. android:layout_marginBottom="30dp"
  27. />
  28. </RelativeLayout>
GridImageAdapter2:
  1. package com.example.testcsdnproject.picdemo;
  2. import android.content.Context;
  3. import android.net.Uri;
  4. import android.text.TextUtils;
  5. import android.util.Log;
  6. import android.view.LayoutInflater;
  7. import android.view.View;
  8. import android.view.ViewGroup;
  9. import android.widget.ImageView;
  10. import android.widget.TextView;
  11. import androidx.recyclerview.widget.RecyclerView;
  12. import com.bumptech.glide.Glide;
  13. import com.bumptech.glide.load.engine.DiskCacheStrategy;
  14. import com.example.testcsdnproject.R;
  15. import com.luck.picture.lib.config.PictureMimeType;
  16. import com.luck.picture.lib.entity.LocalMedia;
  17. import com.luck.picture.lib.tools.DateUtils;
  18. import java.io.File;
  19. import java.util.ArrayList;
  20. import java.util.List;
  21. public class GridImageAdapter2 extends
  22. RecyclerView.Adapter<GridImageAdapter2.ViewHolder> {
  23. public static final String TAG = "PictureSelector";
  24. public static final int TYPE_CAMERA = 1;
  25. public static final int TYPE_PICTURE = 2;
  26. private LayoutInflater mInflater;
  27. private List<LocalMedia> list = new ArrayList<>();
  28. private int selectMax = 9;
  29. /**
  30. * 点击添加图片跳转
  31. */
  32. private onAddPicClickListener mOnAddPicClickListener;
  33. public interface onAddPicClickListener {
  34. void onAddPicClick();
  35. }
  36. /**
  37. * 删除
  38. */
  39. public void delete(int position) {
  40. try {
  41. if (position != RecyclerView.NO_POSITION && list.size() > position) {
  42. list.remove(position);
  43. notifyItemRemoved(position);
  44. notifyItemRangeChanged(position, list.size());
  45. }
  46. } catch (Exception e) {
  47. e.printStackTrace();
  48. }
  49. }
  50. public GridImageAdapter2(Context context, onAddPicClickListener mOnAddPicClickListener) {
  51. this.mInflater = LayoutInflater.from(context);
  52. this.mOnAddPicClickListener = mOnAddPicClickListener;
  53. }
  54. public GridImageAdapter2(Context context, onAddPicClickListener mOnAddPicClickListener, int selectMax) {
  55. this.mInflater = LayoutInflater.from(context);
  56. this.mOnAddPicClickListener = mOnAddPicClickListener;
  57. this.selectMax = selectMax;
  58. }
  59. public void setSelectMax(int selectMax) {
  60. this.selectMax = selectMax;
  61. }
  62. public void setList(List<LocalMedia> list) {
  63. this.list = list;
  64. }
  65. public List<LocalMedia> getData() {
  66. return list == null ? new ArrayList<>() : list;
  67. }
  68. public void remove(int position) {
  69. if (list != null && position < list.size()) {
  70. list.remove(position);
  71. }
  72. }
  73. public class ViewHolder extends RecyclerView.ViewHolder {
  74. ImageView mImg;
  75. ImageView mIvDel;
  76. TextView tvDuration;
  77. public ViewHolder(View view) {
  78. super(view);
  79. mImg = view.findViewById(R.id.fiv);
  80. mIvDel = view.findViewById(R.id.iv_del);
  81. tvDuration = view.findViewById(R.id.tv_duration);
  82. }
  83. }
  84. @Override
  85. public int getItemCount() {
  86. if (list.size() < selectMax) {
  87. return list.size() + 1;
  88. } else {
  89. return list.size();
  90. }
  91. }
  92. @Override
  93. public int getItemViewType(int position) {
  94. if (isShowAddItem(position)) {
  95. return TYPE_CAMERA;
  96. } else {
  97. return TYPE_PICTURE;
  98. }
  99. }
  100. /**
  101. * 创建ViewHolder
  102. */
  103. @Override
  104. public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
  105. View view = mInflater.inflate(R.layout.gv_filter_image,
  106. viewGroup, false);
  107. final ViewHolder viewHolder = new ViewHolder(view);
  108. return viewHolder;
  109. }
  110. private boolean isShowAddItem(int position) {
  111. int size = list.size() == 0 ? 0 : list.size();
  112. return position == size;
  113. }
  114. /**
  115. * 设置值
  116. */
  117. @Override
  118. public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
  119. //少于8张,显示继续添加的图标
  120. if (getItemViewType(position) == TYPE_CAMERA) {
  121. viewHolder.mImg.setImageResource(R.mipmap.ic_add_image);
  122. viewHolder.mImg.setOnClickListener(v -> mOnAddPicClickListener.onAddPicClick());
  123. viewHolder.mIvDel.setVisibility(View.INVISIBLE);
  124. } else {
  125. viewHolder.mIvDel.setVisibility(View.VISIBLE);
  126. viewHolder.mIvDel.setOnClickListener(view -> {
  127. int index = viewHolder.getAdapterPosition();
  128. // 这里有时会返回-1造成数据下标越界,具体可参考getAdapterPosition()源码,
  129. // 通过源码分析应该是bindViewHolder()暂未绘制完成导致,知道原因的也可联系我~感谢
  130. if (index != RecyclerView.NO_POSITION && list.size() > index) {
  131. list.remove(index);
  132. notifyItemRemoved(index);
  133. notifyItemRangeChanged(index, list.size());
  134. }
  135. });
  136. LocalMedia media = list.get(position);
  137. if (media == null
  138. || TextUtils.isEmpty(media.getPath())) {
  139. return;
  140. }
  141. int chooseModel = media.getChooseModel();
  142. String path;
  143. if (media.isCut() && !media.isCompressed()) {
  144. // 裁剪过
  145. path = media.getCutPath();
  146. } else if (media.isCompressed() || (media.isCut() && media.isCompressed())) {
  147. // 压缩过,或者裁剪同时压缩过,以最终压缩过图片为准
  148. path = media.getCompressPath();
  149. } else {
  150. // 原图
  151. path = media.getPath();
  152. }
  153. Log.i(TAG, "原图地址::" + media.getPath());
  154. if (media.isCut()) {
  155. Log.i(TAG, "裁剪地址::" + media.getCutPath());
  156. }
  157. if (media.isCompressed()) {
  158. Log.i(TAG, "压缩地址::" + media.getCompressPath());
  159. Log.i(TAG, "压缩后文件大小::" + new File(media.getCompressPath()).length() / 1024 + "k");
  160. }
  161. if (!TextUtils.isEmpty(media.getAndroidQToPath())) {
  162. Log.i(TAG, "Android Q特有地址::" + media.getAndroidQToPath());
  163. }
  164. if (media.isOriginal()) {
  165. Log.i(TAG, "是否开启原图功能::" + true);
  166. Log.i(TAG, "开启原图功能后地址::" + media.getOriginalPath());
  167. }
  168. long duration = media.getDuration();
  169. viewHolder.tvDuration.setVisibility(PictureMimeType.isHasVideo(media.getMimeType())
  170. ? View.VISIBLE : View.GONE);
  171. if (chooseModel == PictureMimeType.ofAudio()) {
  172. viewHolder.tvDuration.setVisibility(View.VISIBLE);
  173. viewHolder.tvDuration.setCompoundDrawablesRelativeWithIntrinsicBounds
  174. (R.drawable.picture_icon_audio, 0, 0, 0);
  175. } else {
  176. viewHolder.tvDuration.setCompoundDrawablesRelativeWithIntrinsicBounds
  177. (R.drawable.picture_icon_video, 0, 0, 0);
  178. }
  179. viewHolder.tvDuration.setText(DateUtils.formatDurationTime(duration));
  180. if (chooseModel == PictureMimeType.ofAudio()) {
  181. viewHolder.mImg.setImageResource(R.drawable.picture_audio_placeholder);
  182. } else {
  183. Glide.with(viewHolder.itemView.getContext())
  184. .load(PictureMimeType.isContent(path) && !media.isCut() && !media.isCompressed() ? Uri.parse(path)
  185. : path)
  186. .centerCrop()
  187. .placeholder(R.color.app_color_f6)
  188. .diskCacheStrategy(DiskCacheStrategy.ALL)
  189. .into(viewHolder.mImg);
  190. }
  191. //itemView 的点击事件
  192. if (mItemClickListener != null) {
  193. viewHolder.itemView.setOnClickListener(v -> {
  194. int adapterPosition = viewHolder.getAdapterPosition();
  195. mItemClickListener.onItemClick(v, adapterPosition);
  196. });
  197. }
  198. if (mItemLongClickListener != null) {
  199. viewHolder.itemView.setOnLongClickListener(v -> {
  200. int adapterPosition = viewHolder.getAdapterPosition();
  201. mItemLongClickListener.onItemLongClick(viewHolder, adapterPosition, v);
  202. return true;
  203. });
  204. }
  205. }
  206. //设置图片宽高比1:1
  207. ViewGroup.LayoutParams layoutParams = viewHolder.mImg.getLayoutParams();
  208. // layoutParams.width = (int) (Common.getScreenWidth(mContext)*0.95);
  209. layoutParams.height = (int) (layoutParams.width );
  210. viewHolder.mImg.setLayoutParams(layoutParams);
  211. }
  212. private OnItemClickListener mItemClickListener;
  213. public interface OnItemClickListener {
  214. void onItemClick(View v, int position);
  215. }
  216. public void setOnItemClickListener(OnItemClickListener l) {
  217. this.mItemClickListener = l;
  218. }
  219. private OnItemLongClickListener mItemLongClickListener;
  220. public void setItemLongClickListener(OnItemLongClickListener l) {
  221. this.mItemLongClickListener = l;
  222. }
  223. }
gv_filter_image.xml:(小图标自己上千图网找)
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <com.luck.picture.lib.widget.SquareRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="wrap_content"
  5. android:layout_height="wrap_content"
  6. android:gravity="center_vertical"
  7. android:layout_margin="5dp"
  8. android:layout_centerInParent="true">
  9. <ImageView
  10. android:id="@+id/fiv"
  11. android:layout_width="match_parent"
  12. android:layout_height="100dp"
  13. tools:src="#f6f6f6" />
  14. <ImageView
  15. android:id="@+id/iv_del"
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:layout_alignTop="@id/fiv"
  19. android:layout_alignRight="@id/fiv"
  20. android:paddingLeft="@dimen/dp_10"
  21. android:paddingBottom="@dimen/dp_10"
  22. android:scaleType="centerInside"
  23. android:src="@mipmap/ic_delete_menu"
  24. android:visibility="gone"
  25. tools:visibility="visible" />
  26. <TextView
  27. android:id="@+id/tv_duration"
  28. android:layout_width="match_parent"
  29. android:layout_height="30dp"
  30. android:layout_alignLeft="@id/fiv"
  31. android:layout_alignRight="@id/fiv"
  32. android:layout_alignBottom="@id/fiv"
  33. android:background="@mipmap/ps_ic_shadow_bg"
  34. android:drawableLeft="@mipmap/ps_ic_video"
  35. android:drawablePadding="5dp"
  36. android:gravity="center_vertical"
  37. android:paddingLeft="5dp"
  38. android:paddingTop="8dp"
  39. android:text="00:00"
  40. android:textColor="#FFFFFF"
  41. android:textSize="11sp"
  42. android:visibility="gone"
  43. tools:visibility="visible" />
  44. </com.luck.picture.lib.widget.SquareRelativeLayout>
OnItemLongClickListener:
  1. package com.example.testcsdnproject.picdemo;
  2. import android.view.View;
  3. import androidx.recyclerview.widget.RecyclerView;
  4. /**
  5. * @author:luck
  6. * @date:2020-01-13 17:58
  7. * @describe:长按事件
  8. */
  9. public interface OnItemLongClickListener {
  10. void onItemLongClick(RecyclerView.ViewHolder holder, int position, View v);
  11. }
GlideEngine:(加载引擎)
  1. package com.example.testcsdnproject.picdemo;
  2. import android.content.Context;
  3. import android.graphics.Bitmap;
  4. import android.graphics.PointF;
  5. import android.graphics.drawable.Drawable;
  6. import android.view.View;
  7. import android.widget.ImageView;
  8. import androidx.annotation.NonNull;
  9. import androidx.annotation.Nullable;
  10. import androidx.core.graphics.drawable.RoundedBitmapDrawable;
  11. import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
  12. import com.bumptech.glide.Glide;
  13. import com.bumptech.glide.request.RequestOptions;
  14. import com.bumptech.glide.request.target.BitmapImageViewTarget;
  15. import com.bumptech.glide.request.target.ImageViewTarget;
  16. import com.example.testcsdnproject.R;
  17. import com.luck.picture.lib.engine.ImageEngine;
  18. import com.luck.picture.lib.listener.OnImageCompleteCallback;
  19. import com.luck.picture.lib.tools.MediaUtils;
  20. import com.luck.picture.lib.widget.longimage.ImageSource;
  21. import com.luck.picture.lib.widget.longimage.ImageViewState;
  22. import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView;
  23. /**
  24. * @author:luck
  25. * @date:2019-11-13 17:02
  26. * @describe:Glide加载引擎
  27. */
  28. public class GlideEngine implements ImageEngine {
  29. /**
  30. * 加载图片
  31. *
  32. * @param context
  33. * @param url
  34. * @param imageView
  35. */
  36. @Override
  37. public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
  38. Glide.with(context)
  39. .load(url)
  40. .into(imageView);
  41. }
  42. /**
  43. * 加载网络图片适配长图方案
  44. * # 注意:此方法只有加载网络图片才会回调
  45. *
  46. * @param context
  47. * @param url
  48. * @param imageView
  49. * @param longImageView
  50. * @param callback 网络图片加载回调监听 {link after version 2.5.1 Please use the #OnImageCompleteCallback#}
  51. */
  52. @Override
  53. public void loadImage(@NonNull Context context, @NonNull String url,
  54. @NonNull ImageView imageView,
  55. SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) {
  56. Glide.with(context)
  57. .asBitmap()
  58. .load(url)
  59. .into(new ImageViewTarget<Bitmap>(imageView) {
  60. @Override
  61. public void onLoadStarted(@Nullable Drawable placeholder) {
  62. super.onLoadStarted(placeholder);
  63. if (callback != null) {
  64. callback.onShowLoading();
  65. }
  66. }
  67. @Override
  68. public void onLoadFailed(@Nullable Drawable errorDrawable) {
  69. super.onLoadFailed(errorDrawable);
  70. if (callback != null) {
  71. callback.onHideLoading();
  72. }
  73. }
  74. @Override
  75. protected void setResource(@Nullable Bitmap resource) {
  76. if (callback != null) {
  77. callback.onHideLoading();
  78. }
  79. if (resource != null) {
  80. boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
  81. resource.getHeight());
  82. longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
  83. imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
  84. if (eqLongImage) {
  85. // 加载长图
  86. longImageView.setQuickScaleEnabled(true);
  87. longImageView.setZoomEnabled(true);
  88. longImageView.setPanEnabled(true);
  89. longImageView.setDoubleTapZoomDuration(100);
  90. longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
  91. longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
  92. longImageView.setImage(ImageSource.bitmap(resource),
  93. new ImageViewState(0, new PointF(0, 0), 0));
  94. } else {
  95. // 普通图片
  96. imageView.setImageBitmap(resource);
  97. }
  98. }
  99. }
  100. });
  101. }
  102. /**
  103. * 加载网络图片适配长图方案
  104. * # 注意:此方法只有加载网络图片才会回调
  105. *
  106. * @param context
  107. * @param url
  108. * @param imageView
  109. * @param longImageView
  110. * @ 已废弃
  111. */
  112. @Override
  113. public void loadImage(@NonNull Context context, @NonNull String url,
  114. @NonNull ImageView imageView,
  115. SubsamplingScaleImageView longImageView) {
  116. Glide.with(context)
  117. .asBitmap()
  118. .load(url)
  119. .into(new ImageViewTarget<Bitmap>(imageView) {
  120. @Override
  121. protected void setResource(@Nullable Bitmap resource) {
  122. if (resource != null) {
  123. boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
  124. resource.getHeight());
  125. longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
  126. imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
  127. if (eqLongImage) {
  128. // 加载长图
  129. longImageView.setQuickScaleEnabled(true);
  130. longImageView.setZoomEnabled(true);
  131. longImageView.setPanEnabled(true);
  132. longImageView.setDoubleTapZoomDuration(100);
  133. longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
  134. longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
  135. longImageView.setImage(ImageSource.bitmap(resource),
  136. new ImageViewState(0, new PointF(0, 0), 0));
  137. } else {
  138. // 普通图片
  139. imageView.setImageBitmap(resource);
  140. }
  141. }
  142. }
  143. });
  144. }
  145. /**
  146. * 加载相册目录
  147. *
  148. * @param context 上下文
  149. * @param url 图片路径
  150. * @param imageView 承载图片ImageView
  151. */
  152. @Override
  153. public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
  154. Glide.with(context)
  155. .asBitmap()
  156. .load(url)
  157. .override(180, 180)
  158. .centerCrop()
  159. .sizeMultiplier(0.5f)
  160. .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder))
  161. .into(new BitmapImageViewTarget(imageView) {
  162. @Override
  163. protected void setResource(Bitmap resource) {
  164. RoundedBitmapDrawable circularBitmapDrawable =
  165. RoundedBitmapDrawableFactory.
  166. create(context.getResources(), resource);
  167. circularBitmapDrawable.setCornerRadius(8);
  168. imageView.setImageDrawable(circularBitmapDrawable);
  169. }
  170. });
  171. }
  172. /**
  173. * 加载gif
  174. *
  175. * @param context 上下文
  176. * @param url 图片路径
  177. * @param imageView 承载图片ImageView
  178. */
  179. @Override
  180. public void loadAsGifImage(@NonNull Context context, @NonNull String url,
  181. @NonNull ImageView imageView) {
  182. Glide.with(context)
  183. .asGif()
  184. .load(url)
  185. .into(imageView);
  186. }
  187. /**
  188. * 加载图片列表图片
  189. *
  190. * @param context 上下文
  191. * @param url 图片路径
  192. * @param imageView 承载图片ImageView
  193. */
  194. @Override
  195. public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
  196. Glide.with(context)
  197. .load(url)
  198. .override(200, 200)
  199. .centerCrop()
  200. .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder))
  201. .into(imageView);
  202. }
  203. private GlideEngine() {
  204. }
  205. private static GlideEngine instance;
  206. public static GlideEngine createGlideEngine() {
  207. if (null == instance) {
  208. synchronized (GlideEngine.class) {
  209. if (null == instance) {
  210. instance = new GlideEngine();
  211. }
  212. }
  213. }
  214. return instance;
  215. }
  216. }
AddArtWorksBean 测试数据的实体类:
  1. package com.example.testcsdnproject.picdemo;
  2. import com.google.gson.annotations.SerializedName;
  3. import java.io.Serializable;
  4. public class AddArtWorksBean implements Serializable {
  5. @SerializedName("artId")
  6. private Long artId;
  7. @SerializedName("artSaleState")
  8. private String artSaleState;
  9. @SerializedName("audioBand")
  10. private String audioBand;
  11. @SerializedName("authorName")
  12. private String authorName;
  13. @SerializedName("authorPortrait")
  14. private String authorPortrait;
  15. @SerializedName("changeSpeech")
  16. private Integer changeSpeech;
  17. @SerializedName("copyright")
  18. private Long copyright;
  19. @SerializedName("copyrightDirectory")
  20. private String copyrightDirectory;
  21. @SerializedName("cover")
  22. private String cover;
  23. @SerializedName("creativeProcess")
  24. private String creativeProcess;
  25. @SerializedName("fodder")
  26. private Integer fodder;
  27. @SerializedName("gatherId")
  28. private Integer gatherId;
  29. @SerializedName("gatherSort")
  30. private String gatherSort;
  31. @SerializedName("gdmoaId")
  32. private Integer gdmoaId;
  33. @SerializedName("id")
  34. private Long id;
  35. @SerializedName("imageHeight")
  36. private Long imageHeight;
  37. @SerializedName("imageWidth")
  38. private Long imageWidth;
  39. @SerializedName("introduce")
  40. private String introduce;
  41. @SerializedName("isAuthor")
  42. private Integer isAuthor;
  43. @SerializedName("isFamous")
  44. private String isFamous;
  45. @SerializedName("isShare")
  46. private Integer isShare;
  47. @SerializedName("material")
  48. private String material;
  49. @SerializedName("name")
  50. private String name;
  51. @SerializedName("organizationUserid")
  52. private Long organizationUserid;
  53. @SerializedName("parentDirectory")
  54. private String parentDirectory;
  55. @SerializedName("publishTime")
  56. private String publishTime;
  57. @SerializedName("releaseSort")
  58. private Integer releaseSort;
  59. @SerializedName("releaseTime")
  60. private String releaseTime;
  61. @SerializedName("secondMaterial")
  62. private String secondMaterial;
  63. @SerializedName("share")
  64. private Integer share;
  65. @SerializedName("shareDirectory")
  66. private Integer shareDirectory;
  67. @SerializedName("speechUrl")
  68. private String speechUrl;
  69. @SerializedName("state")
  70. private Integer state;
  71. @SerializedName("type")
  72. private Integer type;
  73. @SerializedName("url")
  74. private String url;
  75. @SerializedName("userId")
  76. private Long userId;
  77. @SerializedName("videoTime")
  78. private String videoTime;
  79. @SerializedName("viewNumber")
  80. private Integer viewNumber;
  81. @SerializedName("workGiveLike")
  82. private Integer workGiveLike;
  83. @SerializedName("workHeight")
  84. private Long workHeight;
  85. @SerializedName("workTags")
  86. private String workTags;
  87. @SerializedName("workWidth")
  88. private Long workWidth;
  89. @SerializedName("workYear")
  90. private String workYear;
  91. public Long getArtId() {
  92. return artId;
  93. }
  94. public void setArtId(Long artId) {
  95. this.artId = artId;
  96. }
  97. public String getArtSaleState() {
  98. return artSaleState;
  99. }
  100. public void setArtSaleState(String artSaleState) {
  101. this.artSaleState = artSaleState;
  102. }
  103. public String getAudioBand() {
  104. return audioBand;
  105. }
  106. public void setAudioBand(String audioBand) {
  107. this.audioBand = audioBand;
  108. }
  109. public String getAuthorName() {
  110. return authorName;
  111. }
  112. public void setAuthorName(String authorName) {
  113. this.authorName = authorName;
  114. }
  115. public String getAuthorPortrait() {
  116. return authorPortrait;
  117. }
  118. public void setAuthorPortrait(String authorPortrait) {
  119. this.authorPortrait = authorPortrait;
  120. }
  121. public Integer getChangeSpeech() {
  122. return changeSpeech;
  123. }
  124. public void setChangeSpeech(Integer changeSpeech) {
  125. this.changeSpeech = changeSpeech;
  126. }
  127. public Long getCopyright() {
  128. return copyright;
  129. }
  130. public void setCopyright(Long copyright) {
  131. this.copyright = copyright;
  132. }
  133. public String getCopyrightDirectory() {
  134. return copyrightDirectory;
  135. }
  136. public void setCopyrightDirectory(String copyrightDirectory) {
  137. this.copyrightDirectory = copyrightDirectory;
  138. }
  139. public String getCover() {
  140. return cover;
  141. }
  142. public void setCover(String cover) {
  143. this.cover = cover;
  144. }
  145. public String getCreativeProcess() {
  146. return creativeProcess;
  147. }
  148. public void setCreativeProcess(String creativeProcess) {
  149. this.creativeProcess = creativeProcess;
  150. }
  151. public Integer getFodder() {
  152. return fodder;
  153. }
  154. public void setFodder(Integer fodder) {
  155. this.fodder = fodder;
  156. }
  157. public Integer getGatherId() {
  158. return gatherId;
  159. }
  160. public void setGatherId(Integer gatherId) {
  161. this.gatherId = gatherId;
  162. }
  163. public String getGatherSort() {
  164. return gatherSort;
  165. }
  166. public void setGatherSort(String gatherSort) {
  167. this.gatherSort = gatherSort;
  168. }
  169. public Integer getGdmoaId() {
  170. return gdmoaId;
  171. }
  172. public void setGdmoaId(Integer gdmoaId) {
  173. this.gdmoaId = gdmoaId;
  174. }
  175. public Long getId() {
  176. return id;
  177. }
  178. public void setId(Long id) {
  179. this.id = id;
  180. }
  181. public Long getImageHeight() {
  182. return imageHeight;
  183. }
  184. public void setImageHeight(Long imageHeight) {
  185. this.imageHeight = imageHeight;
  186. }
  187. public Long getImageWidth() {
  188. return imageWidth;
  189. }
  190. public void setImageWidth(Long imageWidth) {
  191. this.imageWidth = imageWidth;
  192. }
  193. public String getIntroduce() {
  194. return introduce;
  195. }
  196. public void setIntroduce(String introduce) {
  197. this.introduce = introduce;
  198. }
  199. public Integer getIsAuthor() {
  200. return isAuthor;
  201. }
  202. public void setIsAuthor(Integer isAuthor) {
  203. this.isAuthor = isAuthor;
  204. }
  205. public String getIsFamous() {
  206. return isFamous;
  207. }
  208. public void setIsFamous(String isFamous) {
  209. this.isFamous = isFamous;
  210. }
  211. public Integer getIsShare() {
  212. return isShare;
  213. }
  214. public void setIsShare(Integer isShare) {
  215. this.isShare = isShare;
  216. }
  217. public String getMaterial() {
  218. return material;
  219. }
  220. public void setMaterial(String material) {
  221. this.material = material;
  222. }
  223. public String getName() {
  224. return name;
  225. }
  226. public void setName(String name) {
  227. this.name = name;
  228. }
  229. public Long getOrganizationUserid() {
  230. return organizationUserid;
  231. }
  232. public void setOrganizationUserid(Long organizationUserid) {
  233. this.organizationUserid = organizationUserid;
  234. }
  235. public String getParentDirectory() {
  236. return parentDirectory;
  237. }
  238. public void setParentDirectory(String parentDirectory) {
  239. this.parentDirectory = parentDirectory;
  240. }
  241. public String getPublishTime() {
  242. return publishTime;
  243. }
  244. public void setPublishTime(String publishTime) {
  245. this.publishTime = publishTime;
  246. }
  247. public Integer getReleaseSort() {
  248. return releaseSort;
  249. }
  250. public void setReleaseSort(Integer releaseSort) {
  251. this.releaseSort = releaseSort;
  252. }
  253. public String getReleaseTime() {
  254. return releaseTime;
  255. }
  256. public void setReleaseTime(String releaseTime) {
  257. this.releaseTime = releaseTime;
  258. }
  259. public String getSecondMaterial() {
  260. return secondMaterial;
  261. }
  262. public void setSecondMaterial(String secondMaterial) {
  263. this.secondMaterial = secondMaterial;
  264. }
  265. public Integer getShare() {
  266. return share;
  267. }
  268. public void setShare(Integer share) {
  269. this.share = share;
  270. }
  271. public Integer getShareDirectory() {
  272. return shareDirectory;
  273. }
  274. public void setShareDirectory(Integer shareDirectory) {
  275. this.shareDirectory = shareDirectory;
  276. }
  277. public String getSpeechUrl() {
  278. return speechUrl;
  279. }
  280. public void setSpeechUrl(String speechUrl) {
  281. this.speechUrl = speechUrl;
  282. }
  283. public Integer getState() {
  284. return state;
  285. }
  286. public void setState(Integer state) {
  287. this.state = state;
  288. }
  289. public Integer getType() {
  290. return type;
  291. }
  292. public void setType(Integer type) {
  293. this.type = type;
  294. }
  295. public String getUrl() {
  296. return url;
  297. }
  298. public void setUrl(String url) {
  299. this.url = url;
  300. }
  301. public Long getUserId() {
  302. return userId;
  303. }
  304. public void setUserId(Long userId) {
  305. this.userId = userId;
  306. }
  307. public String getVideoTime() {
  308. return videoTime;
  309. }
  310. public void setVideoTime(String videoTime) {
  311. this.videoTime = videoTime;
  312. }
  313. public Integer getViewNumber() {
  314. return viewNumber;
  315. }
  316. public void setViewNumber(Integer viewNumber) {
  317. this.viewNumber = viewNumber;
  318. }
  319. public Integer getWorkGiveLike() {
  320. return workGiveLike;
  321. }
  322. public void setWorkGiveLike(Integer workGiveLike) {
  323. this.workGiveLike = workGiveLike;
  324. }
  325. public Long getWorkHeight() {
  326. return workHeight;
  327. }
  328. public void setWorkHeight(Long workHeight) {
  329. this.workHeight = workHeight;
  330. }
  331. public String getWorkTags() {
  332. return workTags;
  333. }
  334. public void setWorkTags(String workTags) {
  335. this.workTags = workTags;
  336. }
  337. public Long getWorkWidth() {
  338. return workWidth;
  339. }
  340. public void setWorkWidth(Long workWidth) {
  341. this.workWidth = workWidth;
  342. }
  343. public String getWorkYear() {
  344. return workYear;
  345. }
  346. public void setWorkYear(String workYear) {
  347. this.workYear = workYear;
  348. }
  349. }
OssService :(OSS上传服务)
  1. package com.example.testcsdnproject.picdemo;
  2. import android.content.Context;
  3. import android.net.Uri;
  4. import android.text.TextUtils;
  5. import android.util.Log;
  6. import com.alibaba.sdk.android.oss.ClientConfiguration;
  7. import com.alibaba.sdk.android.oss.ClientException;
  8. import com.alibaba.sdk.android.oss.OSS;
  9. import com.alibaba.sdk.android.oss.OSSClient;
  10. import com.alibaba.sdk.android.oss.ServiceException;
  11. import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
  12. import com.alibaba.sdk.android.oss.callback.OSSProgressCallback;
  13. import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
  14. import com.alibaba.sdk.android.oss.common.auth.OSSPlainTextAKSKCredentialProvider;
  15. import com.alibaba.sdk.android.oss.internal.OSSAsyncTask;
  16. import com.alibaba.sdk.android.oss.model.PutObjectRequest;
  17. import com.alibaba.sdk.android.oss.model.PutObjectResult;
  18. import org.json.JSONException;
  19. import org.json.JSONObject;
  20. import java.io.File;
  21. import java.util.HashMap;
  22. import java.util.List;
  23. import java.util.Random;
  24. public class OssService {
  25. private OSS oss;
  26. private Context context;
  27. private ProgressCallback progressCallback;
  28. public final static String endpoint = "http://oss-cn-shenzhen.aliyuncs.com";
  29. public final static String accessKeyId = "自己填参数";//
  30. public final static String accessKeySecret = "自己申请参数";
  31. public final static String bucketName = "testCsdn";
  32. public int mType;
  33. public OssService(Context context, int type) {
  34. this.context = context;
  35. this.mType = type;
  36. }
  37. public void initOSSClient() {
  38. //OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider("<StsToken.AccessKeyId>", "<StsToken.SecretKeyId>", "<StsToken.SecurityToken>");
  39. //这个初始化安全性没有Sts安全,如需要很高安全性建议用OSSStsTokenCredentialProvider创建(上一行创建方式)多出的参数SecurityToken为临时授权参数
  40. final OSSCredentialProvider credentialProvider = new OSSPlainTextAKSKCredentialProvider(accessKeyId, accessKeySecret);
  41. final ClientConfiguration conf = new ClientConfiguration();
  42. conf.setConnectionTimeout(15 * 1000); // 连接超时,默认15秒
  43. conf.setSocketTimeout(15 * 1000); // socket超时,默认15秒
  44. conf.setMaxConcurrentRequest(9); // 最大并发请求数,默认5个
  45. conf.setMaxErrorRetry(2); // 失败后最大重试次数,默认2次
  46. // oss为全局变量,endpoint是一个OSS区域地址
  47. oss = new OSSClient(context, endpoint, credentialProvider, conf);
  48. }
  49. public void beginupload(final Context context, String filename, String path, String osspath, final String callbackbody, String houzhuiming) {
  50. //通过填写文件名形成objectname,通过这个名字指定上传和下载的文件
  51. String objectname = filename;
  52. if (objectname == null || objectname.equals("")) {
  53. // ToastUtils.sh("文件名不能为空");
  54. return;
  55. }
  56. //下面3个参数依次为bucket名,Object名,上传文件路径
  57. Log.e("colin: ", callbackbody + "=========" + osspath + objectname + getRandomString() + houzhuiming);
  58. PutObjectRequest put = new PutObjectRequest(bucketName, osspath + objectname +getRandomString() + houzhuiming, path);
  59. if (path == null || path.equals("")) {
  60. return;
  61. }
  62. put.setCallbackParam(new HashMap<String, String>() {
  63. {
  64. put("callbackUrl", "拼接服务器域名"/*AppConstant.OSS_IMAGE_URL*/);
  65. put("callbackBody", callbackbody);
  66. }
  67. });
  68. // 异步上传,可以设置进度回调
  69. put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
  70. @Override
  71. public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
  72. // LogUtil.d("currentSize: " + currentSize + " totalSize: " + totalSize);
  73. double progress = currentSize * 1.0 / totalSize * 100.f;
  74. if (progressCallback != null) {
  75. progressCallback.onProgressCallback(progress);
  76. }
  77. }
  78. });
  79. @SuppressWarnings("rawtypes")
  80. OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
  81. @Override
  82. public void onSuccess(PutObjectRequest request, PutObjectResult result) {
  83. Log.d("colin", "UploadSuccess");
  84. // 只有设置了servercallback,这个值才有数据
  85. String serverCallbackReturnJson = result.getServerCallbackReturnBody();
  86. Log.d("colin", serverCallbackReturnJson);
  87. try {
  88. JSONObject jsonObject = new JSONObject(serverCallbackReturnJson);
  89. String avatar_url = "";
  90. switch (mType) {
  91. case 1:
  92. avatar_url = jsonObject.optString("avatar_url");
  93. break;
  94. case 14:
  95. avatar_url = jsonObject.optString("avatar_url");
  96. break;
  97. case 3:
  98. avatar_url = jsonObject.optString("imageUrl");
  99. break;
  100. case 6:
  101. avatar_url = jsonObject.optString("artShowCoverUrl");
  102. break;
  103. case 9:
  104. avatar_url = jsonObject.optString("photoUrl");
  105. break;
  106. case 11:
  107. avatar_url = jsonObject.optString("videoCoverUrl");
  108. break;
  109. case 2:
  110. avatar_url = "";
  111. break;
  112. }
  113. mOnCallbackClickListener.onCallBack(avatar_url,serverCallbackReturnJson);
  114. } catch (JSONException e) {
  115. e.printStackTrace();
  116. }
  117. }
  118. @Override
  119. public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
  120. // 请求异常
  121. //
  122. if (clientExcepion != null) {
  123. // 本地异常如网络异常等
  124. // LogUtil.e("UploadFailure:表示向OSS发送请求或解析来自OSS的响应时发生错误。\n" +
  125. // " *例如,当网络不可用时,这个异常将被抛出");
  126. clientExcepion.printStackTrace();
  127. }
  128. if (serviceException != null) {
  129. // 服务异常
  130. // LogUtil.e("UploadFailure:表示在OSS服务端发生错误");
  131. Log.e("ErrorCode", serviceException.getErrorCode());
  132. Log.e("RequestId", serviceException.getRequestId());
  133. Log.e("HostId", serviceException.getHostId());
  134. Log.e("RawMessage", serviceException.getRawMessage());
  135. }
  136. }
  137. });
  138. //task.cancel(); // 可以取消任务
  139. // task.waitUntilFinished(); // 可以等待直到任务完成
  140. }
  141. public ProgressCallback getProgressCallback() {
  142. return progressCallback;
  143. }
  144. public void setProgressCallback(ProgressCallback progressCallback) {
  145. this.progressCallback = progressCallback;
  146. }
  147. public interface ProgressCallback {
  148. void onProgressCallback(double progress);
  149. }
  150. private onCallbackClickListener mOnCallbackClickListener;
  151. public interface onCallbackClickListener {
  152. void onCallBack(String imageurl,String json);
  153. }
  154. public void setCallbackClickListener(onCallbackClickListener clickListener) {
  155. this.mOnCallbackClickListener = clickListener;
  156. }
  157. /*---------------------- 分割线 -------------------------*/
  158. private onCallbackVideoClickListener mOnCallbackVideoClickListener;
  159. public interface onCallbackVideoClickListener {
  160. void onCallBackVideo(String imageurl,String coverUrl,String json);
  161. }
  162. public void setCallbackVideoClickListener(onCallbackVideoClickListener clickListener) {
  163. this.mOnCallbackVideoClickListener = clickListener;
  164. }
  165. /*---------------------- 分割线 -------------------------*/
  166. /**
  167. * 阿里云OSS上传(默认是异步多文件上传)
  168. * 布展上传封面
  169. * @param urls
  170. */
  171. public void ossUpload(final List<String> urls) {
  172. if (urls.size() <= 0) {
  173. // 文件全部上传完毕,这里编写上传结束的逻辑,如果要在主线程操作,最好用Handler或runOnUiThead做对应逻辑
  174. return;// 这个return必须有,否则下面报越界异常,原因自己思考下哈
  175. }
  176. final String url = urls.get(0);
  177. if (TextUtils.isEmpty(url)) {
  178. urls.remove(0);
  179. // url为空就没必要上传了,这里做的是跳过它继续上传的逻辑。
  180. ossUpload(urls);
  181. return;
  182. }
  183. Uri uri = Uri.parse(url);
  184. File file = new File(uri.getPath());
  185. if (null == file || !file.exists()) {
  186. urls.remove(0);
  187. // 文件为空或不存在就没必要上传了,这里做的是跳过它继续上传的逻辑。
  188. ossUpload(urls);
  189. return;
  190. }
  191. // 文件后缀
  192. String fileSuffix = "";
  193. if (file.isFile()) {
  194. // 获取文件后缀名
  195. fileSuffix = file.getName().substring(file.getName().lastIndexOf("."));
  196. }
  197. // 文件标识符objectKey
  198. final String objectKey = "alioss_" + System.currentTimeMillis() + fileSuffix;
  199. final String objectKey1 = "image/" +System.currentTimeMillis()+getFileName(url)+"_"+
  200. getRandomString()+"_"+urls.size()+ fileSuffix;
  201. // 下面3个参数依次为bucket名,ObjectKey名,上传文件路径
  202. PutObjectRequest put = new PutObjectRequest(bucketName, objectKey1, url);
  203. // 设置进度回调
  204. put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
  205. @Override
  206. public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
  207. // 进度逻辑
  208. }
  209. });
  210. // 异步上传
  211. OSSAsyncTask task = oss.asyncPutObject(put,
  212. new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
  213. @Override
  214. public void onSuccess(PutObjectRequest request, PutObjectResult result) { // 上传成功
  215. urls.remove(0);
  216. ossUpload(urls);// 递归同步效果
  217. // 只有设置了servercallback,这个值才有数据
  218. String serverCallbackReturnJson = result.getServerCallbackReturnBody();
  219. mOnCallbackClickListener.onCallBack(objectKey1,serverCallbackReturnJson);
  220. }
  221. @Override
  222. public void onFailure(PutObjectRequest request, ClientException clientExcepion,
  223. ServiceException serviceException) { // 上传失败
  224. // 请求异常
  225. if (clientExcepion != null) {
  226. // 本地异常如网络异常等
  227. clientExcepion.printStackTrace();
  228. }
  229. if (serviceException != null) {
  230. // 服务异常
  231. Log.e("ErrorCode", serviceException.getErrorCode());
  232. Log.e("RequestId", serviceException.getRequestId());
  233. Log.e("HostId", serviceException.getHostId());
  234. Log.e("RawMessage", serviceException.getRawMessage());
  235. }
  236. }
  237. });
  238. // task.cancel(); // 可以取消任务
  239. // task.waitUntilFinished(); // 可以等待直到任务完成
  240. }
  241. /**
  242. * 批量上传 包括视频
  243. * @param urls
  244. */
  245. public void ossUploadVideo(final List<AddArtWorksBean> urls) { //AddArtWorksBean自己定义的作品实体类,包括url跟类型
  246. if (urls.size() <= 0) {
  247. // 文件全部上传完毕,这里编写上传结束的逻辑,如果要在主线程操作,最好用Handler或runOnUiThead做对应逻辑
  248. return;// 这个return必须有,否则下面报越界异常,原因自己思考下哈
  249. }
  250. final String url = urls.get(0).getUrl();
  251. String cover = urls.get(0).getCover();
  252. int type = 0;
  253. if (null!=urls.get(0).getType()){
  254. type = urls.get(0).getType(); //文件类型 2视频 其他图片
  255. }
  256. if (TextUtils.isEmpty(url)) {
  257. urls.remove(0);
  258. // url为空就没必要上传了,这里做的是跳过它继续上传的逻辑。
  259. ossUploadVideo(urls);
  260. return;
  261. }
  262. Uri uri = Uri.parse(url);
  263. File file = new File(uri.getPath());
  264. if (null == file || !file.exists()) {
  265. // if (null == file || uri==null) {
  266. urls.remove(0);
  267. // 文件为空或不存在就没必要上传了,这里做的是跳过它继续上传的逻辑。
  268. ossUploadVideo(urls);
  269. return;
  270. }
  271. // 文件后缀
  272. String fileSuffix = "";
  273. if (file.isFile()) {
  274. // 获取文件后缀名
  275. fileSuffix = file.getName().substring(file.getName().lastIndexOf("."));
  276. }
  277. // 文件标识符objectKey
  278. final String objectKey = "alioss_" + System.currentTimeMillis() + fileSuffix;
  279. final String objectKey1 = "image/" +System.currentTimeMillis()+getFileName(url)+"_"+
  280. getRandomString()+"_"+urls.size()+ fileSuffix;
  281. String objectKeyCover = null;
  282. if (cover!=null){
  283. objectKeyCover = "cover/" +System.currentTimeMillis()+getFileName(cover)+"_"+
  284. getRandomString()+"_"+urls.size()+".png" ;
  285. }
  286. // 下面3个参数依次为bucket名,ObjectKey名,上传文件路径
  287. PutObjectRequest put = new PutObjectRequest(bucketName, objectKey1, url);
  288. PutObjectRequest putCover = new PutObjectRequest(bucketName, objectKeyCover, cover);
  289. // 设置进度回调
  290. put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
  291. @Override
  292. public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
  293. // 进度逻辑
  294. double progress = currentSize * 1.0 / totalSize * 100.f;
  295. if (progressCallback != null) {
  296. progressCallback.onProgressCallback(progress);
  297. }
  298. }
  299. });
  300. putCover.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
  301. @Override
  302. public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
  303. double progress = currentSize * 1.0 / totalSize * 100.f;
  304. if (progressCallback != null) {
  305. progressCallback.onProgressCallback(progress);
  306. }
  307. }
  308. });
  309. // 异步上传
  310. if (type==2){
  311. OSSAsyncTask task = oss.asyncPutObject(put,
  312. new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
  313. @Override
  314. public void onSuccess(PutObjectRequest request, PutObjectResult result) { // 上传成功
  315. }
  316. @Override
  317. public void onFailure(PutObjectRequest request, ClientException clientExcepion,
  318. ServiceException serviceException) { // 上传失败
  319. if (clientExcepion != null) {
  320. clientExcepion.printStackTrace();
  321. }
  322. if (serviceException != null) {
  323. Log.e("ErrorCode", serviceException.getErrorCode());
  324. Log.e("RequestId", serviceException.getRequestId());
  325. Log.e("HostId", serviceException.getHostId());
  326. Log.e("RawMessage", serviceException.getRawMessage());
  327. }
  328. }
  329. });
  330. String finalObjectKeyCover = objectKeyCover;
  331. OSSAsyncTask taskCover = oss.asyncPutObject(putCover,
  332. new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
  333. @Override
  334. public void onSuccess(PutObjectRequest request, PutObjectResult result) { // 上传成功
  335. urls.remove(0);
  336. ossUploadVideo(urls);// 递归同步效果
  337. // 只有设置了servercallback,这个值才有数据
  338. String serverCallbackReturnJson = result.getServerCallbackReturnBody();
  339. mOnCallbackVideoClickListener.onCallBackVideo(objectKey1, finalObjectKeyCover,serverCallbackReturnJson);
  340. }
  341. @Override
  342. public void onFailure(PutObjectRequest request, ClientException clientExcepion,
  343. ServiceException serviceException) { // 上传失败
  344. if (clientExcepion != null) {
  345. clientExcepion.printStackTrace();
  346. }
  347. if (serviceException != null) {
  348. Log.e("ErrorCode", serviceException.getErrorCode());
  349. Log.e("RequestId", serviceException.getRequestId());
  350. Log.e("HostId", serviceException.getHostId());
  351. Log.e("RawMessage", serviceException.getRawMessage());
  352. }
  353. }
  354. });
  355. }else{
  356. String finalObjectKeyCover1 = objectKeyCover;
  357. OSSAsyncTask task = oss.asyncPutObject(put,
  358. new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
  359. @Override
  360. public void onSuccess(PutObjectRequest request, PutObjectResult result) { // 上传成功
  361. urls.remove(0);
  362. ossUploadVideo(urls);// 递归同步效果
  363. // 只有设置了servercallback,这个值才有数据
  364. String serverCallbackReturnJson = result.getServerCallbackReturnBody();
  365. // mOnCallbackClickListener.onCallBack(objectKey1,serverCallbackReturnJson);
  366. mOnCallbackVideoClickListener.onCallBackVideo(objectKey1, finalObjectKeyCover1,serverCallbackReturnJson);
  367. }
  368. @Override
  369. public void onFailure(PutObjectRequest request, ClientException clientExcepion,
  370. ServiceException serviceException) { // 上传失败
  371. if (clientExcepion != null) {
  372. clientExcepion.printStackTrace();
  373. }
  374. if (serviceException != null) {
  375. Log.e("ErrorCode", serviceException.getErrorCode());
  376. Log.e("RequestId", serviceException.getRequestId());
  377. Log.e("HostId", serviceException.getHostId());
  378. Log.e("RawMessage", serviceException.getRawMessage());
  379. }
  380. }
  381. });
  382. }
  383. }
  384. /**
  385. * 发布动态上传图片
  386. * @param urls
  387. */
  388. public void ossUploadDynamic(final List<String> urls) {
  389. if (urls.size() <= 0) {
  390. // 文件全部上传完毕,这里编写上传结束的逻辑,如果要在主线程操作,最好用Handler或runOnUiThead做对应逻辑
  391. return;// 这个return必须有,否则下面报越界异常,原因自己思考下哈
  392. }
  393. final String url = urls.get(0);
  394. if (TextUtils.isEmpty(url)) {
  395. urls.remove(0);
  396. ossUploadDynamic(urls);
  397. return;
  398. }
  399. Uri uri = Uri.parse(url);
  400. File file = new File(uri.getPath());
  401. if (null == file || !file.exists()) {
  402. urls.remove(0);
  403. ossUploadDynamic(urls);
  404. return;
  405. }
  406. String fileSuffix = "";
  407. if (file.isFile()) {
  408. fileSuffix = file.getName().substring(file.getName().lastIndexOf("."));
  409. }
  410. if (url.contains("mp4")){
  411. final String objectKeyVideo = "findDynamicVideo/" +System.currentTimeMillis()+
  412. getFileName(url)+"_"+getRandomString()+"_"+urls.size()+ fileSuffix;
  413. PutObjectRequest put = new PutObjectRequest(bucketName, objectKeyVideo, url);
  414. put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
  415. @Override
  416. public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
  417. }
  418. });
  419. OSSAsyncTask task = oss.asyncPutObject(put,
  420. new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
  421. @Override
  422. public void onSuccess(PutObjectRequest request, PutObjectResult result) { // 上传成功
  423. urls.remove(0);
  424. ossUploadDynamic(urls);// 递归同步效果
  425. // 只有设置了servercallback,这个值才有数据
  426. String serverCallbackReturnJson = result.getServerCallbackReturnBody();
  427. mOnCallbackClickListener.onCallBack(objectKeyVideo,serverCallbackReturnJson);
  428. }
  429. @Override
  430. public void onFailure(PutObjectRequest request, ClientException clientExcepion,
  431. ServiceException serviceException) { // 上传失败
  432. if (clientExcepion != null) {
  433. clientExcepion.printStackTrace();
  434. }
  435. if (serviceException != null) {
  436. }
  437. }
  438. });
  439. }else{
  440. final String objectKeyImage = "findDynamicImage/" +System.currentTimeMillis()+
  441. getFileName(url)+"_"+getRandomString()+"_"+urls.size()+ fileSuffix;
  442. PutObjectRequest put = new PutObjectRequest(bucketName, objectKeyImage, url);
  443. put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
  444. @Override
  445. public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
  446. }
  447. });
  448. OSSAsyncTask task = oss.asyncPutObject(put,
  449. new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
  450. @Override
  451. public void onSuccess(PutObjectRequest request, PutObjectResult result) { // 上传成功
  452. urls.remove(0);
  453. ossUploadDynamic(urls);// 递归同步效果
  454. // 只有设置了servercallback,这个值才有数据
  455. String serverCallbackReturnJson = result.getServerCallbackReturnBody();
  456. mOnCallbackClickListener.onCallBack(objectKeyImage,serverCallbackReturnJson);
  457. }
  458. @Override
  459. public void onFailure(PutObjectRequest request, ClientException clientExcepion,
  460. ServiceException serviceException) { // 上传失败
  461. if (clientExcepion != null) {
  462. clientExcepion.printStackTrace();
  463. }
  464. if (serviceException != null) {
  465. }
  466. }
  467. });
  468. }
  469. }
  470. /**
  471. * 阿里云OSS上传(默认是异步多文件上传)
  472. * 只上传图片
  473. * 在主页画作装裱中使用
  474. * @param urls
  475. */
  476. public void ossUploadSculptureSquare(final List<String> urls,String OssFileName) {
  477. if (urls.size() <= 0) {
  478. // 文件全部上传完毕,这里编写上传结束的逻辑,如果要在主线程操作,最好用Handler或runOnUiThead做对应逻辑
  479. return;// 这个return必须有,否则下面报越界异常,原因自己思考下哈
  480. }
  481. final String url = urls.get(0);
  482. if (TextUtils.isEmpty(url)) {
  483. urls.remove(0);
  484. // url为空就没必要上传了,这里做的是跳过它继续上传的逻辑。
  485. ossUpload(urls);
  486. return;
  487. }
  488. Uri uri = Uri.parse(url);
  489. File file = new File(uri.getPath());
  490. if (null == file || !file.exists()) {
  491. // if (null == file || uri==null) {
  492. urls.remove(0);
  493. // 文件为空或不存在就没必要上传了,这里做的是跳过它继续上传的逻辑。
  494. ossUpload(urls);
  495. return;
  496. }
  497. // 文件后缀
  498. String fileSuffix = "";
  499. if (file.isFile()) {
  500. // 获取文件后缀名
  501. fileSuffix = file.getName().substring(file.getName().lastIndexOf("."));
  502. }
  503. // 文件标识符objectKey
  504. final String objectKey1 = OssFileName+System.currentTimeMillis()+
  505. getFileName(url)+"_"+getRandomString()+"_"+urls.size()+ fileSuffix;
  506. // 下面3个参数依次为bucket名,ObjectKey名,上传文件路径
  507. PutObjectRequest put = new PutObjectRequest(bucketName, objectKey1, url);
  508. // 设置进度回调
  509. put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
  510. @Override
  511. public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
  512. // 进度逻辑
  513. }
  514. });
  515. // 异步上传
  516. OSSAsyncTask task = oss.asyncPutObject(put,
  517. new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
  518. @Override
  519. public void onSuccess(PutObjectRequest request, PutObjectResult result) { // 上传成功
  520. urls.remove(0);
  521. ossUpload(urls);// 递归同步效果
  522. // 只有设置了servercallback,这个值才有数据
  523. String serverCallbackReturnJson = result.getServerCallbackReturnBody();
  524. mOnCallbackClickListener.onCallBack(objectKey1,serverCallbackReturnJson);
  525. }
  526. @Override
  527. public void onFailure(PutObjectRequest request, ClientException clientExcepion,
  528. ServiceException serviceException) { // 上传失败
  529. // 请求异常
  530. if (clientExcepion != null) {
  531. // 本地异常如网络异常等
  532. clientExcepion.printStackTrace();
  533. }
  534. if (serviceException != null) {
  535. }
  536. }
  537. });
  538. }
  539. public static String getRandomString() {
  540. String base = "abcdefghijklmnopqrstuvwxyz0123456789";
  541. Random random = new Random();
  542. StringBuffer sb = new StringBuffer();
  543. for (int i = 0; i < base.length(); i++) {
  544. int number = random.nextInt(base.length());
  545. sb.append(base.charAt(number));
  546. }
  547. return sb.toString();
  548. }
  549. public static String getFileName(String pathandname) {
  550. int start = pathandname.lastIndexOf("/");
  551. int end = pathandname.lastIndexOf(".");
  552. if (start != -1 && end != -1) {
  553. return pathandname.substring(start + 1, end);
  554. } else {
  555. return null;
  556. }
  557. }
  558. }

 这里就已经完成了正常的批量选择图片并上传了。

================分割线=========================

批量上传图片视频
MassUploadActivity:
  1. package com.example.testcsdnproject.picdemo;
  2. import androidx.annotation.NonNull;
  3. import androidx.annotation.Nullable;
  4. import androidx.appcompat.app.AppCompatActivity;
  5. import androidx.recyclerview.widget.RecyclerView;
  6. import androidx.recyclerview.widget.StaggeredGridLayoutManager;
  7. import android.content.Intent;
  8. import android.content.pm.ActivityInfo;
  9. import android.graphics.Bitmap;
  10. import android.media.MediaMetadataRetriever;
  11. import android.os.Bundle;
  12. import android.os.Handler;
  13. import android.os.Message;
  14. import android.util.Log;
  15. import android.view.View;
  16. import android.widget.ProgressBar;
  17. import android.widget.TextView;
  18. import android.widget.Toast;
  19. import com.example.testcsdnproject.R;
  20. import com.luck.picture.lib.PictureSelector;
  21. import com.luck.picture.lib.config.PictureMimeType;
  22. import com.luck.picture.lib.entity.LocalMedia;
  23. import java.io.BufferedOutputStream;
  24. import java.io.File;
  25. import java.io.FileOutputStream;
  26. import java.io.IOException;
  27. import java.math.BigDecimal;
  28. import java.util.ArrayList;
  29. import java.util.List;
  30. import okhttp3.RequestBody;
  31. /**
  32. * 批量上传图片视频
  33. */
  34. public class MassUploadActivity extends AppCompatActivity {
  35. private RecyclerView rv_mass_upload;
  36. private TextView tv_upload;
  37. private TextView tv_count,tv_total;
  38. private ProgressBar progressBar;
  39. // private PicAdapter libAdapter; //返回图片适配器 自己写一个吧 就一个imageview 数据体是List<LocalMedia> list ,加载图片:list.get(0).getPath
  40. private Handler mHandler = new Handler(){
  41. @Override
  42. public void handleMessage(@NonNull Message msg) {
  43. super.handleMessage(msg);
  44. switch (msg.what){
  45. case 1:
  46. tv_count.setText(uploadedCount+"");
  47. tv_total.setText("/"+uploadedTotalCount);
  48. progressBar.setMax(uploadedTotalCount);
  49. progressBar.setProgress(uploadedCount);
  50. break;
  51. case 2:
  52. addArtWorksBeans.clear();
  53. for (int i = 0;i<backArtWorksBeans.size();i++){
  54. AddArtWorksBean addArtWorksBean =new AddArtWorksBean();
  55. addArtWorksBean.setUrl(paintingUrlsCallback.get(i));
  56. addArtWorksBean.setName(paintingUrlsCallback.get(i));
  57. addArtWorksBean.setImageHeight(Long.valueOf(albumSelectList.get(i).getHeight()));
  58. addArtWorksBean.setImageWidth(Long.valueOf(albumSelectList.get(i).getWidth()));
  59. // addArtWorksBean.setType(selectList.get(i).getPath().contains(".mp4")?2:1);
  60. addArtWorksBean.setType(albumSelectList.get(i).getRealPath().contains("mp4")?2:1);
  61. String url_cover = backArtWorksBeans.get(i).getCover()/*+"?spm=qipa250&x-oss-process=video/snapshot,t_1000,f_jpg,w_0,h_0,m_fast"*/;
  62. addArtWorksBean.setCover(albumSelectList.get(i).getRealPath().contains("mp4")?url_cover:"");
  63. addArtWorksBeans.add(addArtWorksBean);
  64. }
  65. //请求接口上传数据
  66. /*String json = new Gson().toJson(addArtWorksBeans);
  67. RequestBody requestBody = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), json);
  68. addArtWorksPresenter.addArtWorks(requestBody);*/
  69. //上传成功后更新列表数据
  70. // libAdapter.setNewData();
  71. break;
  72. }
  73. }
  74. };
  75. @Override
  76. protected void onCreate(Bundle savedInstanceState) {
  77. super.onCreate(savedInstanceState);
  78. setContentView(R.layout.activity_mass_upload);
  79. rv_mass_upload = findViewById(R.id.rv_mass_upload);
  80. tv_upload = findViewById(R.id.tv_upload);
  81. tv_count = findViewById(R.id.tv_upload_count);
  82. tv_total = findViewById(R.id.tv_upload_total);
  83. progressBar = findViewById(R.id.upload_progress_bar);
  84. // libAdapter = new PicAdapter(null);
  85. // rv_mass_upload.setAdapter(libAdapter);
  86. StaggeredGridLayoutManager libLayoutManager = new StaggeredGridLayoutManager(4,
  87. StaggeredGridLayoutManager.VERTICAL);
  88. rv_mass_upload.setLayoutManager(libLayoutManager);
  89. openPic();
  90. tv_upload.setOnClickListener(new View.OnClickListener() {
  91. @Override
  92. public void onClick(View view) {
  93. openPic();
  94. }
  95. });
  96. }
  97. //打开相册选择图片
  98. private void openPic(){
  99. PictureSelector.create(MassUploadActivity.this)
  100. .openGallery(PictureMimeType.ofAll())
  101. .imageEngine(GlideEngine.createGlideEngine())
  102. // .loadImageEngine(GlideEngine.createGlideEngine())// 图片加载引擎 需要 implements ImageEngine接口
  103. // .enableCrop(true)//是否开启裁剪
  104. .rotateEnabled(false)//裁剪是否可旋转图片
  105. .isMaxSelectEnabledMask(true)//选择条件达到阀时列表是否启用蒙层效果
  106. // .isCamera(true)//列表是否显示拍照按钮
  107. .maxSelectNum(20)// 最大图片选择数量
  108. // .minSelectNum(1)// 最小选择数量
  109. .maxVideoSelectNum(20) // 视频最大选择数量
  110. // .queryMaxFileSize(10)// 只查多少M以内的图片、视频、音频 单位。
  111. .isDragFrame(true)//是否可拖动裁剪框(固定)
  112. .isWithVideoImage(true)//图片和视频是否可以同选,只在ofAll模式下有效
  113. .imageSpanCount(6)// 每行显示个数
  114. .setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)// 设置相册Activity方向,不设置默认使用系统
  115. .isOriginalImageControl(true)// 是否显示原图控制按钮,如果设置为true则用户可以自由选择是否使用原图,压缩、裁剪功能将会失效
  116. // .withAspectRatio(1, 1)//裁剪比例
  117. .isWeChatStyle(true)
  118. .forResult(824);
  119. }
  120. @Override
  121. protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
  122. super.onActivityResult(requestCode, resultCode, data);
  123. if (resultCode == RESULT_OK && requestCode == 824) { //新版上传相册作品
  124. albumSelectList = PictureSelector.obtainMultipleResult(data);
  125. calculationAverageProgress();
  126. uploadPainting();
  127. }
  128. }
  129. /** 等待对话框 */
  130. // private BaseDialog mWaitUploadDialog;
  131. boolean isCancelUpload;
  132. private String filePaintingPath = "";
  133. private List<String> paintingUrls = new ArrayList<>();
  134. private List<String> paintingUrlsCallback = new ArrayList<>();
  135. private List<AddArtWorksBean> addArtWorksBeans = new ArrayList<>();
  136. private List<AddArtWorksBean> backArtWorksBeans = new ArrayList<>();
  137. private List<LocalMedia> albumSelectList = new ArrayList<>();
  138. double mAverageProgress;//每一个需要上传至oss的本地作品最大的进度值
  139. int uploadedTotalCount = 0;//需要上传的所有数量
  140. int uploadedCount = 0;//已上传数量
  141. OssService ossService;
  142. private List<AddArtWorksBean> toOssBeans = new ArrayList<>();
  143. private void uploadPainting(){
  144. uploadedCount = 0;
  145. isCancelUpload = false;
  146. /*OssService*/ ossService = new OssService(this, 1);
  147. ossService.initOSSClient();
  148. if (albumSelectList.size() == 0) {
  149. Toast.makeText(MassUploadActivity.this,"请添加作品",Toast.LENGTH_SHORT).show();
  150. return;
  151. }
  152. paintingUrls.clear();
  153. toOssBeans.clear();
  154. for (int i = 0; i<albumSelectList.size();i++){
  155. // filePath = selectList.get(i).getPath();
  156. filePaintingPath = albumSelectList.get(i).getRealPath();
  157. paintingUrls.add(filePaintingPath);
  158. AddArtWorksBean addArtWorksBean = new AddArtWorksBean();
  159. addArtWorksBean.setUrl(filePaintingPath);
  160. if (filePaintingPath.contains("mp4")){
  161. addArtWorksBean.setType(2);
  162. addArtWorksBean.setCover(saveBitmap2file(albumSelectList.get(i).getRealPath(),"artvr_"+System.currentTimeMillis()));
  163. }else{
  164. addArtWorksBean.setType(1);
  165. }
  166. toOssBeans.add(addArtWorksBean);
  167. }
  168. ossService.ossUploadVideo(toOssBeans);
  169. /* if (mWaitUploadDialog == null) {
  170. mWaitUploadDialog = new UploadProgressDialog.Builder(ExhibitActivity.this)
  171. // 消息文本可以不用填写
  172. // .setMessage("正在上传,请耐心等待("+uploadedCount+"/"+uploadedTotalCount+")")
  173. .setMessage(uploadedCount+"",uploadedTotalCount+"")
  174. .setUploadCloseListener(this)
  175. .create();
  176. }
  177. if (!mWaitUploadDialog.isShowing()) {
  178. mWaitUploadDialog.show();
  179. }*/
  180. paintingUrlsCallback.clear();
  181. backArtWorksBeans.clear();
  182. //上传回调
  183. ossService.setCallbackVideoClickListener(new OssService.onCallbackVideoClickListener() {
  184. @Override
  185. public void onCallBackVideo(String imageurl, String coverUrl, String json) {
  186. if (!isCancelUpload){
  187. uploadedCount++;
  188. mHandler.sendEmptyMessage(1);
  189. Log.d("colinworkossVideo","imageUrl = "+ imageurl+" coverUrl : "+ coverUrl+ " JSONStr = "+json);
  190. paintingUrlsCallback.add(imageurl);
  191. AddArtWorksBean addArtWorksBean = new AddArtWorksBean();
  192. addArtWorksBean.setUrl(imageurl);
  193. addArtWorksBean.setCover(coverUrl);
  194. backArtWorksBeans.add(addArtWorksBean);
  195. if (backArtWorksBeans.size() == albumSelectList.size()){
  196. mHandler.sendEmptyMessage(2);
  197. }
  198. }else{
  199. ossService.initOSSClient();
  200. }
  201. }
  202. });
  203. }
  204. /* @Override
  205. public void CloseUploadDialog() {
  206. if (mWaitUploadDialog.isShowing()){
  207. mWaitUploadDialog.dismiss();
  208. isCancelUpload = true;
  209. mWaitUploadDialog = null;
  210. }
  211. }*/
  212. /**
  213. * 计算每一个作品的上传进度
  214. */
  215. private void calculationAverageProgress() {
  216. uploadedTotalCount = albumSelectList.size();
  217. if (uploadedTotalCount == 0) {
  218. return;
  219. }
  220. mAverageProgress = format(100d / uploadedTotalCount, 2);
  221. }
  222. /**
  223. * 格式化精度
  224. *
  225. * @param v
  226. * @param point 小数位数
  227. * @return double
  228. */
  229. public static Double format(double v, int point) {
  230. BigDecimal b = new BigDecimal(v);
  231. return b.setScale(point, BigDecimal.ROUND_HALF_UP).doubleValue();
  232. }
  233. /**
  234. * 将bitmap转文件
  235. * <p>
  236. * // * @param bmp
  237. * // * @param filename
  238. *
  239. * @return
  240. */
  241. public String saveBitmap2file(String videoFilePath, String imagename) {
  242. String imagepath = "";
  243. //创建MediaMetadataRetriever对象
  244. MediaMetadataRetriever mmr = new MediaMetadataRetriever();
  245. //设置资源位置
  246. if (videoFilePath == null) {
  247. return "";
  248. }
  249. try {
  250. mmr.setDataSource(videoFilePath);
  251. } catch (IllegalArgumentException e) {
  252. e.printStackTrace();
  253. }
  254. //获取第一帧图像的bitmap对象
  255. Bitmap bitmap = mmr.getFrameAtTime();
  256. // File file = new File(Environment.getExternalStorageDirectory() + "/" + imagename + ".png");//将要保存图片的路径
  257. File file = new File( getApplicationContext().getFilesDir() + "/" + imagename + ".png");//将要保存图片的路径
  258. try {
  259. BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
  260. bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
  261. bos.flush();
  262. bos.close();
  263. // imagepath = Environment.getExternalStorageDirectory() + "/" + imagename + ".png";
  264. imagepath = getApplicationContext().getFilesDir() + "/" + imagename + ".png";
  265. //通知图库有更新
  266. // MyApplication.mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + file.getPath())));
  267. } catch (IOException e) {
  268. e.printStackTrace();
  269. }
  270. return imagepath;
  271. }
  272. }

xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. tools:context=".picdemo.MassUploadActivity">
  8. <androidx.recyclerview.widget.RecyclerView
  9. android:id="@+id/rv_mass_upload"
  10. android:layout_width="match_parent"
  11. android:layout_height="wrap_content"
  12. />
  13. <TextView
  14. android:id="@+id/tv_upload"
  15. android:layout_width="match_parent"
  16. android:layout_height="wrap_content"
  17. android:layout_alignParentBottom="true"
  18. android:layout_centerHorizontal="true"
  19. android:text="批量上传"
  20. android:textColor="@color/white"
  21. android:textSize="20sp"
  22. android:gravity="center"
  23. android:background="@color/picture_color_blue"
  24. android:layout_marginLeft="20dp"
  25. android:layout_marginRight="20dp"
  26. android:layout_marginBottom="30dp"
  27. />
  28. <RelativeLayout
  29. android:id="@+id/rl_loading"
  30. android:layout_width="match_parent"
  31. android:layout_height="wrap_content"
  32. android:layout_above="@+id/tv_upload"
  33. android:layout_marginBottom="20dp">
  34. <LinearLayout
  35. android:id="@+id/ll_upload_amount"
  36. android:layout_width="wrap_content"
  37. android:layout_height="wrap_content"
  38. android:orientation="horizontal"
  39. android:layout_centerHorizontal="true"
  40. android:layout_marginTop="20dp"
  41. >
  42. <TextView
  43. android:layout_width="wrap_content"
  44. android:layout_height="wrap_content"
  45. android:text="上传中"
  46. android:textSize="16sp"
  47. android:textColor="#040404"
  48. />
  49. <TextView
  50. android:id="@+id/tv_upload_count"
  51. android:layout_width="wrap_content"
  52. android:layout_height="wrap_content"
  53. android:text="0"
  54. android:textSize="16sp"
  55. android:textColor="#1B73E8"
  56. android:layout_marginLeft="30dp"
  57. />
  58. <TextView
  59. android:id="@+id/tv_upload_total"
  60. android:layout_width="wrap_content"
  61. android:layout_height="wrap_content"
  62. android:text="/0"
  63. android:textSize="16sp"
  64. android:textColor="#000000"
  65. />
  66. </LinearLayout>
  67. <ProgressBar
  68. android:id="@+id/upload_progress_bar"
  69. style="?android:attr/progressBarStyleHorizontal"
  70. android:layout_width="match_parent"
  71. android:layout_height="6dp"
  72. android:layout_below="@+id/ll_upload_amount"
  73. android:layout_centerHorizontal="true"
  74. android:layout_marginTop="16dp"
  75. android:layout_marginLeft="40dp"
  76. android:layout_marginRight="40dp"
  77. android:layout_marginBottom="6dp"
  78. android:progressDrawable="@drawable/progress_bar_blue_r3" />
  79. </RelativeLayout>
  80. </RelativeLayout>
在drawable中添加progress_bar_blue_r3.xml:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  3. <item android:id="@android:id/background">
  4. <shape>
  5. <!--<corners android:topRightRadius="20dp"
  6. android:bottomRightRadius="20dp" />-->
  7. <corners android:radius="3dp"/>
  8. <solid android:color="#FFFFFF"/>
  9. </shape>
  10. </item>
  11. <item android:id="@android:id/secondaryProgress">
  12. <scale android:scaleWidth="100%">
  13. <shape>
  14. <corners android:radius="3dp"/>
  15. <solid android:color="#FF392B"/>
  16. </shape>
  17. </scale>
  18. </item>
  19. <item android:id="@android:id/progress">
  20. <scale android:scaleWidth="100%"
  21. android:drawable="@drawable/progress_bar_ct" />
  22. </item>
  23. </layer-list>
progress_bar_ct.xml:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:shape="rectangle">
  5. <!-- solid指定形状的填充色,只有android:color一个属性 -->
  6. <solid android:color="#1B73E8" />
  7. <!-- padding设置内容区域离边界的间距 -->
  8. <!-- corners设置圆角,只适用于rectangle -->
  9. <!--4个角都是圆角-->
  10. <corners android:radius="3dp" />
  11. <!--只需要右端圆角-->
  12. <!--<corners android:bottomRightRadius="20dp"
  13. android:topRightRadius="20dp"/>-->
  14. </shape>

裁剪图片:

CutImageMoreSizeActivity 自定义多尺寸裁剪图片
  1. package com.example.testcsdnproject.picdemo;
  2. import android.content.Intent;
  3. import android.graphics.Bitmap;
  4. import android.graphics.BitmapFactory;
  5. import android.graphics.Canvas;
  6. import android.graphics.Rect;
  7. import android.net.Uri;
  8. import android.os.Bundle;
  9. import android.util.Log;
  10. import android.view.View;
  11. import android.widget.TextView;
  12. import androidx.annotation.Nullable;
  13. import androidx.appcompat.app.AppCompatActivity;
  14. import androidx.recyclerview.widget.LinearLayoutManager;
  15. import androidx.recyclerview.widget.RecyclerView;
  16. import com.chad.library.adapter.base.BaseQuickAdapter;
  17. import com.chad.library.adapter.base.listener.OnItemClickListener;
  18. import com.example.testcsdnproject.R;
  19. import com.theartofdev.edmodo.cropper.CropImageView;
  20. import java.io.ByteArrayInputStream;
  21. import java.io.ByteArrayOutputStream;
  22. import java.io.File;
  23. import java.io.FileOutputStream;
  24. import java.util.ArrayList;
  25. import java.util.List;
  26. import top.zibin.luban.CompressionPredicate;
  27. import top.zibin.luban.Luban;
  28. import top.zibin.luban.OnCompressListener;
  29. /**
  30. * 多尺寸裁剪图片
  31. */
  32. public class CutImageMoreSizeActivity extends AppCompatActivity {
  33. CropImageView civ_more_size;
  34. RecyclerView rv_size;
  35. TextView tv_back,tv_finish;
  36. private CutImageSizeAdapter cutImageSizeAdapter;
  37. private List<String> sizeData = new ArrayList<>();
  38. @Override
  39. protected void onCreate(@Nullable Bundle savedInstanceState) {
  40. super.onCreate(savedInstanceState);
  41. setContentView(R.layout.activity_cut_image_more_size);
  42. civ_more_size = findViewById(R.id.civ_more_size);
  43. rv_size = findViewById(R.id.rv_size);
  44. tv_back = findViewById(R.id.tv_back);
  45. tv_finish = findViewById(R.id.tv_check_finish);
  46. initView();
  47. tv_back.setOnClickListener(new View.OnClickListener() {
  48. @Override
  49. public void onClick(View view) {
  50. finish();
  51. }
  52. });
  53. tv_finish.setOnClickListener(new View.OnClickListener() {
  54. @Override
  55. public void onClick(View view) {
  56. if (civ_more_size.getCroppedImage() == null) {
  57. return;
  58. }
  59. String path = getPath() + "/"+currentTimeMillis() + ".jpg";
  60. BitmapFactory.Options options = new BitmapFactory.Options();
  61. /*Matrix matrix = new Matrix();
  62. matrix.setScale(0.25f, 0.25f);*/
  63. Bitmap bm = Bitmap.createBitmap(civ_more_size.getCroppedImage(), 0, 0, civ_more_size.getCroppedImage().getWidth(),
  64. civ_more_size.getCroppedImage().getHeight(), null/*matrix*/, true);
  65. // FileInfoUtils.saveBitmapFile(bm, path);
  66. Log.d("colinimagewh: ", "保存文件大小"+bm.getByteCount() +" byte");
  67. saveBitmap(bm, path);
  68. Luban.with(CutImageMoreSizeActivity.this)
  69. .load(path)
  70. .ignoreBy(100) //不压缩的阈值 单位为k 80
  71. .setTargetDir(getPath())
  72. .filter(new CompressionPredicate() {
  73. @Override
  74. public boolean apply(String path) {
  75. return true;
  76. }
  77. })
  78. .setCompressListener(new OnCompressListener() {
  79. @Override
  80. public void onStart() {
  81. // TODO 压缩开始前调用,可以在方法内启动 loading UI
  82. }
  83. @Override
  84. public void onSuccess(File file) {
  85. // TODO 压缩成功后调用,返回压缩后的图片文件
  86. Log.d("Cutpath: ", "file = "+file.getPath());
  87. Log.d("Cutpath: ", "file.size = "+file.length());
  88. options.inJustDecodeBounds = true;
  89. Log.e("colinimagewh: ", options.outHeight + "----" + options.outWidth);
  90. Intent intent = new Intent();
  91. intent.putExtra("cutimagepath", file.getPath());
  92. setResult(RESULT_OK, intent);
  93. finish();
  94. }
  95. @Override
  96. public void onError(Throwable e) {
  97. // TODO 当压缩过程出现问题时调用
  98. }
  99. }).launch();
  100. }
  101. });
  102. rv_size.addOnItemTouchListener(new OnItemClickListener() {
  103. @Override
  104. public void onSimpleItemClick(BaseQuickAdapter adapter, View view, int position) {
  105. switch (cutImageSizeAdapter.getItem(position)){
  106. case "3":
  107. civ_more_size.setAspectRatio(3,4);
  108. break;
  109. case "1":
  110. civ_more_size.setAspectRatio(1,1);
  111. break;
  112. case "9":
  113. civ_more_size.setAspectRatio(9,16);
  114. break;
  115. case "4":
  116. civ_more_size.setAspectRatio(4,3);
  117. break;
  118. case "16":
  119. civ_more_size.setAspectRatio(16,9);
  120. break;
  121. }
  122. }
  123. });
  124. }
  125. private void initView() {
  126. imageCompress(getIntent().getStringExtra("imageurl"));
  127. civ_more_size.setAspectRatio(3,4);
  128. sizeData.clear();
  129. sizeData.add("3");
  130. sizeData.add("1");
  131. // sizeData.add("9");
  132. sizeData.add("4");
  133. // sizeData.add("16");
  134. cutImageSizeAdapter = new CutImageSizeAdapter(sizeData);
  135. rv_size.setAdapter( cutImageSizeAdapter);
  136. rv_size.setLayoutManager(new LinearLayoutManager(CutImageMoreSizeActivity.this,RecyclerView.HORIZONTAL,false));
  137. }
  138. /**
  139. * 保存图片到指定路径
  140. * @param bitmap
  141. * @param path
  142. */
  143. public static void saveBitmap(Bitmap bitmap,String path){
  144. // File file = new File(Environment.getExternalStorageDirectory(), "ArtvrTwo"+System.currentTimeMillis() + ".jpg");
  145. File file = new File(path);
  146. Log.d("rockerTestCapture","截图保存路径 :" + file.getPath());
  147. try {
  148. FileOutputStream fos = new FileOutputStream(file);
  149. bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
  150. fos.flush();
  151. fos.close();
  152. // ShareZipToWX.shareWechatFriend(this,file); //不用分享
  153. } catch (java.io.IOException e) {
  154. e.printStackTrace();
  155. }
  156. }
  157. public String currentTimeMillis() {
  158. long time = System.currentTimeMillis();//获取系统时间的10位的时间戳
  159. String str = String.valueOf(time);
  160. return str;
  161. }
  162. private void imageCompress(String url) {
  163. // File beforeFile = new File(url);
  164. // Log.d("colinimagewh: ", "压缩前文件大小"+beforeFile.length() +" byte");
  165. Luban.with(this)
  166. .load(url)
  167. .ignoreBy(100) //不压缩的阈值 单位为k 80
  168. .setTargetDir(getPath())
  169. .filter(new CompressionPredicate() {
  170. @Override
  171. public boolean apply(String path) {
  172. return true;
  173. }
  174. })
  175. .setCompressListener(new OnCompressListener() {
  176. @Override
  177. public void onStart() {
  178. // TODO 压缩开始前调用,可以在方法内启动 loading UI
  179. }
  180. @Override
  181. public void onSuccess(File file) {
  182. // TODO 压缩成功后调用,返回压缩后的图片文件
  183. // Log.d("colinimagewh: ", "压缩后文件大小"+file.length() +" byte");
  184. // localImageUrl = file.getPath();
  185. // glideImage( localImageUrl);
  186. civ_more_size.setImageUriAsync(Uri.fromFile(file));
  187. }
  188. @Override
  189. public void onError(Throwable e) {
  190. // TODO 当压缩过程出现问题时调用
  191. }
  192. }).launch();
  193. }
  194. private String getPath(){
  195. File file = new File(getFilesDir(),"/Crop");
  196. if (!file.exists()) {
  197. file.mkdirs();
  198. }
  199. return file.getPath();
  200. }
  201. /**
  202. * 质量压缩方法
  203. * @param image
  204. * @return
  205. */
  206. public static Bitmap compressImage(Bitmap image) {
  207. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  208. image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
  209. int options = 90;
  210. while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
  211. baos.reset(); // 重置baos即清空baos
  212. image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
  213. options -= 10;// 每次都减少10
  214. }
  215. ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
  216. Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
  217. return bitmap;
  218. }
  219. /**
  220. * 压缩图片到目标大小以下
  221. *
  222. * @param file
  223. * @param targetSize
  224. */
  225. public void compressBmpFileToTargetSize(File file, long targetSize) {
  226. // Log.d(TAG, String.format("compressBmpFileToTargetSize start file.length():%d", file.length()));
  227. if (file.length() > targetSize) {
  228. // 每次宽高各缩小一半
  229. int ratio = 2;
  230. // 获取图片原始宽高
  231. BitmapFactory.Options options = new BitmapFactory.Options();
  232. Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
  233. int targetWidth = options.outWidth / ratio;
  234. int targetHeight = options.outHeight / ratio;
  235. // 压缩图片到对应尺寸
  236. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  237. int quality = 100;
  238. Bitmap result = generateScaledBmp(bitmap, targetWidth, targetHeight, baos, quality);
  239. // 计数保护,防止次数太多太耗时。
  240. int count = 0;
  241. while (baos.size() > targetSize && count <= 10) {
  242. targetWidth /= ratio;
  243. targetHeight /= ratio;
  244. count++;
  245. // 重置,不然会累加
  246. baos.reset();
  247. result = generateScaledBmp(result, targetWidth, targetHeight, baos, quality);
  248. }
  249. try {
  250. FileOutputStream fos = new FileOutputStream(file);
  251. fos.write(baos.toByteArray());
  252. fos.flush();
  253. fos.close();
  254. } catch (Exception e) {
  255. e.printStackTrace();
  256. }
  257. }
  258. // Log.d(TAG, String.format("compressBmpFileToTargetSize end file.length():%d", file.length()));
  259. }
  260. /**
  261. * 图片缩小一半
  262. *
  263. * @param srcBmp
  264. * @param targetWidth
  265. * @param targetHeight
  266. * @param baos
  267. * @param quality
  268. * @return
  269. */
  270. private Bitmap generateScaledBmp(Bitmap srcBmp, int targetWidth, int targetHeight, ByteArrayOutputStream baos, int quality) {
  271. Bitmap result = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
  272. Canvas canvas = new Canvas(result);
  273. Rect rect = new Rect(0, 0, result.getWidth(), result.getHeight());
  274. canvas.drawBitmap(srcBmp, null, rect, null);
  275. if (!srcBmp.isRecycled()) {
  276. srcBmp.recycle();
  277. }
  278. result.compress(Bitmap.CompressFormat.JPEG, quality, baos);
  279. return result;
  280. }
  281. }

xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:background="#1a1a1a"
  8. >
  9. <RelativeLayout
  10. android:id="@+id/rl_top"
  11. android:layout_width="match_parent"
  12. android:layout_height="50dp"
  13. android:layout_marginTop="40dp">
  14. <TextView
  15. android:id="@+id/tv_back"
  16. android:layout_width="50dp"
  17. android:layout_height="50dp"
  18. android:layout_marginLeft="16dp"
  19. android:gravity="center"
  20. android:text="返回"
  21. android:textColor="@color/white"
  22. android:textSize="16sp" />
  23. <TextView
  24. android:layout_width="wrap_content"
  25. android:layout_height="wrap_content"
  26. android:layout_centerInParent="true"
  27. android:text="编辑图片"
  28. android:textColor="#FFFFFFFF"
  29. android:textSize="20sp" />
  30. <TextView
  31. android:id="@+id/tv_check_finish"
  32. android:layout_width="50dp"
  33. android:layout_height="50dp"
  34. android:layout_alignParentRight="true"
  35. android:layout_marginRight="16dp"
  36. android:textColor="@color/white"
  37. android:textSize="16sp"
  38. android:gravity="center"
  39. android:text="完成"/>
  40. </RelativeLayout>
  41. <com.theartofdev.edmodo.cropper.CropImageView
  42. android:id="@+id/civ_more_size"
  43. android:layout_width="match_parent"
  44. android:layout_height="match_parent"
  45. android:layout_above="@+id/tv_tips"
  46. android:layout_below="@+id/rl_top"
  47. android:layout_centerHorizontal="true"
  48. android:layout_marginBottom="20dp"
  49. android:visibility="visible"
  50. app:cropBorderCornerColor="@color/white"
  51. app:cropBorderCornerOffset="0dp"
  52. app:cropBorderCornerThickness="5dp"
  53. app:cropBorderLineColor="@color/white"
  54. app:cropBorderLineThickness="1dp"
  55. app:cropGuidelines="on"
  56. app:cropGuidelinesColor="@color/white"
  57. app:cropInitialCropWindowPaddingRatio="0"
  58. app:cropSnapRadius="0dp" />
  59. <TextView
  60. android:id="@+id/tv_tips"
  61. android:layout_width="wrap_content"
  62. android:layout_height="wrap_content"
  63. android:text="选择上传尺寸并裁剪"
  64. android:textSize="12sp"
  65. android:textColor="#FF848484"
  66. android:layout_centerHorizontal="true"
  67. android:layout_above="@+id/rv_size"
  68. android:layout_marginBottom="15dp"
  69. />
  70. <androidx.recyclerview.widget.RecyclerView
  71. android:id="@+id/rv_size"
  72. android:layout_width="match_parent"
  73. android:layout_height="72dp"
  74. android:layout_alignParentBottom="true"
  75. android:layout_marginLeft="16dp"
  76. android:layout_marginBottom="32dp"
  77. />
  78. </RelativeLayout>
CutImageSizeAdapter:
  1. package com.example.testcsdnproject.picdemo;
  2. import android.widget.ImageView;
  3. import android.widget.TextView;
  4. import androidx.annotation.Nullable;
  5. import com.chad.library.adapter.base.BaseQuickAdapter;
  6. import com.chad.library.adapter.base.BaseViewHolder;
  7. import com.example.testcsdnproject.R;
  8. import java.util.List;
  9. public class CutImageSizeAdapter extends BaseQuickAdapter<String, BaseViewHolder> {
  10. // private ImageView iv_rectangle;
  11. private TextView tv_size;
  12. public CutImageSizeAdapter(@Nullable List<String> data) {
  13. super(R.layout.item_cut_image_size,data);
  14. }
  15. @Override
  16. protected void convert(BaseViewHolder helper, String item) {
  17. // iv_rectangle = helper.getView(R.id.iv_rectangle);
  18. tv_size = helper.getView(R.id.tv_size);
  19. if (item.equals("3")){
  20. // iv_rectangle.setImageResource(R.mipmap.ic_rectangle_3_4);
  21. tv_size.setText("3:4");
  22. }else if (item.equals("1")){
  23. // iv_rectangle.setImageResource(R.mipmap.ic_rectangle_1_1);
  24. tv_size.setText("1:1");
  25. }else if (item.equals("9")){
  26. // iv_rectangle.setImageResource(R.mipmap.ic_rectangle_9_16);
  27. tv_size.setText("9:16");
  28. }else if (item.equals("4")){
  29. // iv_rectangle.setImageResource(R.mipmap.ic_rectangle_4_3);
  30. tv_size.setText("4:3");
  31. }else if (item.equals("16")){
  32. // iv_rectangle.setImageResource(R.mipmap.ic_rectangle_16_9);
  33. tv_size.setText("16:9");
  34. }else{
  35. // iv_rectangle.setImageResource(R.mipmap.ic_rectangle_3_4);
  36. tv_size.setText("3:4");
  37. }
  38. }
  39. }

xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="71dp"
  4. android:layout_height="@dimen/dp_40"
  5. android:background="#252525"
  6. android:layout_marginRight="7dp"
  7. xmlns:app="http://schemas.android.com/apk/res-auto">
  8. <LinearLayout
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:orientation="horizontal"
  12. android:layout_centerInParent="true">
  13. <!-- 尺寸选中框 需要自己加
  14. <ImageView
  15. android:id="@+id/iv_rectangle"
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:src="@mipmap/ic_rectangle_3_4"
  19. android:layout_marginRight="@dimen/dp_8"
  20. android:layout_gravity="center_vertical"
  21. />-->
  22. <TextView
  23. android:id="@+id/tv_size"
  24. android:layout_width="wrap_content"
  25. android:layout_height="wrap_content"
  26. android:text="3:4"
  27. android:textSize="14sp"
  28. android:textColor="#FFE5E5E5"
  29. android:layout_gravity="center_vertical"
  30. />
  31. </LinearLayout>
  32. </RelativeLayout>

使用:

  1. //带图片地址传过去
  2. Intent intentCut = new Intent(this, CutImageMoreSizeActivity.class);
  3. intentCut.putExtra("imageurl", afterAiPath);
  4. startActivityForResult(intentCut, 530);
  5. @Override
  6. protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
  7. super.onActivityResult(requestCode, resultCode, data);
  8. if (resultCode == RESULT_OK) {
  9. switch (requestCode) {
  10. case 530: //拿到裁剪好的图片操作
  11. if (data == null){
  12. return;
  13. }
  14. afterAiPathCut = data.getStringExtra("cutimagepath");
  15. bitmapAfter = BitmapFactory.decodeFile(afterAiPathCut);
  16. int cutWidth = bitmapAfter.getWidth();
  17. int cutHeight = bitmapAfter.getHeight();
  18. if (cutWidth == cutHeight){
  19. cutWidth = 512;
  20. cutHeight = 512;
  21. }else if (cutWidth > cutHeight){
  22. cutWidth = 800;
  23. cutHeight = 600;
  24. }else{
  25. cutWidth = 600;
  26. cutHeight = 800;
  27. }
  28. ViewGroup.LayoutParams layoutParams = iv_cut_ai_pic.getLayoutParams();
  29. layoutParams.width = (int) (Common.getScreenWidth(this) *0.85);
  30. layoutParams.height = (int) (layoutParams.width * cutHeight/cutWidth );
  31. iv_cut_ai_pic.setLayoutParams(layoutParams);
  32. /* BitmapDrawable bdAfter=new BitmapDrawable(bitmapAfter);
  33. bv_before_after.setDrawableRight(bdAfter);*/
  34. iv_cut_ai_pic.setImageBitmap(bitmapAfter);
  35. iv_cut_ai_pic.setVisibility(View.VISIBLE);
  36. bv_before_after.setVisibility(View.GONE);
  37. break;
  38. }
  39. }
  40. }

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号