• 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" />

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

    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 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 urls = new ArrayList<>();
    87. private List 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
    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. "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 {
    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 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 list) {
    63. this.list = list;
    64. }
    65. public List 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. "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(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(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("", "", "");
    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() {
    63. {
    64. put("callbackUrl", "拼接服务器域名"/*AppConstant.OSS_IMAGE_URL*/);
    65. put("callbackBody", callbackbody);
    66. }
    67. });
    68. // 异步上传,可以设置进度回调
    69. put.setProgressCallback(new OSSProgressCallback() {
    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() {
    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 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() {
    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() {
    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 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() {
    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() {
    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() {
    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() {
    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() {
    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 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() {
    415. @Override
    416. public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
    417. }
    418. });
    419. OSSAsyncTask task = oss.asyncPutObject(put,
    420. new OSSCompletedCallback() {
    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() {
    444. @Override
    445. public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
    446. }
    447. });
    448. OSSAsyncTask task = oss.asyncPutObject(put,
    449. new OSSCompletedCallback() {
    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 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() {
    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() {
    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 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
    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 paintingUrls = new ArrayList<>();
    134. private List paintingUrlsCallback = new ArrayList<>();
    135. private List addArtWorksBeans = new ArrayList<>();
    136. private List backArtWorksBeans = new ArrayList<>();
    137. private List albumSelectList = new ArrayList<>();
    138. double mAverageProgress;//每一个需要上传至oss的本地作品最大的进度值
    139. int uploadedTotalCount = 0;//需要上传的所有数量
    140. int uploadedCount = 0;//已上传数量
    141. OssService ossService;
    142. private List 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
    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. *

    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. "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. "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:radius="3dp"/>
    6. <solid android:color="#FFFFFF"/>
    7. shape>
    8. item>
    9. <item android:id="@android:id/secondaryProgress">
    10. <scale android:scaleWidth="100%">
    11. <shape>
    12. <corners android:radius="3dp"/>
    13. <solid android:color="#FF392B"/>
    14. shape>
    15. scale>
    16. item>
    17. <item android:id="@android:id/progress">
    18. <scale android:scaleWidth="100%"
    19. android:drawable="@drawable/progress_bar_ct" />
    20. item>
    21. layer-list>
    progress_bar_ct.xml:
    1. "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="#1B73E8" />
    6. <corners android:radius="3dp" />
    7. 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 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. "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 {
    10. // private ImageView iv_rectangle;
    11. private TextView tv_size;
    12. public CutImageSizeAdapter(@Nullable List 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. "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. <TextView
    14. android:id="@+id/tv_size"
    15. android:layout_width="wrap_content"
    16. android:layout_height="wrap_content"
    17. android:text="3:4"
    18. android:textSize="14sp"
    19. android:textColor="#FFE5E5E5"
    20. android:layout_gravity="center_vertical"
    21. />
    22. LinearLayout>
    23. 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. }

  • 相关阅读:
    博客无限滚动加载(html、css、js)实现
    Microsoft Visual C++ 14.0 or greater is required.
    进程与线程
    3D视觉识别案例:3D无序棒料抓取,阀体圆环上下料,电机定子上料
    《你好,放大器》----学习记录(六)
    【源码解读】asp.net core源码启动流程精细解读
    现代信号处理——平稳随机信号的功率谱密度
    防御保护--入侵防御系统IPS
    docker分layer的好处
    【机器学习基础】机器学习的模型评估(评估方法及性能度量原理及主要公式)
  • 原文地址:https://blog.csdn.net/qq_38306233/article/details/136482315