package tws.component.log.upload;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.http.HttpStatus;
import tws.component.log.TwsLog;
import tws.component.log.impl.TwsLogUtils;
import android.os.AsyncTask;
public class UploadLogTask extends AsyncTask<String, Integer, String> {
private static final String TAG = "UploadLogTask";
private static final int ZIP_FILE_PROCESS = 30;
private static final int ZIP_EXTRADATA_PROCESS = 5;
private static final int UPLOAD_BUSSINFO_PROCESS = 10;
private static final int DEL_FILE_PROCESS = 10;
/** 正式环境地址 */
private final String LOG_DEFAULT_SERVICE = "http://wwgv.html5.qq.com/upload";
// private final String LOG_DEFAULT_SERVICE = "http://showlog.cs0309.html5.qq.com/upload";
/** 测试环境地址 */
private final String LOG_TEST_SERVICE = "http://showlog.cs0309.html5.qq.com/upload";
private String CONTENT_DISPOSITION_HEADER = "Content-Disposition: form-data; name=\"" ;
private String CONTENT_TYPE_HEADER = "Content-Type:application/octet-stream" ;
private String QUOT = "\"" ;
private String ITEM_SPERATOR = "|";
private String PARAM_SPERATOR = ";";
private String LINE_END = "\r\n";
private String LINE_START_HYPHENS = "--";
private String RSP_OK ="OK";
private String RSP_FAILS="";
private int TASK_STAT_RUNNING = 1;
private int TASK_STAT_CANCEL = -1;
/** 缓冲区大小 */
private int BUFF_SIZE = 2 * 1024;
/** 请求url地址 */
private String mReqUrl = null;
/** app 相关基础信息 */
private AppRomBaseInfo mBaseInfo;
/** app 上报日志的业务信息 */
private AppBussInfo mBussInfo;
/** 日志传输状态监听*/
private ILogTransferStatusListener mLogTransferStatusListener;
private String mBoundary = null;
private int mTaskStat = 0;
public UploadLogTask(AppBussInfo bussInfo, AppRomBaseInfo appRomBaseInfo) {
this(null, bussInfo, appRomBaseInfo);
}
public UploadLogTask(String reqUrl, AppBussInfo bussInfo, AppRomBaseInfo baseInfo) {
mReqUrl = reqUrl;
mBussInfo = bussInfo;
mBaseInfo = baseInfo;
}
public void setLogTransferStatusListener(ILogTransferStatusListener listener) {
mLogTransferStatusListener = listener;
}
public void executeTask(String...strings ) {
if (mBussInfo != null) {
mBussInfo.mRunState = 1;
}
this.execute(strings);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
mTaskStat = TASK_STAT_RUNNING;
try {
if ( mBussInfo != null && isNeedUiCallback() &&mBussInfo.mUiCallBack != null) {
mBussInfo.mUiCallBack.onUploadStarted(mBussInfo.mResId);
}
} catch (Throwable e) {
TwsLog.w(TAG, "onPreExecute -> e: " + e + ", err msg: " + e.getMessage());
}
}
@Override
protected String doInBackground(String... params) {
String result = "";
// 设置boundary
mBoundary = "----uploadLogTask_" +System.currentTimeMillis();
if (mLogTransferStatusListener != null) {
mLogTransferStatusListener.onLogTransferStarted(mBussInfo);
}
// ----------------- 压缩指定log文件 -----------------
String pkgName = params == null ? "" : params[0];
File zipFile = zipUploadFile(pkgName);
// 上传zip文件
publishProgress(ZIP_FILE_PROCESS);
// ----------------- 文件压缩完成,开始上传-----------------
HttpURLConnection connection = null;
// 网络传输流
DataOutputStream outputStream = null;
// 上传文件流程
FileInputStream fileInputStream = null;
// 开始上传信息
try {
// 初始化连接
connection = initConnection();
if (connection == null) {
// 删除zip文件
if (zipFile != null) {
zipFile.delete();
}
publishProgress(100);
return "initConnection-> fails";
}
outputStream = new DataOutputStream(connection.getOutputStream());
// 上传baseInfo
result = "上传 romInfo 失败";
String baseInfo = getRomInfo();
TwsLog.d(TAG, "doInBackground->baseInfo = " + baseInfo);
uploadStr(outputStream, "rominfo", baseInfo);
// 上传业务信息(错误码,错误信息等)
result = "上传 bussinfo 失败";
String bussInfo = getBussInfo();
TwsLog.d(TAG, "doInBackground->bussInfo = " + bussInfo);
uploadStr(outputStream, "bussinfo", bussInfo);
// 上传基础信息完成
publishProgress(ZIP_FILE_PROCESS + UPLOAD_BUSSINFO_PROCESS);
if (isTaskCancel()) { // 任务取消
result = "日志上传任务取消";
} else {
result = "上传 文件 失败";
if (zipFile != null && zipFile.isFile() && zipFile.exists()) {
String fileName = zipFile.getAbsolutePath();
fileInputStream = new FileInputStream(new File(fileName));
result = uploadFile(outputStream, fileInputStream, "tromreport", fileName);
}
}
// 写入传输完成结束符
outputStream.writeBytes(LINE_START_HYPHENS);
outputStream.writeBytes(mBoundary);
outputStream.writeBytes(LINE_START_HYPHENS);
outputStream.writeBytes(LINE_END);
// 数据传输完成
outputStream.flush();
outputStream.close();
outputStream = null;
// 解析返回数据
processResponse(connection);
} catch (Exception e) {
TwsLog.w(TAG, "doInBackground->上传失败, err: " + e + ", err msg: " + e.getMessage());
if (isStrEmpty(result)) {
result = RSP_FAILS;
}
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
TwsLog.w(TAG, "doInBackground->outputStream closed, err: " + e + ", err msg: " + e.getMessage());
}
}
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
TwsLog.w(TAG, "doInBackground->fileInputStream closed, err: " + e + ", err msg: " + e.getMessage());
}
}
}
// 删除zip文件
if (zipFile != null) {
zipFile.delete();
}
publishProgress(100);
return result;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
TwsLog.d(TAG, "onPostExecute->result = " + result);
try {
if ( mBussInfo != null && isNeedUiCallback() &&mBussInfo.mUiCallBack != null) {
mBussInfo.mUiCallBack.onUploadEnd(mBussInfo.mResId, result);
}
} catch (Throwable e) {
TwsLog.w(TAG, "onPostExecute -> e: " + e + ", err msg: " + e.getMessage());
}
if (mLogTransferStatusListener != null) {
mLogTransferStatusListener.onLogTransferEnd(mBussInfo);
}
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
TwsLog.d(TAG, "onProgressUpdate->result = " + values[0] + ", resId = " + mBussInfo.mResId);
try {
if (isNeedUiCallback() && mBussInfo != null && mBussInfo.mUiCallBack != null) {
TwsLog.v(TAG, "onProgressUpdate->onUploadProgressUpdated = " + values[0]);
mBussInfo.mUiCallBack.onUploadProgressUpdated(mBussInfo.mResId, values[0]);
}
} catch (Throwable e) {
TwsLog.w(TAG, "onProgressUpdate -> e: " + e + ", err msg: " + e.getMessage());
}
}
public AppBussInfo getAppBussInfo() {
return mBussInfo;
}
public void cancelTask() {
mTaskStat = TASK_STAT_CANCEL;
// cancel(mayInterruptIfRunning)
}
private boolean isNeedUiCallback() {
if (mLogTransferStatusListener != null) {
return mLogTransferStatusListener.isBussInfoValid(mBussInfo);
}
return false;
}
private boolean isTaskCancel() {
return mTaskStat == TASK_STAT_CANCEL;
}
private File zipUploadFile(String pkgName) {
String logFilePath = mBussInfo.mFilePath;
String extraFilePath = mBussInfo.mExtraPath;
byte[] extraDatas = mBussInfo.mExtraDatas;
if (isStrEmpty(logFilePath) && isStrEmpty(extraFilePath)
&& (extraDatas == null || extraDatas.length == 0)) { // 不上传日志信息
TwsLog.w(TAG, "zipUploadFile -> no file or data need upload, cancel zipfile");
return null;
}
List<String> filePaths = new ArrayList<String>();
File uploadLogFile = null;
String zipFilePath = null;
if (!isStrEmpty(logFilePath)) { // 上传log文件的信息
uploadLogFile = new File(logFilePath);
}
// ------- 开始处理压缩文件---------
if (uploadLogFile != null && uploadLogFile.exists()) {
zipFilePath = uploadLogFile.getAbsolutePath();
if (uploadLogFile.isDirectory()) { // 上传指定log目录:是一个文件夹
String[] fileList = uploadLogFile.list();
if (fileList != null && fileList.length > 0) {
int filesCnt = fileList.length;
TwsLog.d(TAG, "doInBackground-> upload files cnt = " + filesCnt);
for (int i = 0; i < filesCnt; i++) {
if (isStrEmpty(fileList[i])) {
continue;
}
filePaths.add(zipFilePath + File.separator +fileList[i]);
} // ~ 根目录文件添加完成
}
// 指定目录下无日志文件, 指定默认压缩文件名
zipFilePath = zipFilePath + File.separator + pkgName + "_UploadDefault";
} else { // 添加指定文件
filePaths.add(logFilePath);
}
} // ~ end 默认日志数据信息处理完成
if (isStrEmpty(zipFilePath)) { // 无默认日志文件信息
// 设置默认压缩文件信息
File logFileDir = TwsLogUtils.getLogFileDirectory(pkgName, false);
if (logFileDir == null) {
TwsLog.w(TAG, "zipUploadFile: logFileDir is null");
return null;
}
zipFilePath = logFileDir.getAbsolutePath()
+ File.separator + pkgName+ "_UploadDefault";
}
TwsLog.i(TAG, "zipUploadFile-> zipFilePath = " + zipFilePath);
// 压缩文件信息
File zipFile = new File(zipFilePath + ".zip");
if (!isStrEmpty(mBussInfo.mExtraPath)) { // 添加额外文件
filePaths.add(mBussInfo.mExtraPath);
}
// 压缩所有信息
if (!zipFiles(zipFile, filePaths, mBussInfo.mExtraDatas)) {
TwsLog.w(TAG, "doInBackground-> zip files fails");
}
return zipFile;
}
/**
* 获取业务信息
* -- 格式BussName=TRomSync|ErrCode=1|ErrMsg="err"
* @return
*/
private String getBussInfo() {
String bussName = null;
int errCode = 0;
String errMsg = null;
// int reportType = -1;
if (mBussInfo != null) {
bussName = mBussInfo.mBussName;
errCode = mBussInfo.mErrCode;
errMsg = mBussInfo.mErrMsg;
// reportType = mBussInfo.mReportType;
}
Map<String, String> bussInfo = new HashMap<String, String>(3);
if (isStrEmpty(bussName)) {
bussName = "default";
}
bussInfo.put("BussName", bussName);
bussInfo.put("ErrCode", String.valueOf(errCode));
bussInfo.put("ErrMsg", errMsg);
// 改用不同业务名处理
// bussInfo.put("ReportType", String.valueOf(reportType));
return getItemFormatValues(bussInfo);
}
/**
* 获取app相关基础信息
* GUID=xxx|QUA=base64(xxx)|IMEI=xxx|LC=xx|RomId=xxx|Package=xxx
* @return
*/
private String getRomInfo() throws Exception {
Map<String, String> infos = new HashMap<String, String>(6);
if (mBaseInfo == null) {
mBaseInfo = new AppRomBaseInfo();
}
String qua = URLEncoder.encode(mBaseInfo.mQua, "UTF-8");
byte[] guid = mBaseInfo.mGuid;
if (guid == null) {
guid = new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
}
infos.put("GUID", TwsLogUtils.byteToHexString(guid));
infos.put("QUA", qua);
infos.put("IMEI", mBaseInfo.mImei);
infos.put("LC", mBaseInfo.mLc);
infos.put("RomId", String.valueOf(mBaseInfo.mRomId));
infos.put("Package", mBaseInfo.mPkgName);
infos.put("Ticket", mBaseInfo.mTicket);
return getItemFormatValues(infos);
}
/**
* 获取指定格式的字符串信息
* -- key=value|key=value|...
* @param items
* @return
*/
private String getItemFormatValues(Map<String, String> items) {
if (items == null || items.isEmpty()) {
return "";
}
String key = null;
String value = null;
StringBuffer buffer = new StringBuffer();
for (Entry<String, String> entry : items.entrySet()) {
key = entry.getKey();
value = entry.getValue();
if (isStrEmpty(key)) {
continue;
}
if (value == null) {
value = "na";
}
value = value.replace("&", "_");
value = value.replace("|", "#");
buffer.append(key);
buffer.append("=");
buffer.append(value);
buffer.append(ITEM_SPERATOR);
}
// 去掉最后一个分割符
return buffer.substring(0, buffer.length() - 1);
}
private HttpURLConnection initConnection() {
HttpURLConnection connection = null;
URL url = null;
try {
// String boundary = "----uploadLogTask_" +System.currentTimeMillis();
if (isStrEmpty(mReqUrl) && mBaseInfo.isTestFlg()) { // 测试环境
mReqUrl = LOG_TEST_SERVICE;
}
if (isStrEmpty(mReqUrl)) { // 默认正式环境
mReqUrl = LOG_DEFAULT_SERVICE;
}
TwsLog.i(TAG, "initConnection-> reqUrl = " + mReqUrl +", envFlg = " + mBaseInfo.mEnvFlg + ", boundary = " + mBoundary);
url = new URL(mReqUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
//connection.setChunkedStreamingMode(0);
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + mBoundary);
} catch (IOException e) {
TwsLog.w(TAG, "initConnection-> err: " + e + ", err msg: " + e.getMessage());
connection = null;
url = null;
}
return connection;
}
private String uploadStr(DataOutputStream outputStream, String reqFunc, String data) throws Exception{
// 写入开始分割连接符
outputStream.writeBytes(LINE_START_HYPHENS);
outputStream.writeBytes(mBoundary);
outputStream.writeBytes(LINE_END);
// 写入content disposition
outputStream.writeBytes(CONTENT_DISPOSITION_HEADER);
outputStream.writeBytes(reqFunc);
outputStream.writeBytes(QUOT);
outputStream.writeBytes(LINE_END);
outputStream.writeBytes(LINE_END);
byte[] dataBytes = data.getBytes("UTF-8");
// 写入数据
outputStream.write(dataBytes);
outputStream.writeBytes(LINE_END);
return RSP_OK;
}
// private String uploadBytes(DataOutputStream outputStream, String reqFunc, byte[] datas) throws Exception{
//
// // 写入开始分割连接符
// outputStream.writeBytes(LINE_START_HYPHENS);
// outputStream.writeBytes(mBoundary);
// outputStream.writeBytes(LINE_END);
//
// // 写入content disposition
// outputStream.writeBytes(CONTENT_DISPOSITION_HEADER);
// outputStream.writeBytes(reqFunc);
// outputStream.writeBytes(QUOT);
//
// outputStream.writeBytes(LINE_END);
// outputStream.writeBytes(LINE_END);
// // 写入数据
// outputStream.write(datas);
//
// outputStream.writeBytes(LINE_END);
// return RSP_OK;
// }
/**
* 上传 压缩好了的文件
* @param outputStream
* @param reqFunc
* @param fileName
* @return
* @throws Exception
*/
private String uploadFile(DataOutputStream outputStream, FileInputStream fileInputStream, String reqFunc, String fileName) throws Exception{
String response = "error";
String uploadFileName = fileName;
TwsLog.d(TAG, "uploadFile-> filename: "+fileName + ", reqUrl:"+mReqUrl);
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer = null;
int maxBufferSize = BUFF_SIZE;
// 写入开始分割连接符
outputStream.writeBytes(LINE_START_HYPHENS);
outputStream.writeBytes(mBoundary);
outputStream.writeBytes(LINE_END);
// 写入content disposition
outputStream.writeBytes(CONTENT_DISPOSITION_HEADER);
outputStream.writeBytes(reqFunc);
outputStream.writeBytes(QUOT);
outputStream.writeBytes(PARAM_SPERATOR);
// 写入文件名参数
outputStream.writeBytes("filename=");
outputStream.writeBytes(QUOT);
outputStream.writeBytes(uploadFileName);
outputStream.writeBytes(QUOT);
outputStream.writeBytes(LINE_END);
// 写入文件类型Content-Type:
outputStream.writeBytes(CONTENT_TYPE_HEADER);
outputStream.writeBytes(LINE_END);
outputStream.writeBytes(LINE_END);
// 开始写文件
bytesAvailable = fileInputStream.available();
// 设置缓冲区大小
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
TwsLog.d(TAG, "upload file length:" + bytesAvailable);
int fileLength = bytesAvailable;
int sendSize = bufferSize;
while (bytesRead > 0) {
if (isTaskCancel()) { // 任务取消
response = "文件上传取消";
break;
}
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
// 更新上传文件进度
int process = Math.round(((((float) sendSize / fileLength)
* (100 - ZIP_FILE_PROCESS - DEL_FILE_PROCESS - UPLOAD_BUSSINFO_PROCESS) / 100)) * 100);
publishProgress(process + ZIP_FILE_PROCESS + UPLOAD_BUSSINFO_PROCESS);
sendSize += bufferSize;
} // ~ end upload zip file
outputStream.writeBytes(LINE_END);
response = "上传成功";
return response;
}
/**
* 处理返回数据
* @param connection
* @return
*/
private String processResponse(HttpURLConnection connection) {
String response = null;
try {
TwsLog.d(TAG, "processResponse-> start receiver rsp");
int serverResponseCode = connection.getResponseCode();
String serverResponseMessage = connection.getResponseMessage();
TwsLog.d(TAG, "processResponse-> Server Response Code:" + serverResponseCode
+ ", Server Response Message:" + serverResponseMessage);
InputStream is = connection.getInputStream();
int ch;
StringBuffer strBuffer = new StringBuffer();
while ((ch = is.read()) != -1) {
strBuffer.append((char) ch);
}
String responseString = strBuffer.toString();
TwsLog.d(TAG, "response string is" + responseString);
if (serverResponseCode == HttpStatus.SC_OK) {
response = "成功";
} else {
response = "失败,请检查网络重试";
}
} catch (MalformedURLException ex) {
response = "失败,请检查网络重试";
TwsLog.w(TAG, "Upload file to server, error: " + ex + ", err msg" + ex.getMessage());
} catch (Exception e) {
response = "失败,请检查网络重试";
TwsLog.w(TAG, e);
}
return response;
}
/**
* 仅压缩指定文件,不压缩文件夹
* @param zipFile 压缩文件信息
* @param filePaths 需要入的文件列表
* @param extraDatas 压缩的额外信息
* @return
*/
private boolean zipFiles(File zipFile, List<String> filePaths, byte[] extraDatas) {
int cnt = filePaths == null ? 0 : filePaths.size();
if (cnt == 0 && extraDatas == null) {
TwsLog.w(TAG, "zipFiles-> filePaths and extraData is empty");
return false;
}
// 文件个数
TwsLog.i(TAG, "zipFiles-> fileCnt = " + cnt);
String filePath = null;
File fileInfo = null;
byte buffer[] = new byte[BUFF_SIZE];
int readFileLen;
ZipOutputStream zipout = null;
ZipEntry zipEntry = null;
BufferedInputStream fileIos = null;
try {
//删除之前的压缩文件
if (zipFile.exists()) {
zipFile.delete();
}
if (zipFile.getParentFile() != null && !zipFile.getParentFile().exists()) {
zipFile.mkdirs();
}
zipout = new ZipOutputStream(
new BufferedOutputStream(new FileOutputStream(zipFile), BUFF_SIZE));
int zipFipAllProcess = ZIP_FILE_PROCESS - ZIP_EXTRADATA_PROCESS;
for (int i = 0; i < cnt; i++) { // 遍历所有文件
filePath = filePaths.get(i);
if (isStrEmpty(filePath)) {
continue;
}
fileInfo = new File(filePath);
if (!fileInfo.exists() || fileInfo.isDirectory()) {
TwsLog.i(TAG, "zipFiles-> file is not exist or is directory: " + filePath);
continue;
}
if (fileInfo.getAbsolutePath().equals(zipFile.getAbsolutePath())) {
TwsLog.i(TAG, "zipFiles-> file is zipFile, ignore !!!");
continue;
}
// 开始压缩文件
zipEntry = new ZipEntry(fileInfo.getName());
zipout.putNextEntry(zipEntry);
TwsLog.i(TAG, "zipFiles-> file: " + fileInfo.getAbsolutePath());
fileIos = new BufferedInputStream(new FileInputStream(fileInfo), BUFF_SIZE);
while ((readFileLen = fileIos.read(buffer)) != -1) {
// 将文件写入zip流
zipout.write(buffer, 0, readFileLen);
// 更新压缩文件进度
// readLen += realLength;
// int process = Math.round(((float)readLen/fileLen * ZIP_FILE_PROCESS /100) * 100);
// publishProgress(process);
} // ~ end while 一个文件压缩完成
publishProgress(Math.round((float)((i + 1) / cnt) * zipFipAllProcess));
// 关闭文件流
fileIos.close();
fileIos = null;
zipout.flush();
zipout.closeEntry();
} // ~ enf for 所有文件压缩完成
// 添加额外数据
// 开始压缩文件
if (extraDatas != null && extraDatas.length > 0) {
zipEntry = new ZipEntry("extraData");
zipout.putNextEntry(zipEntry);
zipout.write(extraDatas);
}
publishProgress(ZIP_FILE_PROCESS);
zipout.close();
zipout = null;
return true;
} catch (Exception e) {
TwsLog.w(TAG, "zipFiles -> e: " + e + ", err msg: " + e.getMessage());
} finally {
if (fileIos != null) {
try {
fileIos.close();
} catch (Exception e) {
TwsLog.w(TAG, "zipFiles -> fileios close e: " + e + ", err msg: " + e.getMessage());
}
}
if (zipout != null) {
try {
zipout.close();
} catch (Exception e) {
TwsLog.w(TAG, "zipFiles -> zipout close e: " + e + ", err msg: " + e.getMessage());
}
}
}
return false;
}
// public void zipFiles(File resFile, File zipFile) throws IOException {
// ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile), 1024));
//
// zipFile(resFile, zipout);
//
// zipout.close();
// }
//
// private void zipFile(File resFile, ZipOutputStream zipout) throws FileNotFoundException, IOException {
//
// byte buffer[] = new byte[BUFF_SIZE];
//
// BufferedInputStream in = new BufferedInputStream(new FileInputStream(resFile), BUFF_SIZE);
//
// ZipEntry zipEntry = new ZipEntry(resFile.getName());
// zipout.putNextEntry(zipEntry);
//
// TwsLog.d(TAG, "zipFile :" + resFile.getName() + ", size:" + resFile.length());
//
// int readLen = 0;
// long fileLen = resFile.length();
//
// int realLength;
// while ((realLength = in.read(buffer)) != -1) {
// zipout.write(buffer, 0, realLength);
//
// // 更新压缩文件进度
// readLen += realLength;
// int process = Math.round(((float)readLen/fileLen * ZIP_FILE_PROCESS /100) * 100);
// publishProgress(process);
// }
//
// in.close();
// zipout.flush();
// zipout.closeEntry();
// }
private boolean isStrEmpty(String str) {
return str == null || "".equals(str);
}
/**
* 上传状态回调
* @author sukeyli
*
*/
public static interface ILogTransferStatusListener {
/**
* 开始传输日志
*/
void onLogTransferStarted(AppBussInfo appBussInfo);
/**
* 日志传输完成
*/
void onLogTransferEnd(AppBussInfo appBussInfo);
boolean isBussInfoValid(AppBussInfo appBussInfo);
}
}