刚做了个人中心的上传头像功能,就来总结一下做的过程。一开始就直接去github上找一个第三方框架接入,省点事,先是听了朋友的推荐去看了一下bilibili开源的一款Boxing的框架,但是使用起来发现不太符合我的需求。最后还是使用TakePhoto这个,使用起来十分好用。
https://github.com/Bilibili/boxing
bilibili的开源框架?
赶忙下来用一用,首先看一下它的simple使用流程。
(不得不吐槽一下,这个项目github下的介绍文档写的有点不知所云,让一个没接触过这框架的人去读根本获取不到什么信息,还是老老实实下的demo自己去研究,而且demo里面不只是简简单单的demo,还加了Behavior之类与功能无关的代码,十分影响阅读)
build.grade中加入:
compile 'com.bilibili:boxing:1.0.1'
compile 'com.bilibili:boxing-impl:1.0.1'
AndroidManifest.xml文件里还需要加入这段:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.file.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/boxing_file_provider"/>
provider>
IBoxingMediaLoader loader = new BoxingGlideLoader();
BoxingMediaLoader.getInstance().init(loader);
BoxingCrop.getInstance().init(new BoxingUcrop());//如果你需要裁剪功能的话。
贴上这段代码发现这是需要自己实现的类。。。需要注意的是!!!Boxing只是支持裁剪,也就是说它留了裁剪的接口,但是需要你自己去裁剪,官方demo中使用的是ucrop:
compile('com.yalantis:ucrop:2.2.0')
BoxingGlideLoader:
public class BoxingGlideLoader implements IBoxingMediaLoader {
@Override
public void displayThumbnail(@NonNull ImageView img, @NonNull String absPath, int width, int height) {
String path = "file://" + absPath;
try {
// https://github.com/bumptech/glide/issues/1531
Glide.with(img.getContext()).load(path).placeholder(R.drawable.ic_boxing_default_image).crossFade().centerCrop().override(width, height).into(img);
} catch(IllegalArgumentException ignore) {
}
}
@Override
public void displayRaw(@NonNull final ImageView img, @NonNull String absPath, int width, int height, final IBoxingCallback callback) {
String path = "file://" + absPath;
BitmapTypeRequest request = Glide.with(img.getContext())
.load(path)
.asBitmap();
if (width > 0 && height > 0) {
request.override(width, height);
}
request.listener(new RequestListener() {
@Override
public boolean onException(Exception e, String model, Target target, boolean isFirstResource) {
if (callback != null) {
callback.onFail(e);
return true;
}
return false;
}
@Override
public boolean onResourceReady(Bitmap resource, String model, Target target, boolean isFromMemoryCache, boolean isFirstResource) {
if (resource != null && callback != null) {
img.setImageBitmap(resource);
callback.onSuccess();
return true;
}
return false;
}
}).into(img);
}
}
裁剪类:BoxingUcrop:
public class BoxingUcrop implements IBoxingCrop {
@Override
public void onStartCrop(Context context, Fragment fragment, @NonNull BoxingCropOption cropConfig,
@NonNull String path, int requestCode) {
Uri uri = new Uri.Builder()
.scheme("file")
.appendPath(path)
.build();
UCrop.Options crop = new UCrop.Options();
// do not copy exif information to crop pictures
// because png do not have exif and png is not Distinguishable
crop.setCompressionFormat(Bitmap.CompressFormat.PNG);
crop.withMaxResultSize(cropConfig.getMaxWidth(), cropConfig.getMaxHeight());
crop.withAspectRatio(cropConfig.getAspectRatioX(), cropConfig.getAspectRatioY());
UCrop.of(uri, cropConfig.getDestination())
.withOptions(crop)
.start(context, fragment, requestCode);
}
@Override
public Uri onCropFinish(int resultCode, Intent data) {
if (data == null) {
return null;
}
Throwable throwable = UCrop.getError(data);
if (throwable != null) {
return null;
}
return UCrop.getOutput(data);
}
}
另外注册裁剪的activity:
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Boxing.AppTheme.NoActionBar"/>
我是在fragment中接入这个功能的,所以比activity里还要复杂一点点。
BoxingConfig config = new BoxingConfig(Mode); // Mode:Mode.SINGLE_IMG, Mode.MULTI_IMG, Mode.VIDEO
config.needCamera(cameraRes).needGif().withMaxCount(9) // camera, gif support, set selected images count
.withMediaPlaceHolderRes(resInt) // set the image placeholder, default 0
.withAlbumPlaceHolderRes(resInt) // set the album placeholder, default 0
.withVideoDurationRes(resInt) // set the video duration resource in video mode, default 0
需要配置的数据。
然后就是启动读取相册了:
// start thumbnails Activity, need boxing-impl.
Boxing.of(config).withIntent(context, BoxingActivity.class).start(callerActivity, REQUEST_CODE);
// start view raw image Activity, need boxing-impl.
Boxing.of(config).withIntent(context, BoxingViewActivity.class).start(callerActivity, REQUEST_CODE);
上面的注释就是这两个方式的不同用法 ,我使用的是第一个方法。
然后就是在Activity里面加入
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
List medias = Boxing.getResult(data);
// 注意medias是null的情况,防止崩溃
}
好了 这就是Boxing的简单使用流程了,说实话,给我的感觉是一点都不简介,使用起来挺麻烦的。这里再介绍一下另外一款我中意的框架。
(https://github.com/crazycodeboy/TakePhoto)
这个框架使用的人很多,网上资料也很全,github上Demo写的也很好,使用起来很流畅。我这里就简单介绍一下用法:
compile 'com.jph.takephoto:takephoto_library:4.0.3'
Fragment去继承TakePhotoFragment
然后继承三个监听方法。
/**
* takePhoto的回调接口
*
* @param result
*/
@Override
public void takeSuccess(TResult result) {
super.takeSuccess(result);
TImage image = result.getImage();
}
注意:TResult的getCompressPath只有你使用压缩之后才能获取到,不然为null。
初始化配置,
// 初始化TakePhoto选取头像的配置
TakePhoto takePhoto = getTakePhoto();
CropOptions.Builder builder = new CropOptions.Builder();
builder.setAspectX(800).setAspectY(800);
builder.setWithOwnCrop(true);
File file = new File(Environment.getExternalStorageDirectory(),
"/temp/" + System.currentTimeMillis() + ".jpg");
if (!file.getParentFile().exists()) {
boolean mkdirs = file.getParentFile().mkdirs();
if (!mkdirs) {
ToastUtil.showShort("文件目录创建失败");
}
}
Uri imageUri = Uri.fromFile(file);
CompressConfig config = new CompressConfig.Builder()
.setMaxSize(102400)
.setMaxPixel(400)
.enableReserveRaw(true)
.create();
takePhoto.onEnableCompress(config, true);
启动相册
takePhoto.onPickFromDocumentsWithCrop(imageUri, builder.create());
启动相机
takePhoto.onPickFromCaptureWithCrop(imageUri, builder.create());
两个框架最后我还是使用了TakePhoto,因为它的功能配置都封装的很好,我觉得使用便利程度上是优于Boxing的,但是boxing还支持视频这些多媒体文件,也算是功能上强大于TakePhoto吧。有需要的话可以使用Boxing,但一般的上传头像功能这些使用takephoto已经绰绰有余了。