其实,我写文章主要是对自己学习的记录,让自己对所学到的知识进行归纳总结,我也不知道这些文章是否对你有作用,但如果你看了,觉得有哪些不足的地方望指点,一起学习,一起进步。在我的上一篇文章我的安卓开发之路收获到了几个喜欢一个加油鼓励。很是让我感激、兴奋。我也更加有信心、有毅力的坚持写好博客。虽然最近老师一直在催论文、项目又挺着急的,但今天我要分享我的一个安卓笔记,也是从项目中总结的。
最近我在做一个社交类安卓手机应用有这么一个需求:动态发表视频、文本、图片、位置等信息,就类似陌陌、微博等发布动态效果。今天也将这个功能实现了。现在给你分享我的设计思路与功能实现主要代码。如果你也像实现这样的功能需求的话,希望这篇文章能够帮助到你,如果你觉得有不足之处,希望你能够指点思路。
首先我的思路是从手机微博客户端(ios)开始的,一般来说,上传一个视频文件还是要一定的时间的,但如果在调用发布动态接口的时候,先让用户在这个发布动态页面干等的话必定会影响用户的心情的。甚至如果时间太长的话用户可能卸载掉你的app。因此我们必须在不影响用户操作的情况下实现视频上传并成功调用发布动态的接口。然而调用后台服务让其在后台实现视频上传并成功调用发布动态接口,大概思路就是这样。我们项目的后台与前台实现上传交互主要用到了--七牛云储存--实现上传功能。主要过程如下:进入发布页面打开UploadService.class---通过视频的绝对路径调用服务端提供的接口获取一个key--成功获取key值之后销毁这个发布界面并缓存所有需要上传的数据--通过EventBus3.0通知服务并调用断点续传方法---上传操作完成之后就调用发布动态接口---最后在动态列表界面就能刷新到你刚刚发布的数据了
首先项目至少有一个写一个BaseActivity基类吧,并且项目中的每个页面都继承这个基类,然后写一个启动服务和注册EventBus的方法,在需要启动服务或者注册EventBus的界面调用这两个方法就能够启动服务和注册了。
启动服务和注册EventBus的方法,记得停止服务和注销Eventbus
if (isStartUploadService()) {
uploadService.setAction("com.youshusoft.nowlineclient.UPLOAD_ACTION");
uploadService.setPackage("com.youshusoft.nowlineclient.service.UploadService");//安卓L以上系统要
startService(uploadService);
}
if (isBindEventBusHere()) {
EventBus.getDefault().register(this);
}
/**
* 是否开启上传服务
*
* @return
*/
protected boolean isStartUploadService() {
return false;
}
/**
* 是否注册EventBus
*
* @return
*/
protected boolean isBindEventBusHere() {
return false;
}
获取上传视频的绝对路径之后调用服务端接口获取key值:
//视频上传
public void UpLoadVideo(final String path) {
File file = new File(path);
final String key = MD5Util.getFileMD5String(file);
videoKey = key;
if (file.exists() && file.isFile()) {
if (qiNiuApi == null) {
qiNiuApi = new QiNiuApi();
}
qiNiuApi.getVideoUpToken(key, new RequestCallback() {
@Override
public void resultSuccess(Object data) {
if (data.toString().trim().equals("")) {
//已经上传过的话,直接调用发布动态接口
DynamicApi dynamicApi = new DynamicApi();
dynamicApi.insert(publish(), longitude, latitude, Integer.parseInt(UserInfoCache.getInstance(PublishActivity.this).getLocationDetail().getCityCode()), addStr, requestCallback);
} else {
//获取服务端的返回的key
upToken = new UpToken();
upToken.setToken(data.toString());
upToken.setKey(key);
Dynamic dynamic = new Dynamic();
dynamic.setContent(publish());
dynamic.setLn(longitude);
dynamic.setLa(latitude);
dynamic.setCity(Integer.valueOf(UserInfoCache.getInstance(PublishActivity.this).getLocationDetail().getCityCode()));
dynamic.setPos(addStr);
//缓存需要上传的数据到本地,避免程序预料不到的异常崩溃是数据失败,在重新打开程序的时候会用到
UserInfoCache.getInstance(PublishActivity.this).setUploadQuene(new UploadQueueBean(dynamic, upToken, videoPath));
//通知上传服务上传视频
EventBus.getDefault().post(new MessageEvent(EventConfig.UPLOAD_VIDEO, new UploadQueueBean(dynamic, upToken, videoPath)));
}
showShortToast(R.string.publish_success);
finish();
}
});
} else {
LogUtils.e(getString(R.string.file_notexit));
}
}
UploadSevice.class接受到了上传操作的通知(参考EventBus):
@Subscribe(threadMode = ThreadMode.POSTING)
public void onBackgroundEventBus(MessageEvent messageEvent) {
switch (messageEvent.getEventCode()) {
case EventConfig.UPLOAD_VIDEO:
message = (UploadQueueBean) messageEvent.getData();
dynamic = message.getDynamic();
breakpointUpload(message.getFilePath(), message.getUpToken());
break;
}
}
断点续传(参考七牛SDK):
/**
* 断点续传
*
* @param filePath 文件路径
*/
private void breakpointUpload(String filePath, UpToken upToken) {
Recorder recorder = null;
try {
String sdcard = Environment.getExternalStorageDirectory().getPath();
recorder = new FileRecorder(sdcard + "/youshusoft/nowLine/");
} catch (IOException e) {
//可能文件目录不存在或没有权限
e.printStackTrace();
}
KeyGenerator keyGen = new KeyGenerator() {
@Override
public String gen(String key, File file) {
return key;
}
};
Configuration config = new Configuration.Builder()
.recorder(recorder, keyGen)
.build();
uploadManager = new UploadManager(config);
uploadManager.put(filePath, upToken.getKey(), upToken.getToken(), new UpCompletionHandler() {
@Override
public void complete(String key, ResponseInfo info, JSONObject response) {
LogUtils.e(key + ",\r\n " + info + ",\r\n " + response);
}
}, new UploadOptions(null, null, false, progressHandler,
new UpCancellationSignal() {
public boolean isCancelled() {
return false;
}
}));
}
进度动态监听(参考七牛SDK):
progressHandler = new UpProgressHandler() {
@Override
public void progress(String key, double percent) {
progress = percent;
if (percent == 1.0) {
//调用动态发布接口
new DynamicApi().insert(dynamic.getContent(), dynamic.getLn(), dynamic.getLa(), dynamic.getCity(), dynamic.getPos(), new RequestCallback() {
@Override
public void resultSuccess(Object data) {
message = null;
//清除上传队列缓存信息
UserInfoCache.getInstance(UploadService.this).setUploadQuene(message);
}
});
//通知BaseActivity 上传完成
EventBus.getDefault().post(new MessageEvent(EventConfig.UPLOAD_SUCCESS));
}
}
};
当上传到成功的时候就通知BaseActivity
/**
* 默认情况,和发送事件在同一个线程
*
* @param messageEvent
*/
@Subscribe(threadMode = ThreadMode.POSTING)
public void onPostEventBus(MessageEvent messageEvent) {
switch (messageEvent.getEventCode()) {
case EventConfig.UPLOAD_SUCCESS:
uploadService.setAction("com.youshusoft.nowlineclient.UPLOAD_ACTION");
stopService(uploadService);
break;
}
}
上传期间遇到异常崩溃的话,再次打开页面的时候会提示是否继续上传操作
if (UserInfoCache.getInstance(BaseActivity.this).getUploadQueue() != null && !isServiceWork(this, UploadService.class.getName())) {
uploadService.setAction("com.youshusoft.nowlineclient.UPLOAD_ACTION");
uploadService.setPackage("com.youshusoft.nowlineclient.service.UploadService");
startService(uploadService);
showUploadDialog();
}
EventBus信息通用类:
/**
* Created by zhangyuting on 2016/4/6.
*/
public class MessageEvent {
/**
* reserved data
*/
private T data;
/**
* this code distinguish between different events
*/
private int eventCode = -1;
public MessageEvent(int eventCode) {
this(eventCode, null);
}
public MessageEvent(int eventCode, T data) {
this.eventCode = eventCode;
this.data = data;
}
/**
* get event code
*
* @return
*/
public int getEventCode() {
return this.eventCode;
}
/**
* get event reserved data
*
* @return
*/
public T getData() {
return this.data;
}
}
到此就差不多了吧。希望这篇文章能够帮助到你,我也很希望能得到你的宝贵意见!好了我要去写论文了,现在是深夜一点半!
总结了些问题
1.没有了解透EventBus的使用。可能以后会接触Rx大家族
2.与微博还是有些差距,具体的解决方案暂时没有
3.不是干货,但应该能用吧~~~~哈哈