Android开发之使用Retrofit上传截屏保存的图片

需求是这样的:在某个界面,点击某个按钮之后截取当前手机界面,并使用Retrofit上传到服务器。

在截屏和上传操作之间还有一个图片的保存步骤,以及上传成功之后的删除,这里就需要手机的读写权限和网络权限。

1.首先是截屏代码:

public static Bitmap takeScreenShot(Activity activity) {
        
        // View是你需要截图的View
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap b1 = view.getDrawingCache();

        // 获取状态栏高度
        Rect frame = new Rect();
        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
        int statusBarHeight = frame.top;

        // 获取屏幕长和高
        int width = activity.getWindowManager().getDefaultDisplay().getWidth();
        int height = activity.getWindowManager().getDefaultDisplay()
                .getHeight();
        // 去掉标题栏
        Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height
                - statusBarHeight);
        view.destroyDrawingCache();
        return b;
}

压缩Bitmap:

public static Bitmap compressImage(Bitmap image) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        
        //质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
        image.compress(Bitmap.CompressFormat.JPEG, 80, baos);
        int options = 100;
        
        //循环判断如果压缩后图片是否大于100kb,大于继续压缩
        while (baos.toByteArray().length / 1024 > 100) {
            
            //重置baos即清空baos
            baos.reset();
            
            //这里压缩options%,把压缩后的数据存放到baos中
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);
            
            //每次都减少10
            options -= 10;
        }
        
        //把压缩后的数据baos存放到ByteArrayInputStream中
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        
        //把ByteArrayInputStream数据生成图片
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
        return bitmap;
}

这里放到一个工具类当中,返回一个压缩后的Bitmap图片。

2.保存图片:

public class ScannerUtils {

  // 扫描的两种方式
  public static enum ScannerType {
    RECEIVER, MEDIA
  }

  // 首先保存图片
  public static String saveImageToGallery(Context context, Bitmap bitmap, ScannerType type) {
    File appDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "android");
    if (!appDir.exists()) {
      // 目录不存在 则创建
      appDir.mkdirs();
    }
    //下面的CompressFormat.PNG/CompressFormat.JPEG, 这里对应.png/.jpeg
    String fileName = System.currentTimeMillis() + ".png";
    File file = new File(appDir, fileName);
    try {
      FileOutputStream fos = new FileOutputStream(file);
      bitmap.compress(CompressFormat.PNG, 100, fos); // 保存bitmap至本地
      fos.flush();
      fos.close();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (type == ScannerType.RECEIVER) {
        ScannerByReceiver(context, file.getAbsolutePath());
      } else if (type == ScannerType.MEDIA) {
        ScannerByMedia(context, file.getAbsolutePath());
      }
      if (bitmap!=null&&!bitmap.isRecycled()) {

        //当存储大图片时,为避免出现OOM ,及时回收Bitmap
        bitmap.recycle();

        // 通知系统回收
        System.gc();
      }

      //返回保存的图片路径
      return file.getAbsolutePath();
    }
  }

  //删除图片
  public static void deleteSuccess(Context context, String filePath) {
    Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    ContentResolver mContentResolver = context.getContentResolver();
    String where = MediaStore.Images.Media.DATA + "='" + filePath + "'";
    //删除图片
    mContentResolver.delete(uri, where, null);
  }

  /** Receiver扫描更新图库图片 **/
  private static void ScannerByReceiver(Context context, String path) {
    context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + path)));
    Log.v("TAG", "receiver scanner completed");
  }

  /** MediaScanner 扫描更新图片图片 **/
  private static void ScannerByMedia(Context context, String path) {
    MediaScannerConnection.scanFile(context, new String[] {path}, null, null);
    Log.v("TAG", "media scanner completed");
  }
}

保存图片成功后返回图片所在的存储路径。

3.上传图片:

@Query、@QueryMap 一般是 @Get标记的,URL后面跟的参数请求 ?key=value&key1=value1

@Field、@FieldMap 一般是@Post 、@FormUrlEncoded标记的,表单请求

@Part、@PartMap 一般是@Post、 @Multipart标记的,带文件的表单请求

@Body标记的请求体,支持自定义Bean类,但不能标记为 @FormUrlEncoded / @Multipart

 这里请求数据用的Retrofit + RxJava,FastJSON解析数据。

Retrofit的用法这里就不说了!!!

部分代码:

private Retrofit createRetrofit(Retrofit.Builder builder, OkHttpClient client, String url) {
        return builder
                .baseUrl(url)
                .client(client)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }

 4.上传图片:

@Multipart
@POST("这里是服务器地址")
Observable<JSONObject> uploadFanganFile(@PartMap Map<String, RequestBody> map, @Part() MultipartBody.Part file);

 

// 截屏
Bitmap bitmap = compressImage(takeScreenShot(this));

//保存
String filePath = ScannerUtils.saveImageToGallery(this, bitmap, ScannerUtils.ScannerType.RECEIVER);

//上传
public void uploadFanganFile(String filePath) {
       
        Map<String, RequestBody> params =  new HashMap<String, RequestBody>();
        params.put("name", RequestBody.create(MediaType.parse("text/plain"), "name"));
        //如果有多个参数按上面方法添加即可
        //params.put("name1", RequestBody.create(MediaType.parse("text/plain"), "name1"));
        // ......
        File file = new File(filePath);
        RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
        addSubscribe(mDataManager.uploadFanganFile(params, body)
                .compose(RxUtils.rxSchedulerHelper())
                .subscribeWith(new BaseObserver<JSONObject>(mView,
                        "上传失败") {

                    @Override
                    public void onNext(JSONObject jsonObject) {
                        //上传成功, 删除图片
                        ScannerUtils.deleteSuccess(this, filePath);
                    }

                    @Override
                    public void onComplete() {
                        super.onComplete();
                       
                    }
                }));
    }

OVER

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值