CCDownloader-android implements Data Task Download.

This commit is contained in:
Vincent Yang 2015-09-10 18:03:15 +08:00
parent 7e2fe05050
commit bd80eb6f46
4 changed files with 105 additions and 34 deletions

View File

@ -152,7 +152,7 @@ namespace cocos2d { namespace network {
onTaskProgress(*coTask->task, dl, dlNow, dlTotal, transferDataToBuffer); onTaskProgress(*coTask->task, dl, dlNow, dlTotal, transferDataToBuffer);
} }
void DownloaderAndroid::_onFinish(int taskId, int errCode, const char *errStr) void DownloaderAndroid::_onFinish(int taskId, int errCode, const char *errStr, vector<unsigned char>& data)
{ {
DLLOG("DownloaderAndroid::_onFinish(taskId: %d, errCode: %d, errStr: %s)", taskId, errCode, (errStr)?errStr:"null"); DLLOG("DownloaderAndroid::_onFinish(taskId: %d, errCode: %d, errStr: %s)", taskId, errCode, (errStr)?errStr:"null");
auto iter = _taskMap.find(taskId); auto iter = _taskMap.find(taskId);
@ -163,9 +163,8 @@ namespace cocos2d { namespace network {
} }
DownloadTaskAndroid *coTask = iter->second; DownloadTaskAndroid *coTask = iter->second;
string str = (errStr ? errStr : ""); string str = (errStr ? errStr : "");
vector<unsigned char> data;
onTaskFinish(*coTask->task, onTaskFinish(*coTask->task,
(errCode ? DownloadTask::ERROR_IMPL_INTERNAL : DownloadTask::ERROR_FILE_OP_FAILED), errStr ? DownloadTask::ERROR_IMPL_INTERNAL : DownloadTask::ERROR_NO_ERROR,
errCode, errCode,
str, str,
data data
@ -189,7 +188,7 @@ static void _nativeOnProgress(JNIEnv *env, jclass clazz, jint id, jint taskId, j
downloader->_onProcess((int)taskId, (int64_t)dl, (int64_t)dlnow, (int64_t)dltotal); downloader->_onProcess((int)taskId, (int64_t)dl, (int64_t)dlnow, (int64_t)dltotal);
} }
static void _nativeOnFinish(JNIEnv *env, jclass clazz, jint id, jint taskId, jint errCode, jstring errStr) static void _nativeOnFinish(JNIEnv *env, jclass clazz, jint id, jint taskId, jint errCode, jstring errStr, jbyteArray data)
{ {
DLLOG("_nativeOnFinish(id: %d, taskId: %d)", id, taskId); DLLOG("_nativeOnFinish(id: %d, taskId: %d)", id, taskId);
auto iter = sDownloaderMap.find(id); auto iter = sDownloaderMap.find(id);
@ -199,22 +198,33 @@ static void _nativeOnFinish(JNIEnv *env, jclass clazz, jint id, jint taskId, jin
return; return;
} }
cocos2d::network::DownloaderAndroid *downloader = iter->second; cocos2d::network::DownloaderAndroid *downloader = iter->second;
vector<unsigned char> buf;
if (errStr) if (errStr)
{ {
const char *nativeErrStr = nullptr; // failure
env->GetStringUTFChars(errStr, JNI_FALSE); const char *nativeErrStr = env->GetStringUTFChars(errStr, JNI_FALSE);
downloader->_onFinish((int)taskId, (int)errCode, nativeErrStr); downloader->_onFinish((int)taskId, (int)errCode, nativeErrStr, buf);
env->ReleaseStringUTFChars(errStr, nativeErrStr); env->ReleaseStringUTFChars(errStr, nativeErrStr);
return;
} }
else
// success
if (data)
{ {
downloader->_onFinish((int)taskId, (int)errCode, nullptr); int len = env->GetArrayLength(data);
if (len)
{
buf.reserve(len);
buf.resize(len);
env->GetByteArrayRegion(data, 0, len, reinterpret_cast<jbyte*>(buf.data()));
} }
}
downloader->_onFinish((int)taskId, (int)errCode, nullptr, buf);
} }
static JNINativeMethod sMethodTable[] = { static JNINativeMethod sMethodTable[] = {
{ "nativeOnProgress", "(IIJJJ)V", (void*)_nativeOnProgress }, { "nativeOnProgress", "(IIJJJ)V", (void*)_nativeOnProgress },
{ "nativeOnFinish", "(III" JARG_STR ")V", (void*)_nativeOnFinish }, { "nativeOnFinish", "(III" JARG_STR "[B)V", (void*)_nativeOnFinish },
}; };
static bool _registerNativeMethods(JNIEnv* env) static bool _registerNativeMethods(JNIEnv* env)

View File

@ -43,7 +43,7 @@ namespace cocos2d { namespace network
// designed called by internal // designed called by internal
void _onProcess(int taskId, int64_t dl, int64_t dlNow, int64_t dlTotal); void _onProcess(int taskId, int64_t dl, int64_t dlNow, int64_t dlTotal);
void _onFinish(int taskId, int errCode, const char *errStr); void _onFinish(int taskId, int errCode, const char *errStr, std::vector<unsigned char>& data);
protected: protected:
int _id; int _id;
_jobject* _impl; _jobject* _impl;

View File

@ -1,6 +1,8 @@
package org.cocos2dx.lib; package org.cocos2dx.lib;
import com.loopj.android.http.AsyncHttpClient; import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.BinaryHttpResponseHandler;
import com.loopj.android.http.FileAsyncHttpResponseHandler; import com.loopj.android.http.FileAsyncHttpResponseHandler;
import com.loopj.android.http.RequestHandle; import com.loopj.android.http.RequestHandle;
@ -10,6 +12,54 @@ import org.apache.http.message.BasicHeader;
import java.io.File; import java.io.File;
import java.util.*; import java.util.*;
class DataTaskHandler extends BinaryHttpResponseHandler {
int _id;
private Cocos2dxDownloader _downloader;
private long _lastBytesWritten;
void LogD(String msg) {
android.util.Log.d("Cocos2dxDownloader", msg);
}
public DataTaskHandler(Cocos2dxDownloader downloader, int id) {
super(new String[]{".*"});
_downloader = downloader;
_id = id;
_lastBytesWritten = 0;
}
@Override
public void onProgress(long bytesWritten, long totalSize) {
//LogD("onProgress(bytesWritten:" + bytesWritten + " totalSize:" + totalSize);
long dlBytes = bytesWritten - _lastBytesWritten;
long dlNow = bytesWritten;
long dlTotal = totalSize;
_downloader.onProgress(_id, dlBytes, dlNow, dlTotal);
_lastBytesWritten = bytesWritten;
}
@Override
public void onStart() {
_downloader.onStart(_id);
}
@Override
public void onFailure(int i, Header[] headers, byte[] errorResponse, Throwable throwable) {
LogD("onFailure(i:" + i + " headers:" + headers + " throwable:" + throwable);
String errStr = "";
if (null != throwable) {
errStr = throwable.toString();
}
_downloader.onFinish(_id, i, errStr, null);
}
@Override
public void onSuccess(int i, Header[] headers, byte[] binaryData) {
LogD("onSuccess(i:" + i + " headers:" + headers);
_downloader.onFinish(_id, 0, null, binaryData);
}
}
class FileTaskHandler extends FileAsyncHttpResponseHandler { class FileTaskHandler extends FileAsyncHttpResponseHandler {
int _id; int _id;
File _finalFile; File _finalFile;
@ -53,13 +103,17 @@ class FileTaskHandler extends FileAsyncHttpResponseHandler {
@Override @Override
public void onFailure(int i, Header[] headers, Throwable throwable, File file) { public void onFailure(int i, Header[] headers, Throwable throwable, File file) {
LogD("onFailure(i:" + i + " headers:" + headers.toString() + " throwable:" + throwable + " file:" + file); LogD("onFailure(i:" + i + " headers:" + headers + " throwable:" + throwable + " file:" + file);
_downloader.onFinish(_id, i, throwable.toString()); String errStr = "";
if (null != throwable) {
errStr = throwable.toString();
}
_downloader.onFinish(_id, i, errStr, null);
} }
@Override @Override
public void onSuccess(int i, Header[] headers, File file) { public void onSuccess(int i, Header[] headers, File file) {
LogD("onSuccess(i:" + i + " headers:" + headers.toString() + " file:" + file); LogD("onSuccess(i:" + i + " headers:" + headers + " file:" + file);
String errStr = null; String errStr = null;
do { do {
// rename temp file to final file // rename temp file to final file
@ -78,7 +132,7 @@ class FileTaskHandler extends FileAsyncHttpResponseHandler {
File tempFile = getTargetFile(); File tempFile = getTargetFile();
tempFile.renameTo(_finalFile); tempFile.renameTo(_finalFile);
} while (false); } while (false);
_downloader.onFinish(_id, 0, errStr); _downloader.onFinish(_id, 0, errStr, null);
} }
} }
@ -86,12 +140,11 @@ class DownloadTask {
DownloadTask() { DownloadTask() {
handle = null; handle = null;
fileHandler = null; handler = null;
resetStatus(); resetStatus();
} }
void resetStatus() { void resetStatus() {
finished = false;
bytesReceived = 0; bytesReceived = 0;
totalBytesReceived = 0; totalBytesReceived = 0;
totalBytesExpected = 0; totalBytesExpected = 0;
@ -99,9 +152,7 @@ class DownloadTask {
} }
RequestHandle handle; RequestHandle handle;
FileTaskHandler fileHandler; AsyncHttpResponseHandler handler;
boolean finished;
// progress // progress
long bytesReceived; long bytesReceived;
@ -139,14 +190,14 @@ public class Cocos2dxDownloader {
} }
} }
public void onFinish(final int id, final int errCode, final String errStr) { public void onFinish(final int id, final int errCode, final String errStr, final byte[] data) {
DownloadTask task = (DownloadTask)_taskMap.get(id); DownloadTask task = (DownloadTask)_taskMap.get(id);
if (null == task) return; if (null == task) return;
_taskMap.remove(id); _taskMap.remove(id);
Cocos2dxHelper.runOnGLThread(new Runnable() { Cocos2dxHelper.runOnGLThread(new Runnable() {
@Override @Override
public void run() { public void run() {
nativeOnFinish(_id, id, errCode, errStr); nativeOnFinish(_id, id, errCode, errStr, data);
} }
}); });
} }
@ -175,7 +226,15 @@ public class Cocos2dxDownloader {
@Override @Override
public void run() { public void run() {
DownloadTask task = new DownloadTask(); DownloadTask task = new DownloadTask();
if (0 == path.length()) {
// data task
task.handler = new DataTaskHandler(downloader, id);
task.handle = downloader._httpClient.get(Cocos2dxHelper.getActivity(), url, task.handler);
}
do { do {
if (0 == path.length()) break;
// file task
File tempFile = new File(path + downloader._tempFileNameSufix); File tempFile = new File(path + downloader._tempFileNameSufix);
if (tempFile.isDirectory()) break; if (tempFile.isDirectory()) break;
@ -185,7 +244,7 @@ public class Cocos2dxDownloader {
File finalFile = new File(path); File finalFile = new File(path);
if (tempFile.isDirectory()) break; if (tempFile.isDirectory()) break;
task.fileHandler = new FileTaskHandler(downloader, id, tempFile, finalFile); task.handler = new FileTaskHandler(downloader, id, tempFile, finalFile);
Header[] headers = null; Header[] headers = null;
long fileLen = tempFile.length(); long fileLen = tempFile.length();
if (fileLen > 0) { if (fileLen > 0) {
@ -194,8 +253,8 @@ public class Cocos2dxDownloader {
list.add(new BasicHeader("Range", "bytes=" + fileLen + "-")); list.add(new BasicHeader("Range", "bytes=" + fileLen + "-"));
headers = list.toArray(new Header[list.size()]); headers = list.toArray(new Header[list.size()]);
} }
task.handle = downloader._httpClient.get(Cocos2dxHelper.getActivity(), url, headers, null, task.fileHandler); task.handle = downloader._httpClient.get(Cocos2dxHelper.getActivity(), url, headers, null, task.handler);
//task.handle = downloader._httpClient.get(url, task.fileHandler); //task.handle = downloader._httpClient.get(url, task.handler);
} while (false); } while (false);
if (null == task.handle) { if (null == task.handle) {
@ -203,7 +262,7 @@ public class Cocos2dxDownloader {
Cocos2dxHelper.runOnGLThread(new Runnable() { Cocos2dxHelper.runOnGLThread(new Runnable() {
@Override @Override
public void run() { public void run() {
downloader.nativeOnFinish(downloader._id, id, 0, errStr); downloader.nativeOnFinish(downloader._id, id, 0, errStr, null);
} }
}); });
} else { } else {
@ -223,7 +282,7 @@ public class Cocos2dxDownloader {
while (iter.hasNext()) { while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next(); Map.Entry entry = (Map.Entry) iter.next();
//Object key = entry.getKey(); //Object key = entry.getKey();
DownloadTask task = (DownloadTask)entry.getValue(); DownloadTask task = (DownloadTask) entry.getValue();
if (null != task.handle) { if (null != task.handle) {
task.handle.cancel(true); task.handle.cancel(true);
} }
@ -233,5 +292,5 @@ public class Cocos2dxDownloader {
} }
native void nativeOnProgress(int id, int taskId, long dl, long dlnow, long dltotal); native void nativeOnProgress(int id, int taskId, long dl, long dlnow, long dltotal);
native void nativeOnFinish(int id, int taskId, int errCode, String errStr); native void nativeOnFinish(int id, int taskId, int errCode, String errStr, final byte[] data);
} }

View File

@ -138,16 +138,18 @@ void DownloaderAsyncTest::onEnter()
, bytesReceived , bytesReceived
, totalBytesReceived , totalBytesReceived
, totalBytesExpected); , totalBytesExpected);
if (transferDataToBuffer)
{
std::vector<unsigned char> buf; std::vector<unsigned char> buf;
buf.reserve(bytesReceived); buf.reserve(bytesReceived);
int64_t transfered = transferDataToBuffer(buf.data(), buf.capacity()); int64_t transfered = transferDataToBuffer(buf.data(), buf.capacity());
assert(transfered == bytesReceived); assert(transfered == bytesReceived);
}
}; };
_downloader->onDataTaskSuccess = [this](const network::DownloadTask& task, _downloader->onDataTaskSuccess = [this](const network::DownloadTask& task,
std::vector<unsigned char>& data){ std::vector<unsigned char>& data){
CCLOG("DownloaderAsyncTest onDataTaskSuccess(%ld)", data.size()); CCLOG("DownloaderAsyncTest onDataTaskSuccess(dataLen:%ld)", data.size());
}; };
auto menuItem = MenuItemFont::create("start download", [=](Ref* sender){ auto menuItem = MenuItemFont::create("start download", [=](Ref* sender){