use of org.xutils.ex.HttpException in project xUtils3 by wyouflf.
the class HttpFragment method onTest5Click.
/**
* 缓存示例, 更复杂的例子参考 {@link org.xutils.image.ImageLoader}
*/
@Event(value = R.id.btn_test5)
private void onTest5Click(View view) throws FileNotFoundException {
BaiduParams params = new BaiduParams();
params.wd = "xUtils";
// 默认缓存存活时间, 单位:毫秒.(如果服务没有返回有效的max-age或Expires)
params.setCacheMaxAge(1000 * 60);
Callback.Cancelable cancelable = // 使用CacheCallback, xUtils将为该请求缓存数据.
x.http().get(params, new Callback.CacheCallback<String>() {
private boolean hasError = false;
private String result = null;
@Override
public boolean onCache(String result) {
// 得到缓存数据, 缓存过期后不会进入这个方法.
// 如果服务端没有返回过期时间, 参考params.setCacheMaxAge(maxAge)方法.
//
// * 客户端会根据服务端返回的 header 中 max-age 或 expires 来确定本地缓存是否给 onCache 方法.
// 如果服务端没有返回 max-age 或 expires, 那么缓存将一直保存, 除非这里自己定义了返回false的
// 逻辑, 那么xUtils将请求新数据, 来覆盖它.
//
// * 如果信任该缓存返回 true, 将不再请求网络;
// 返回 false 继续请求网络, 但会在请求头中加上ETag, Last-Modified等信息,
// 如果服务端返回304, 则表示数据没有更新, 不继续加载数据.
//
this.result = result;
// true: 信任缓存数据, 不在发起网络请求; false不信任缓存数据.
return false;
}
@Override
public void onSuccess(String result) {
// 注意: 如果服务返回304 或 onCache 选择了信任缓存, 这时result为null.
if (result != null) {
this.result = result;
}
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
hasError = true;
Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();
if (ex instanceof HttpException) {
// 网络错误
HttpException httpEx = (HttpException) ex;
int responseCode = httpEx.getCode();
String responseMsg = httpEx.getMessage();
String errorResult = httpEx.getResult();
// ...
} else {
// 其他错误
// ...
}
}
@Override
public void onCancelled(CancelledException cex) {
Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show();
}
@Override
public void onFinished() {
if (!hasError && result != null) {
// 成功获取数据
Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show();
}
}
});
}
use of org.xutils.ex.HttpException in project xUtils3 by wyouflf.
the class HttpFragment method onTest1Click.
/**
* 1. 方法必须私有限定,
* 2. 方法参数形式必须和type对应的Listener接口一致.
* 3. 注解参数value支持数组: value={id1, id2, id3}
* 4. 其它参数说明见{@link org.xutils.view.annotation.Event}类的说明.
**/
@Event(value = R.id.btn_test1, type = View.OnClickListener.class)
private void onTest1Click(View view) {
/**
* 自定义实体参数类请参考:
* 请求注解 {@link org.xutils.http.annotation.HttpRequest}
* 请求注解处理模板接口 {@link org.xutils.http.app.ParamsBuilder}
*
* 需要自定义类型作为callback的泛型时, 参考:
* 响应注解 {@link org.xutils.http.annotation.HttpResponse}
* 响应注解处理模板接口 {@link org.xutils.http.app.ResponseParser}
*
* 示例: 查看 org.xutils.sample.http 包里的代码
*/
BaiduParams params = new BaiduParams();
params.wd = "xUtils";
// 有上传文件时使用multipart表单, 否则上传原始文件流.
// params.setMultipart(true);
// 上传文件方式 1
// params.uploadFile = new File("/sdcard/test.txt");
// 上传文件方式 2
// params.addBodyParameter("uploadFile", new File("/sdcard/test.txt"));
Callback.Cancelable cancelable = x.http().get(params, /**
* 1. callback的泛型:
* callback参数默认支持的泛型类型参见{@link org.xutils.http.loader.LoaderFactory},
* 例如: 指定泛型为File则可实现文件下载, 使用params.setSaveFilePath(path)指定文件保存的全路径.
* 默认支持断点续传(采用了文件锁和尾端校验续传文件的一致性).
* 其他常用类型可以自己在LoaderFactory中注册,
* 也可以使用{@link org.xutils.http.annotation.HttpResponse}
* 将注解HttpResponse加到自定义返回值类型上, 实现自定义ResponseParser接口来统一转换.
* 如果返回值是json形式, 那么利用第三方的json工具将十分容易定义自己的ResponseParser.
* 如示例代码{@link org.xutils.sample.http.BaiduResponse}, 可直接使用BaiduResponse作为
* callback的泛型.
*
* @HttpResponse 注解 和 ResponseParser接口仅适合做json, xml等文本类型数据的解析,
* 如果需要其他数据类型的解析可参考:
* {@link org.xutils.http.loader.LoaderFactory}
* 和 {@link org.xutils.common.Callback.PrepareCallback}.
* LoaderFactory提供PrepareCallback第一个泛型参数类型的自动转换,
* 第二个泛型参数需要在prepare方法中实现.
* (LoaderFactory中已经默认提供了部分常用类型的转换实现, 其他类型需要自己注册.)
*
* 2. callback的组合:
* 可以用基类或接口组合个种类的Callback, 见{@link org.xutils.common.Callback}.
* 例如:
* a. 组合使用CacheCallback将使请求检测缓存或将结果存入缓存(仅GET请求生效).
* b. 组合使用PrepareCallback的prepare方法将为callback提供一次后台执行耗时任务的机会,
* 然后将结果给onCache或onSuccess.
* c. 组合使用ProgressCallback将提供进度回调.
* ...(可参考{@link org.xutils.image.ImageLoader}
* 或 示例代码中的 {@link org.xutils.sample.download.DownloadCallback})
*
* 3. 请求过程拦截或记录日志: 参考 {@link org.xutils.http.app.RequestTracker}
*
* 4. 请求Header获取: 参考 {@link org.xutils.http.app.RequestInterceptListener}
*
* 5. 其他(线程池, 超时, 重定向, 重试, 代理等): 参考 {@link org.xutils.http.RequestParams}
*
**/
new Callback.CommonCallback<List<BaiduResponse>>() {
@Override
public void onSuccess(List<BaiduResponse> result) {
Toast.makeText(x.app(), result.get(0).toString(), Toast.LENGTH_LONG).show();
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();
if (ex instanceof HttpException) {
// 网络错误
HttpException httpEx = (HttpException) ex;
int responseCode = httpEx.getCode();
String responseMsg = httpEx.getMessage();
String errorResult = httpEx.getResult();
// ...
} else {
// 其他错误
// ...
}
}
@Override
public void onCancelled(CancelledException cex) {
Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show();
}
@Override
public void onFinished() {
}
});
// cancelable.cancel(); // 取消请求
}
use of org.xutils.ex.HttpException in project xUtils3 by wyouflf.
the class HttpRequest method sendRequest.
/**
* invoke via Loader
*
* @throws IOException
*/
@Override
@TargetApi(Build.VERSION_CODES.KITKAT)
public void sendRequest() throws Throwable {
isLoading = false;
responseCode = 0;
URL url = new URL(queryUrl);
{
// init connection
Proxy proxy = params.getProxy();
if (proxy != null) {
connection = (HttpURLConnection) url.openConnection(proxy);
} else {
connection = (HttpURLConnection) url.openConnection();
}
// try to fix bug: accidental EOFException before API 19
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
connection.setRequestProperty("Connection", "close");
}
connection.setReadTimeout(params.getReadTimeout());
connection.setConnectTimeout(params.getConnectTimeout());
connection.setInstanceFollowRedirects(params.getRedirectHandler() == null);
if (connection instanceof HttpsURLConnection) {
SSLSocketFactory sslSocketFactory = params.getSslSocketFactory();
if (sslSocketFactory != null) {
((HttpsURLConnection) connection).setSSLSocketFactory(sslSocketFactory);
}
}
}
if (params.isUseCookie()) {
// add cookies
try {
Map<String, List<String>> singleMap = COOKIE_MANAGER.get(url.toURI(), new HashMap<String, List<String>>(0));
List<String> cookies = singleMap.get("Cookie");
if (cookies != null) {
connection.setRequestProperty("Cookie", TextUtils.join(";", cookies));
}
} catch (Throwable ex) {
LogUtil.e(ex.getMessage(), ex);
}
}
{
// add headers
List<RequestParams.Header> headers = params.getHeaders();
if (headers != null) {
for (RequestParams.Header header : headers) {
String name = header.key;
String value = header.getValueStr();
if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(value)) {
if (header.setHeader) {
connection.setRequestProperty(name, value);
} else {
connection.addRequestProperty(name, value);
}
}
}
}
}
// intercept response
if (requestInterceptListener != null) {
requestInterceptListener.beforeRequest(this);
}
{
// write body
HttpMethod method = params.getMethod();
try {
connection.setRequestMethod(method.toString());
} catch (ProtocolException ex) {
try {
// fix: HttpURLConnection not support PATCH method.
Field methodField = HttpURLConnection.class.getDeclaredField("method");
methodField.setAccessible(true);
methodField.set(connection, method.toString());
} catch (Throwable ignored) {
throw ex;
}
}
if (HttpMethod.permitsRequestBody(method)) {
RequestBody body = params.getRequestBody();
if (body != null) {
if (body instanceof ProgressBody) {
((ProgressBody) body).setProgressHandler(progressHandler);
}
String contentType = body.getContentType();
if (!TextUtils.isEmpty(contentType)) {
connection.setRequestProperty("Content-Type", contentType);
}
long contentLength = body.getContentLength();
if (contentLength < 0) {
connection.setChunkedStreamingMode(256 * 1024);
} else {
if (contentLength < Integer.MAX_VALUE) {
connection.setFixedLengthStreamingMode((int) contentLength);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
connection.setFixedLengthStreamingMode(contentLength);
} else {
connection.setChunkedStreamingMode(256 * 1024);
}
}
connection.setRequestProperty("Content-Length", String.valueOf(contentLength));
connection.setDoOutput(true);
body.writeTo(connection.getOutputStream());
}
}
}
if (params.isUseCookie()) {
// save cookies
try {
Map<String, List<String>> headers = connection.getHeaderFields();
if (headers != null) {
COOKIE_MANAGER.put(url.toURI(), headers);
}
} catch (Throwable ex) {
LogUtil.e(ex.getMessage(), ex);
}
}
// check response code
responseCode = connection.getResponseCode();
// intercept response
if (requestInterceptListener != null) {
requestInterceptListener.afterRequest(this);
}
if (responseCode == 204 || responseCode == 205) {
// empty content
throw new HttpException(responseCode, this.getResponseMessage());
} else if (responseCode >= 300) {
HttpException httpException = new HttpException(responseCode, this.getResponseMessage());
try {
httpException.setResult(IOUtil.readStr(this.getInputStream(), params.getCharset()));
} catch (Throwable ignored) {
}
LogUtil.e(httpException.toString() + ", url: " + queryUrl);
throw httpException;
}
isLoading = true;
}
use of org.xutils.ex.HttpException in project xUtils3 by wyouflf.
the class FileLoader method load.
@Override
public File load(final UriRequest request) throws Throwable {
ProcessLock processLock = null;
File result = null;
try {
// 处理[下载逻辑1](见文件头doc)
saveFilePath = params.getSaveFilePath();
diskCacheFile = null;
if (TextUtils.isEmpty(saveFilePath)) {
if (progressHandler != null && !progressHandler.updateProgress(0, 0, false)) {
throw new Callback.CancelledException("download stopped!");
}
// 保存路径为空, 存入磁盘缓存.
initDiskCacheFile(request);
} else {
tempSaveFilePath = saveFilePath + ".tmp";
}
if (progressHandler != null && !progressHandler.updateProgress(0, 0, false)) {
throw new Callback.CancelledException("download stopped!");
}
// 等待, 若不能下载则取消此次下载.
processLock = ProcessLock.tryLock(saveFilePath + "_lock", true);
if (processLock == null || !processLock.isValid()) {
throw new FileLockedException("download exists: " + saveFilePath);
}
params = request.getParams();
{
// 处理[断点逻辑1](见文件头doc)
long range = 0;
if (isAutoResume) {
File tempFile = new File(tempSaveFilePath);
long fileLen = tempFile.length();
if (fileLen <= CHECK_SIZE) {
IOUtil.deleteFileOrDir(tempFile);
range = 0;
} else {
range = fileLen - CHECK_SIZE;
}
}
// retry 时需要覆盖RANGE参数
params.setHeader("RANGE", "bytes=" + range + "-");
}
if (progressHandler != null && !progressHandler.updateProgress(0, 0, false)) {
throw new Callback.CancelledException("download stopped!");
}
// may be throw an HttpException
request.sendRequest();
contentLength = request.getContentLength();
if (isAutoRename) {
responseFileName = getResponseFileName(request);
}
if (isAutoResume) {
isAutoResume = isSupportRange(request);
}
if (progressHandler != null && !progressHandler.updateProgress(0, 0, false)) {
throw new Callback.CancelledException("download stopped!");
}
if (diskCacheFile != null) {
DiskCacheEntity entity = diskCacheFile.getCacheEntity();
entity.setLastAccess(System.currentTimeMillis());
entity.setEtag(request.getETag());
entity.setExpires(request.getExpiration());
entity.setLastModify(new Date(request.getLastModified()));
}
result = this.load(request.getInputStream());
} catch (HttpException httpException) {
if (httpException.getCode() == 416) {
if (diskCacheFile != null) {
result = diskCacheFile.commit();
} else {
result = new File(tempSaveFilePath);
}
// 从缓存获取文件, 不rename和断点, 直接退出.
if (result != null && result.exists()) {
if (isAutoRename) {
responseFileName = getResponseFileName(request);
}
result = autoRename(result);
} else {
IOUtil.deleteFileOrDir(result);
throw new IllegalStateException("cache file not found" + request.getCacheKey());
}
} else {
throw httpException;
}
} finally {
IOUtil.closeQuietly(processLock);
IOUtil.closeQuietly(diskCacheFile);
}
return result;
}
Aggregations