很久没写博客了, 自己定的路已经走歪,菜鸟的进阶之路上我只是走了一步,自从发了一篇博客之后在没有来过这里,已经有一年了吧,今天再次回到这里。
言归正传,今天要写的是xUtils3.x网络请求的封装和请求https,最近xUtils做出了一次比较大的重构,原有的使用规则都有了新的变化。具体的变化可以去 https://github.com/wyouflf/xUtils3.git ,还有很多大神都整理了很多写了博客,需要了解的自行去看。
xUtils3.x还是和之前一样分有4大模块:注解模块,网络模块,图片加载模块,数据库模块。
在开始封装之前,我们需要把准备工作做好.
1. 不可缺少的权限:
2. 导入jar 和 so 文件 (提供一个大神的下载地址:http://dl.bintray.com/wyouflf/maven/org/xutils/xutils/ )
如果是AS 使用Gradle 构建时添加一下依赖即可 compile 'org.xutils:xutils:3.2.2'
3.初始化 在Application的oncreate方法中加入下面代码:
x.Ext.init(this);
x.Ext.setDebug(BuildConfig.DEBUG);
4.在Acitivity里使用注解的话. 需要在Activity的oncreate方法中加入下面代码:
x.view().inject(this);
Fragment里注解就需要onCreateView里 return x.view().inject(this, inflater, container);
哈哈,是不是太啰嗦了,等等先。 xUtils3.x网络请求里最大的变化就是
x.http().get(params, mCallback); x.http().post(params, mCallback);直接用x来获取。取消了HttpUtils这个类.
RequestParams params = new RequestParams(url); 在newRequestParams的时候必须要传请求接口url. 这就是在网络模块里一些的改变. 但并不是所有的。
开始上代码咯。HttpXUtils3Manager类
import java.io.InputStream;
import java.net.HttpCookie;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.xutils.x;
import org.xutils.common.Callback.Cancelable;
import org.xutils.common.Callback.CommonCallback;
import org.xutils.ex.HttpException;
import org.xutils.http.HttpMethod;
import org.xutils.http.RequestParams;
import org.xutils.http.cookie.DbCookieStore;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager.NameNotFoundException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.TypeReference;
import com.lidroid.xutils.http.HttpHandler;
import com.ylpw.ticketapp.BuildConfig;
import com.ylpw.ticketapp.R;
import com.ylpw.ticketapp.YongLeApplication;
import com.ylpw.ticketapp.common.App;
import com.ylpw.ticketapp.common.ConstantManager;
import com.ylpw.ticketapp.common.LogManager;
import com.ylpw.ticketapp.log.Logger;
import com.ylpw.ticketapp.model.TResult;
import com.ylpw.ticketapp.model.TResultWrapper;
import com.ylpw.ticketapp.util.Base64Util;
import com.ylpw.ticketapp.util.NetworkUtils;
import com.ylpw.ticketapp.util.ToastUtils;
/**
* xUtils3 应用与网络通讯管理类
**/
public class HttpXUtils3Manager {
/** Https 证书验证对象 */
private static SSLContext s_sSLContext = null;
private static final String TAG = "HttpXUtils3Manager";
private HttpXUtils3Manager() {
}
/**
* http get请求
*
* @param params 请求参数 get请求使用 addQueryStringParameter方法添加参数
* @param mCallback 回调对象
* @return 网络请求的Cancelable 可以中断请求
*/
public static Cancelable getHttpRequest(RequestParams params, final XUtils3Callback mCallback) {
return sendHttpRequest(HttpMethod.GET, params, mCallback);
}
/**
* http post请求
*
* @param params 请求参数 post请求使用 addBodyParameter方法添加参数
* @param mCallback 回调对象
* @return 网络请求的Cancelable 可以中断请求
*/
public static Cancelable postHttpRequest(RequestParams params, final XUtils3Callback mCallback) {
return sendHttpRequest(HttpMethod.POST, params, mCallback);
}
/**
* 发送请求 Cancelable
*
* @param method 请求方式(GET POST)
* @param params 请求参数
* @param mCallback 回调对象
* @return 网络请求的Cancelable 可以中断请求
*/
public static Cancelable sendHttpRequest(HttpMethod method, RequestParams params, final XUtils3Callback mCallback){
if (!NetworkUtils.isNetworkAvailable(YongLeApplication.getInstance())) {// 网络请求之前先检查网络是否可用
mCallback.onFinished();
mCallback.onError(new TResult(), "网络连接失败,请重试");
ToastUtils.showToast(R.string.checknetwork);
return null;
}
if (params == null) {
params = new RequestParams();
}
params.setHeader("Cookie", App.getCookie());// 设置Cookie
params.setCacheMaxAge(1000*0); //为请求添加缓存时间
params.setConnectTimeout(ConstantManager.CONNECTION_TIME_OUT); //超时时间60s
/** Cancelable cancelable = x.http().get(params, Callback); */
return x.http().request(method, params , new CommonCallback() {
@Override //取消
public void onCancelled(CancelledException msg) {
ToastUtils.showToast(msg.getMessage());
mCallback.onError(new TResult(), msg.getMessage());
mCallback.onFinished();
}
@Override //错误
public void onError(Throwable arg0, boolean arg1) {
if (arg0 instanceof HttpException) { // 网络错误
}
ToastUtils.showToast(arg0.getMessage());
LogManager.i(TAG, "==> RequestCallBack.onError()");
LogManager.e(TAG, "==> response:" + arg0.getMessage() + "\n==> error:" + arg1);
mCallback.onError(new TResult(), arg0.getMessage());
mCallback.onFinished();
}
@Override //成功
public void onSuccess(String result) {
if (result == null) {
return;
}
LogManager.i(TAG, "==> RequestCallBack.onSuccess()");
Logger.json(result);
try {
TResultWrapper
公共的请求回调类XUtils3Callback
import com.ylpw.ticketapp.model.TResult;
/**
* 公共的请求回调类
*
* xiexucheng
*/
public interface XUtils3Callback {
/**
* 通讯成功,返回正常的数据时回调的方法
*
* @param result 返回信息
*/
void onSuccess(String result);
/**
* 请求失败、拦截到错误等,回调的方法
*
* @param mTResult 错误信息 根据自己的项目接口的返回去model
* @param message 提示信息
*/
void onError(TResult mTResult, String message);
/**
* 请求结束回调的方法
*/
void onFinished();
}
在Activity中使用
private void getHttpXUtilsData() {
RequestParams params = new RequestParams("https://www.baidu.com");
params.addQueryStringParameter("name", "dlx2cheng");
HttpXUtils3Manager.getHttpRequest(params, new XUtils3Callback() {
@Override
public void onSuccess(String result) {
//这里用的是fastjson解析
TResultWrapper resulta = JSON.parseObject(result, new Typ eReference>() {});
TProductDataWrapper data = resulta.getData();
if (data != null) {
}
}
@Override
public void onError(TResult mTResult, String message) {
ToastUtils.showToast(message);
}
@Override
public void onFinished() {
}
});
}
到这里基本就是一套xUtils3.x的get和post请求的封装了。 但是.. 如果你运行成功了一定会事情失败。因为请求的是https://www.baidu.com
这是https的请求. 一般公司都有一个SSL证书,也就是crt文件或者cet文件(其实都是一样的)。 把文件放入assets或者raw文件下, 只要拿到文件就行了。
xUtils当然也提供了设置SSL的方法.
params.setSslSocketFactory(sslContext.getSocketFactory()); //绑定SSL证书(https请求)
当然也是写在sendHttpRequest里,跟在设置超时时间后面就行了。 下面看代码:
params.setHeader("Cookie", App.getCookie());// 设置Cookie
params.setCacheMaxAge(1000*0); //为请求添加缓存时间
params.setConnectTimeout(ConstantManager.CONNECTION_TIME_OUT); //超时时间60s
/** 判断https证书是否成功验证 */
SSLContext sslContext = getSSLContext(YongLeApplication.getInstance());
if(null == sslContext){
if (BuildConfig.DEBUG) LogManager.d(TAG, "Error:Can't Get SSLContext!");
return null;
}
params.setSslSocketFactory(sslContext.getSocketFactory()); //绑定SSL证书(https请求)
/**
* 获取Https的证书
* @param context Activity(fragment)的上下文
* @return SSL的上下文对象
*/
private static SSLContext getSSLContext(Context context) {
CertificateFactory certificateFactory = null;
InputStream inputStream = null;
Certificate cer = null;
KeyStore keystore = null;
TrustManagerFactory trustManagerFactory = null;
try {
certificateFactory = CertificateFactory.getInstance("X.509");
inputStream = context.getAssets().open("baidu.crt");//这里导入SSL证书文件
try {
//读取证书
cer = certificateFactory.generateCertificate(inputStream);
LogManager.i(TAG, cer.getPublicKey().toString());
} finally {
inputStream.close();
}
//创建一个证书库,并将证书导入证书库
keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null,null); //双向验证时使用
keystore.setCertificateEntry("trust", cer);
// 实例化信任库
trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// 初始化信任库
trustManagerFactory.init(keystore);
s_sSLContext = SSLContext.getInstance("TLS");
s_sSLContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
//信任所有证书 (官方不推荐使用)
// s_sSLContext.init(null, new TrustManager[]{new X509TrustManager() {
//
// @Override
// public X509Certificate[] getAcceptedIssuers() {
// return null;
// }
//
// @Override
// public void checkServerTrusted(X509Certificate[] arg0, String arg1)
// throws CertificateException {
//
// }
//
// @Override
// public void checkClientTrusted(X509Certificate[] arg0, String arg1)
// throws CertificateException {
//
// }
// }}, new SecureRandom());
return s_sSLContext;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
这个异常呢也就是说证书的信任路径找不到. 当时我就报了这俩问题, 我仔细看代码没发现问题, 又上某度查了一天还是没有什么答案, 有的都是让信任所有证书,后来我突然想到看证书的有效时间才发现证书到期了!!! 赶紧找公司给了我一个新的, 放进去后完全没事了 - -. 很纠结的。 当然了, 有可能还有其他的问题会导致出现这两个异常。。
如果有发现代码不对和疑问的地方,欢迎各位来探讨. 我的QQ和邮箱:7907716、[email protected]