刚做了个人中心的上传头像功能,就来总结一下做的过程。一开始就直接去github上找一个第三方框架接入,省点事,先是听了朋友的推荐去看了一下bilibili开源的一款Boxing的框架,但是使用起来发现不太符合我的需求。最后还是使用TakePhoto这个,使用起来十分好用。

一、Boxing

bilibili的开源框架?

赶忙下来用一用,首先看一下它的simple使用流程。

(不得不吐槽一下,这个项目github下的介绍文档写的有点不知所云,让一个没接触过这框架的人去读根本获取不到什么信息,还是老老实实下的demo自己去研究,而且demo里面不只是简简单单的demo,还加了Behavior之类与功能无关的代码,十分影响阅读)

1、配置

build.grade中加入:

compile 'com.bilibili:boxing:1.0.1'

compile 'com.bilibili:boxing-impl:1.0.1'

AndroidManifest.xml文件里还需要加入这段:

android:name="android.support.v4.content.FileProvider"

android:authorities="${applicationId}.file.provider"

android:exported="false"

android:grantUriPermissions="true">

android:name="android.support.FILE_PROVIDER_PATHS"

android:resource="@xml/boxing_file_provider"/>

2、初始化

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:

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的简单使用流程了,说实话,给我的感觉是一点都不简介,使用起来挺麻烦的。这里再介绍一下另外一款我中意的框架。

二、TakePhoto

(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已经绰绰有余了。

eed69f759539

我的肥仔

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐