校科创项目即将接近尾声,最近学习了一下安卓客户端和服务端的对接,使用的是Okhttp这个开源框架。
1 Okhttp简介
Okhttp是目前Android主流的处理网络请求的开源框架,用于替代HttpUrlConnection。从Android4.4开始,google已经开始将源码中的HttpURLConnection替换为OkHttp。
2 Okhttp的安装
在所处Module的build.gradle的dependencies中添加:
implementation("com.squareup.okhttp3:okhttp:4.3.1")
添加后同步。
3 Okhttp使用的基本步骤
-
取得 OkHttpClient 对象(或OkHttpClient.Builder对象)
OkHttpClient okHttpClient=new OkHttpClient(); /*或*/ OkHttpClient.Builder okHttpClientBuilder=new OkHttpClient.Builder();
-
构造Request
Request.Builder builder=new Request.Builder(); /*****get请求-请求头URL*****/ Request request=builder.get().url(mBaseUrl+"请求内容").build(); /*****post请求-请求体*****/ RequestBody requestBody=RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), "json数据内容"); /*或*/ RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file); /*或*/ FormBody requestBody = new FormBody //FormBody extends RequestBody .Builder() .add("usename","zqq_post") .add("password","123456").build(); Request request = builder.url(mBaseUrl + 服务端方法名).post(requestBody).build();
-
将Request封装为Call
private void executeRequest(Request request) throws IOException { Call call=okHttpClientBuilder.build().newCall(request); call.enqueue(new Callback() { @Override public void onFailure(@NotNull Call call, @NotNull IOException e) { L.e("onFailure" +e.getMessage()); e.printStackTrace(); } @Override public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { L.e("onResponse:"); final String res=response.body().string(); L.e(res); runOnUiThread(new Runnable() { @Override public void run() { /******对客户端元素的操作******/ } }); } }); }
-
执行call
executeRequest(request);
4 Session和Cookie
-
功能:记录一系列状态
-
两者区别:session是记录在服务端的,cookie是记录在客户端的
-
session解决了不同HTTP的请求的关联问题,让它们产生联系
-
session追踪的实现
在客户端中,我需要为赋予cookiejar
okHttpClientBuilder.cookieJar(new PersistenceCookieJar());
封装的接口如下:
public class PersistenceCookieJar implements CookieJar {
List<Cookie> cache = new ArrayList<>();
//Http请求结束,Response中有Cookie时候回调
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
//内存中缓存Cookie
cache.addAll(cookies);
}
//Http发送请求前回调,Request中设置Cookie
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
//过期的Cookie
List<Cookie> invalidCookies = new ArrayList<>();
//有效的Cookie
List<Cookie> validCookies = new ArrayList<>();
for (Cookie cookie : cache) {
if (cookie.expiresAt() < System.currentTimeMillis()) {
//判断是否过期
invalidCookies.add(cookie);
} else if (cookie.matches(url)) {
//匹配Cookie对应url
validCookies.add(cookie);
}
}
//缓存中移除过期的Cookie
cache.removeAll(invalidCookies);
//返回List<Cookie>让Request进行设置
return validCookies;
}
};
同时,在服务端中,我可以获取到相应的sessionId:
request.getSession.getId();
5 常见问题
- Android 6.0+的动态权限问题
除了要在AndroidManifest中声明权限,还要使用如下代码动态获取
public void accessPermission(){
if (Build.VERSION.SDK_INT >= 23) {
int REQUEST_CODE_CONTACT = 101;
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
//验证是否许可权限
for (String str : permissions) {
if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
//申请权限
this.requestPermissions(permissions, REQUEST_CODE_CONTACT);
return;
}}}}