需求是这样的:在某个界面,点击某个按钮之后截取当前手机界面,并使用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