<p>其實,我寫文章主要是對自己學習的記錄,讓自己對所學到的知識進行歸納總結(jié),我也不知道這些文章是否對你有作用,但如果你看了,覺得有哪些不足的地方望指點,一起學習,一起進步。在我的上一篇文章我的安卓開發(fā)之路收獲到了幾個喜歡一個加油鼓勵。很是讓我感激、興奮。我也更加有信心、有毅力的堅持寫好博客。雖然最近老師一直在催論文、項目又挺著急的,但今天我要分享我的一個安卓筆記,也是從項目中總結(jié)的。
<p>最近我在做一個社交類安卓手機應用有這么一個需求:動態(tài)發(fā)表視頻、文本、圖片、位置等信息,就類似陌陌、微博等發(fā)布動態(tài)效果。今天也將這個功能實現(xiàn)了?,F(xiàn)在給你分享我的設(shè)計思路與功能實現(xiàn)主要代碼。如果你也像實現(xiàn)這樣的功能需求的話,希望這篇文章能夠幫助到你,如果你覺得有不足之處,希望你能夠指點思路。
<p>首先我的思路是從手機微博客戶端(ios)開始的,一般來說,上傳一個視頻文件還是要一定的時間的,但如果在調(diào)用發(fā)布動態(tài)接口的時候,先讓用戶在這個發(fā)布動態(tài)頁面干等的話必定會影響用戶的心情的。甚至如果時間太長的話用戶可能卸載掉你的app。因此我們必須在不影響用戶操作的情況下實現(xiàn)視頻上傳并成功調(diào)用發(fā)布動態(tài)的接口。然而調(diào)用后臺服務(wù)讓其在后臺實現(xiàn)視頻上傳并成功調(diào)用發(fā)布動態(tài)接口,大概思路就是這樣。我們項目的后臺與前臺實現(xiàn)上傳交互主要用到了--七牛云儲存--實現(xiàn)上傳功能。主要過程如下:進入發(fā)布頁面打開UploadService.class---通過視頻的絕對路徑調(diào)用服務(wù)端提供的接口獲取一個key--成功獲取key值之后銷毀這個發(fā)布界面并緩存所有需要上傳的數(shù)據(jù)--通過EventBus3.0通知服務(wù)并調(diào)用斷點續(xù)傳方法---上傳操作完成之后就調(diào)用發(fā)布動態(tài)接口---最后在動態(tài)列表界面就能刷新到你剛剛發(fā)布的數(shù)據(jù)了
首先項目至少有一個寫一個BaseActivity基類吧,并且項目中的每個頁面都繼承這個基類,然后寫一個啟動服務(wù)和注冊EventBus的方法,在需要啟動服務(wù)或者注冊EventBus的界面調(diào)用這兩個方法就能夠啟動服務(wù)和注冊了。
<p>啟動服務(wù)和注冊EventBus的方法,記得停止服務(wù)和注銷Eventbus
if (isStartUploadService()) {
uploadService.setAction("com.youshusoft.nowlineclient.UPLOAD_ACTION");
uploadService.setPackage("com.youshusoft.nowlineclient.service.UploadService");//安卓L以上系統(tǒng)要
startService(uploadService);
}
if (isBindEventBusHere()) {
EventBus.getDefault().register(this);
}
/**
* 是否開啟上傳服務(wù)
*
* @return
*/
protected boolean isStartUploadService() {
return false;
}
/**
* 是否注冊EventBus
*
* @return
*/
protected boolean isBindEventBusHere() {
return false;
}
獲取上傳視頻的絕對路徑之后調(diào)用服務(wù)端接口獲取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("")) {
//已經(jīng)上傳過的話,直接調(diào)用發(fā)布動態(tài)接口
DynamicApi dynamicApi = new DynamicApi();
dynamicApi.insert(publish(), longitude, latitude, Integer.parseInt(UserInfoCache.getInstance(PublishActivity.this).getLocationDetail().getCityCode()), addStr, requestCallback);
} else {
//獲取服務(wù)端的返回的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);
//緩存需要上傳的數(shù)據(jù)到本地,避免程序預料不到的異常崩潰是數(shù)據(jù)失敗,在重新打開程序的時候會用到
UserInfoCache.getInstance(PublishActivity.this).setUploadQuene(new UploadQueueBean(dynamic, upToken, videoPath));
//通知上傳服務(wù)上傳視頻
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));
}
}
<p>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;
}
}
<p>斷點續(xù)傳(參考七牛SDK):
/**
* 斷點續(xù)傳
*
* @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) {
//可能文件目錄不存在或沒有權(quán)限
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;
}
}));
}
<p>進度動態(tài)監(jiān)聽(參考七牛SDK):
progressHandler = new UpProgressHandler() {
@Override
public void progress(String key, double percent) {
progress = percent;
if (percent == 1.0) {
//調(diào)用動態(tài)發(fā)布接口
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
/**
* 默認情況,和發(fā)送事件在同一個線程
*
* @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;
}
}
<p>上傳期間遇到異常崩潰的話,再次打開頁面的時候會提示是否繼續(xù)上傳操作
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();
}
<p>EventBus信息通用類:
/**
* Created by zhangyuting on 2016/4/6.
*/
public class MessageEvent<T> {
/**
* 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;
}
}
到此就差不多了吧。希望這篇文章能夠幫助到你,我也很希望能得到你的寶貴意見!好了我要去寫論文了,現(xiàn)在是深夜一點半!
總結(jié)了些問題
1.沒有了解透EventBus的使用??赡芤院髸佑|Rx大家族
2.與微博還是有些差距,具體的解決方案暫時沒有
3.不是干貨,但應該能用吧~~~~哈哈