| 知乎专栏 |
http://square.github.io/okhttp/
再 app/build.gradle 文件中增加依赖包
implementation "com.squareup.okhttp3:okhttp:4.10.0"
app/build.gradle
neo@MacBook-Pro ~/AndroidStudioProjects/okhttp % cat app/build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "cn.netkiller.okhttp"
minSdkVersion 28
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.squareup.okhttp3:okhttp:3.11.0'
}
在 app/src/main/AndroidManifest.xml 文件中增加
<uses-permission android:name="android.permission.INTERNET" />
否则 okhttp 无法访问网络,添加后的效果如下。
neo@MacBook-Pro ~/AndroidStudioProjects/okhttp % cat app/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.netkiller.okhttp">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
如果你尝试使用 http 链接 OkHttp3 就抛出异常: CLEARTEXT communication to " + host + " not permitted by network security policy
开发过程中由于 https ssl 需要购买证书,费用较高,通常测试环境我们仍然使用 http 下面方法是开启 http 模式,
创建文件 res/xml/network_security_config.xml 内容如下
neo@MacBook-Pro ~/AndroidStudioProjects/okhttp % cat app/src/main/res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">localhost</domain>
</domain-config>
</network-security-config>
再 app/src/main/AndroidManifest.xml 文件中增加 android:networkSecurityConfig="@xml/network_security_config"
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.netkiller.okhttp">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
ConnectionPool connectionPool = new ConnectionPool(10, 5, TimeUnit.MINUTES);
OkHttpClient client = new OkHttpClient.Builder()
.connectionPool(connectionPool)
.retryOnConnectionFailure(true)
.connectTimeout(5, TimeUnit.MINUTES)
.readTimeout(5, TimeUnit.MINUTES)
.writeTimeout(Duration.ofSeconds(90))
.callTimeout(Duration.ofSeconds(90))
.build();
client.dispatcher().setMaxRequestsPerHost(200);
client.dispatcher().setMaxRequests(200);
HttpUrl url = new HttpUrl.Builder()
.scheme("https")
.host("www.netkiller.cn")
.addPathSegment("search")
.addQueryParameter("q", "polar bears")
.build();
System.out.println(url);
HttpUrl url = HttpUrl.parse("https://twitter.com/search?q=cute%20%23puppies&f=images");
for (int i = 0, size = url.querySize(); i < size; i++) {
System.out.println(url.queryParameterName(i) + ": " + url.queryParameterValue(i));
}
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.netkiller.cn")
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("服务器端错误: " + response);
}
Headers responseHeaders = response.headers();
for (int i = 0; i < responseHeaders.size(); i++) {
System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
}
System.out.println(response.body().string());
HttpUrl.Builder urlBuilder = HttpUrl.parse("https://www.netkiller.cn").newBuilder();
urlBuilder.addPathSegments("search/cache_vector_chatgpt");
urlBuilder.addQueryParameter("question", "Helloworld!!!");
String url = urlBuilder.build().toString();
Log.d("API", url);
OkHttpClient client = new OkHttpClient();
try {
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
Log.d("API", response.body().string());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
URL 输出
https://www.netkiller.cn/search/cache_vector_chatgpt?question=Helloworld%21%21%21
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()) {
Log.i("TAG", "Async: " + response.body().string());
}
}
});
from 数据如下
key=value&other=data
String url = "https://api.netkiller.cn/oauth/token";
OkHttpClient client = new OkHttpClient();
RequestBody formBody = new FormBody.Builder()
.add("grant_type", "password")
.add("username", "netkiller")
.add("password", "123456")
.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("服务器端错误: " + response);
}
POST RAW Json 数据,数据的形态这样的
{"key":"value"}
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
OkHttpClient client = new OkHttpClient();
final MediaType MEDIA_TYPE_TEXT = MediaType.parse("text/plain");
final String postBody = "Hello World";
RequestBody requestBody = new RequestBody() {
@Override
public MediaType contentType() {
return MEDIA_TYPE_TEXT;
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
sink.writeUtf8(postBody);
}
@Override
public long contentLength() throws IOException {
return postBody.length();
}
};
Request request = new Request.Builder()
.url("https://www.google.com")
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("服务器端错误: " + response);
}
System.out.println(response.body().string());
import java.util.concurrent.TimeUnit;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class Test {
public static void main(String[] args) throws Exception {
String url = "http://****";
String json = "{\"param\":\"value2\",\"key\":\"value\"}";
OkHttpClient client = new OkHttpClient().newBuilder() //
.readTimeout(60, TimeUnit.SECONDS) // 设置读取超时时间
.writeTimeout(60, TimeUnit.SECONDS) // 设置写的超时时间
.connectTimeout(60, TimeUnit.SECONDS) // 设置连接超时时间
.build();
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder().url(url).put(body).build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
}
}
添加Http头
Request request = new Request.Builder()
.url(url)
.addHeader("CLIENT", "AD")
.addHeader("USERID", "343")
.build();
覆盖 HTTP 头
Request request = new Request.Builder()
.header("Authorization", "replace this text with your token")
.url(url)
.build();
public class Headers {
public static void main(String[] args) throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.netkiller.cn")
.header("User-Agent", "Apple Mac")
.addHeader("Accept", "text/html")
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("服务器端错误: " + response);
}
System.out.println(response.header("Server"));
System.out.println(response.headers("Set-Cookie"));
}
}
OkHttpClient mHttpClient = new OkHttpClient.Builder().cookieJar(new CookieJar() {
private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
cookieStore.put(url.host(), cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> cookies = cookieStore.get(url.host());
return cookies != null ? cookies : new ArrayList<Cookie>();
}
}).build();
Request request = new Request.Builder()
.cacheControl(new CacheControl.Builder().noCache().build())
.url(url)
.build();
// 等同于 nocache
Request request = new Request.Builder()
.cacheControl(new CacheControl.Builder()
.maxAge(0, TimeUnit.SECONDS)
.build())
.url("https://www.netkiller.cn")
.build();
// 设置缓存 365 天
Request request = new Request.Builder()
.cacheControl(new CacheControl.Builder()
.maxStale(365, TimeUnit.DAYS)
.build())
.url("https://www.netkiller.cn")
.build();
Request request = new Request.Builder()
.cacheControl(new CacheControl.Builder()
.onlyIfCached()
.build())
.url("https://www.netkiller.cn/helloworld.txt")
.build();
Response forceCacheResponse = client.newCall(request).execute();
if (forceCacheResponse.code() != 504) {
// The resource was cached! Show it.
} else {
// The resource was not cached.
}
OkHttpClient 方案
OkHttpClient client = new OkHttpClient.Builder().authenticator(
new Authenticator(){
public Request authenticate(Route route, Response response) {
String credential = Credentials.basic("api","secret");
return response.request().newBuilder().header("Authorization", credential).build();
}
}
).build();
Request 方案
public void post(String function, File file, Callback responseCallback) {
HttpUrl.Builder urlBuilder = HttpUrl.parse(address).newBuilder();
urlBuilder.addPathSegments(function);
// urlBuilder.addQueryParameter("sentence", question);
String url = urlBuilder.build().toString();
Log.i(TAG, "Post URL: " + url);
OkHttpClient client = this.client();
String credential = Credentials.basic(username, password);
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(), RequestBody.create(file, MediaType.parse("multipart/form-data")))
.build();
Request request = new Request.Builder().url(url)
// .addHeader("token", token)
.addHeader("Authorization", credential)
.post(requestBody).build();
client.newCall(request).enqueue(responseCallback);
}
使用字符串拼接 URL地址特别容易出错
String url = "https://www.netkiller.cn/article?username="+ username + "&category="+ category;
较好的处理方式是使用 HttpUrl.Builder
HttpUrl.Builder builder = HttpUrl.parse("https://www.netkiller.cn/article").newBuilder();
builder.addQueryParameter("username", "netkiller");
builder.addQueryParameter("category", "android");
String url = builder.build().toString();
Log.d("okhttp", url);
输出结果
https://www.netkiller.cn/article?username=netkiller&category=android
package cn.netkiller.okhttp;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class HttpActivity extends AppCompatActivity {
TextView textView;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_http);
textView = (TextView) findViewById(R.id.textView);
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
textView.setText((String) msg.obj);
}
};
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("https://api.netkiller.cn/member/json").build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("okhttp", "Connect timeout. " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String text = response.body().string();
Log.d("okhttp", "HTTP Code " + response.code() + " TEXT " + text);
Message msg = new Message();
msg.what = 0;
msg.obj = text;
mHandler.sendMessage(msg);
}
});
}
}
Oauth 返回数据,通过 Gson 的 fromJson 存储到下面类中。
package cn.netkiller.okhttp.pojo;
public class Oauth {
private String access_token;
private String token_type;
private String refresh_token;
private String expires_in;
private String scope;
private String jti;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getToken_type() {
return token_type;
}
public void setToken_type(String token_type) {
this.token_type = token_type;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getExpires_in() {
return expires_in;
}
public void setExpires_in(String expires_in) {
this.expires_in = expires_in;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getJti() {
return jti;
}
public void setJti(String jti) {
this.jti = jti;
}
@Override
public String toString() {
return "Oauth{" +
"access_token='" + access_token + '\'' +
", token_type='" + token_type + '\'' +
", refresh_token='" + refresh_token + '\'' +
", expires_in='" + expires_in + '\'' +
", scope='" + scope + '\'' +
", jti='" + jti + '\'' +
'}';
}
}
Activity 文件
package cn.netkiller.okhttp;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.google.gson.Gson;
import java.io.IOException;
import cn.netkiller.okhttp.pojo.Oauth;
import okhttp3.Authenticator;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Credentials;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.Route;
public class Oauth2jwtActivity extends AppCompatActivity {
private TextView token;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_oauth2jwt);
token = (TextView) findViewById(R.id.token);
try {
get();
} catch (IOException e) {
e.printStackTrace();
}
}
public static Oauth accessToken() throws IOException {
OkHttpClient client = new OkHttpClient.Builder().authenticator(
new Authenticator() {
public Request authenticate(Route route, Response response) {
String credential = Credentials.basic("api", "secret");
return response.request().newBuilder().header("Authorization", credential).build();
}
}
).build();
String url = "https://api.netkiller.cn/oauth/token";
RequestBody formBody = new FormBody.Builder()
.add("grant_type", "password")
.add("username", "blockchain")
.add("password", "123456")
.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("服务器端错误: " + response);
}
Gson gson = new Gson();
Oauth oauth = gson.fromJson(response.body().string(), Oauth.class);
Log.i("oauth", oauth.toString());
return oauth;
}
public void get() throws IOException {
OkHttpClient client = new OkHttpClient.Builder().authenticator(
new Authenticator() {
public Request authenticate(Route route, Response response) throws IOException {
return response.request().newBuilder().header("Authorization", "Bearer " + accessToken().getAccess_token()).build();
}
}
).build();
String url = "https://api.netkiller.cn/misc/compatibility";
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
call.cancel();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String myResponse = response.body().string();
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i("oauth", myResponse);
token.setText(myResponse);
}
});
}
});
}
public void post() throws IOException {
OkHttpClient client = new OkHttpClient.Builder().authenticator(
new Authenticator() {
public Request authenticate(Route route, Response response) throws IOException {
return response.request().newBuilder().header("Authorization", "Bearer " + accessToken().getAccess_token()).build();
}
}
).build();
String url = "https://api.netkiller.cn/history/create";
String json = "{\n" +
" \"assetsId\": \"5bced71c432c001c6ea31924\",\n" +
" \"title\": \"添加信息\",\n" +
" \"message\": \"信息内容\",\n" +
" \"status\": \"录入\"\n" +
"}";
final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
call.cancel();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String myResponse = response.body().string();
runOnUiThread(new Runnable() {
@Override
public void run() {
// Gson gson = new Gson();
// Oauth oauth = gson.fromJson(myResponse, Oauth.class);
// Log.i("oauth", oauth.toString());
token.setText(myResponse);
}
});
}
});
}
}
上面的例子演示了,怎样获取 access token 以及 HTTP 基本操作 GET 和 POST,再Restful接口中还可能会用到 PUT, DELETE 等等,原来相同,这里就不在演示。
首先确认你的服务器是支持 HTTP2,HTTP2配置方法可以参考 《Netkiller Web 手札》
下面是我的例子仅供参考,Nginx 开启 http2 代理后面的 Spring Cloud 接口。
server {
listen 80;
listen 443 ssl http2;
server_name api.netkiller.cn;
ssl_certificate ssl/netkiller.cn.crt;
ssl_certificate_key ssl/netkiller.cn.key;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 60m;
charset utf-8;
access_log /var/log/nginx/api.netkiller.cn.access.log;
error_page 497 https://$host$uri?$args;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
安卓程序如下
String url = "https://api.netkiller.cn/member/json";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("okhttp", "Connect timeout. " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String text = response.body().string();
Log.d("okhttp", "HTTP Code " + response.code() + " TEXT " + text);
Log.d("okhttp", "Protocol: " + response.protocol());
}
});
运行结果
D/okhttp: HTTP Code 200 TEXT {"status":false,"reason":"","code":0,"data":{"id":null,"username":"12322228888","mobile":"12322228888","password":"123456","wechat":"微信ID","role":"Organization","captcha":null,"createDate":"2018-10-25 09:25:23","updateDate":null}}
Protocol: h2
输出 h2 表示当前接口与服务器连接是通过 http2 完成。
buttonSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
HttpUrl.Builder urlBuilder = HttpUrl.parse(apiUrl).newBuilder();
urlBuilder.addPathSegments("search/cache_vector_chatgpt");
urlBuilder.addQueryParameter("question", editTextMessage.getText().toString());
String url = urlBuilder.build().toString();
Log.d("API", url);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()) {
answer = response.body().string();
updateResult(answer);
Log.i("TAG", "Async: " + answer);
}
}
});
}
});
private void updateResult(final String response) {
//在子线程中更新UI
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// 在这里进行UI操作,将结果显示到界面上
text_dashboard.setText(response);
}
});
}
Lambda 表达式
private void showResponse(final String response) {
//在子线程中更新UI
runOnUiThread(() -> {
// 在这里进行UI操作,将结果显示到界面上
responseText.setText(response);
});
}
在 Fragment 中需这样使用 getActivity().runOnUiThread()
buttonSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
HttpUrl.Builder urlBuilder = HttpUrl.parse(apiUrl).newBuilder();
urlBuilder.addPathSegments("search/cache_vector_chatgpt");
urlBuilder.addQueryParameter("question", editTextMessage.getText().toString());
String url = urlBuilder.build().toString();
Log.d("API", url);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()) {
answer = response.body().string();
getActivity().runOnUiThread(() -> {
text_dashboard.setText(answer);
});
Log.i("TAG", "Async: " + answer);
}
}
});
}
});
public void postStream(String function, LinkedHashMap<String, String> params, String json) throws InterruptedException {
HttpUrl.Builder urlBuilder = HttpUrl.parse(address).newBuilder();
urlBuilder.addPathSegments(function);
if (params != null) {
for (Map.Entry<String, String> entry : params.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
urlBuilder.addQueryParameter(key, value);
}
}
String url = urlBuilder.build().toString();
Log.d(TAG, "Post URL: " + url + " Json: " + json);
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(json, mediaType);
Request request = new Request.Builder()
.url(url)
// .addHeader("Authorization", "Bearer " + token)
.addHeader("Accept", "text/event-stream")
// .addHeader("accept-encoding", "gzip, deflate")
.addHeader("token", this.token)
.post(body).build();
OkHttpClient client = this.client();
RealEventSource realEventSource = new RealEventSource(request, new EventSourceListener() {
@Override
public void onOpen(EventSource eventSource, Response response) {
Log.d(TAG, "onOpen");
}
@Override
public void onEvent(EventSource eventSource, String id, String type, String data) {
Log.d(TAG, "Stream Id: " + id + " Type: " + type + " Data: " + data); // 请求到的数据
}
@Override
public void onClosed(EventSource eventSource) {
Log.d(TAG, "onClosed");
}
@Override
public void onFailure(EventSource eventSource, Throwable throwable, Response response) {
Log.d(TAG, "onFailure");//这边可以监听并重新打开
Log.d(TAG, response.toString());
Log.d(TAG, throwable.toString());
}
});
realEventSource.connect(client);
}
public void getStream(String function, LinkedHashMap<String, String> params, EventSourceListener listener) throws InterruptedException {
HttpUrl.Builder urlBuilder = HttpUrl.parse(address).newBuilder();
urlBuilder.addPathSegments(function);
if (params != null) {
for (Map.Entry<String, String> entry : params.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
urlBuilder.addQueryParameter(key, value);
}
}
String url = urlBuilder.build().toString();
// Log.d(TAG, "Post URL: " + url + " params: " + params.toString());
Request request = new Request.Builder()
.url(url)
// .addHeader("Authorization", "Bearer " + token)
.addHeader("Accept", "text/event-stream; charset=utf-8")
// .addHeader("accept-encoding", "gzip, deflate")
.addHeader("token", this.token)
.get().build();
OkHttpClient client = this.client();
EventSource.Factory createFactory = EventSources.createFactory(client);
// EventSourceListener eventSourceListener = new EventSourceListener() {
// @Override
// public void onEvent(EventSource eventSource, String id, String type, String data) {
//
// Log.d(TAG, "Stream Id: " + id + " Type: " + type + " Data: " + data); // 请求到的数据
// }
//
// public void onFailure(EventSource eventSource, Throwable throwable, Response response) {
// super.onFailure(eventSource, throwable, response);
// Log.d(TAG, response.toString());
// Log.d(TAG, throwable.toString());
// }
// };
createFactory.newEventSource(request, listener);
}
package cn.netkiller.service;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.reactivestreams.Publisher;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketMessage;
import org.springframework.web.reactive.socket.WebSocketSession;
import org.springframework.web.reactive.socket.client.StandardWebSocketClient;
import org.springframework.web.reactive.socket.client.WebSocketClient;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class WebSocketService {
private final OkHttpClient webSocketClient;
private final Request request;
String url = "wss://socketsbay.com/wss/v2/1/demo/";
private WebSocket webSocket;
public WebSocketService() {
webSocketClient = new OkHttpClient.Builder().pingInterval(30, TimeUnit.SECONDS).build();
log.info("WebSocket url: {}", url);
// 构造请求对象
request = new Request.Builder().url(url).build();
connect();
}
public void send(String text) {
if (webSocket == null) {
connect();
}
webSocket.send(text);
log.info("Send: " + text);
}
public void connect() {
// 调用websocket服务端
webSocket = webSocketClient.newWebSocket(request, new MyWebSocketListener());
log.info(webSocket.toString());
}
class MyWebSocketListener extends WebSocketListener {
/**
* websocket连接建立后来到这个方法
*
* @param webSocket
* @param response
*/
@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
try {
log.info("onOpen: " + response.body().string());
} catch (IOException e) {
}
}
@Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
log.info("Receive: " + text);
}
// @Override
// public void onMessage(WebSocket webSocket, ByteString bytes) {
// super.onMessage(webSocket, bytes);
// }
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
super.onClosing(webSocket, code, reason);
log.info("onClosing code: " + code + " reason: " + reason);
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
super.onClosed(webSocket, code, reason);
log.info("onClosed code: " + code + " reason: " + reason);
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
if (response == null) {
log.error("onFailure, response is null.");
return;
}
try {
log.error("onFailure, code: {}, errmsg: {}", response.code(), response.body().string());
} catch (IOException e) {
log.warn("onFailure failed, error: {}", e.getMessage());
}
}
}
}
package cn.aigcsst.student.cloud;
import android.util.Log;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.List;
import okhttp3.Call;
import okhttp3.EventListener;
import okhttp3.Handshake;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.Response;
public class LoggingEventListener extends EventListener {
private static final String TAG = LoggingEventListener.class.getSimpleName();
private Long mCallStartTime = null;
private Long mCallEndTime = null;
private Long mDnsStartTime = null;
private Long mDnsEndTime = null;
private Long mConnectStartTime = null;
private Long mSecureConnectStartTime = null;
private Long mSecureConnectEndTime = null;
private Long mConnectEndTime = null;
private Long mRequestHeadersStartTime = null;
private Long mRequestHeadersEndTime = null;
private Long mResponseHeadersStartTime = null;
private Long mResponseHeadersEndTime = null;
private Long mResponseBodyStartTime = null;
private Long mResponseBodyEndTime = null;
@Override
public void callStart(Call call) {
mCallStartTime = System.currentTimeMillis();
Log.i(TAG, "Event callStart at " + mCallStartTime);
}
@Override
public void dnsStart(Call call, String domainName) {
mDnsStartTime = System.currentTimeMillis();
Log.i(TAG, "Event dnsStart at " + mDnsStartTime);
}
@Override
public void dnsEnd(Call call, String domainName, List<InetAddress> inetAddressList) {
mDnsEndTime = System.currentTimeMillis();
Log.i(TAG, "Event dnsEnd at " + mDnsEndTime + " dnsDuration is " + (mDnsEndTime - mDnsStartTime) + " ms");
}
@Override
public void connectStart(Call call, InetSocketAddress inetSocketAddress, Proxy proxy) {
mConnectStartTime = System.currentTimeMillis();
Log.i(TAG, "Event connectStart at " + mConnectStartTime);
}
@Override
public void secureConnectStart(Call call) {
mSecureConnectStartTime = System.currentTimeMillis();
Log.i(TAG, "Event secureConnectStart at " + mSecureConnectStartTime);
}
@Override
public void secureConnectEnd(Call call, Handshake handshake) {
mSecureConnectEndTime = System.currentTimeMillis();
Log.i(TAG, "Event secureConnectEnd at " + mSecureConnectEndTime + " secureConnectDuration is " + (mSecureConnectEndTime - mSecureConnectStartTime) + " ms");
}
@Override
public void connectEnd(Call call, InetSocketAddress inetSocketAddress, Proxy proxy, Protocol protocol) {
mConnectEndTime = System.currentTimeMillis();
Log.i(TAG, "Event connectEnd at " + mConnectEndTime + " ConnectDuration is " + (mConnectEndTime - mConnectStartTime) + " ms");
}
@Override
public void requestHeadersStart(Call call) {
mRequestHeadersStartTime = System.currentTimeMillis();
Log.i(TAG, "Event requestHeadersStart at " + mRequestHeadersStartTime);
}
@Override
public void requestHeadersEnd(Call call, Request request) {
mRequestHeadersEndTime = System.currentTimeMillis();
Log.i(TAG, "Event requestHeadersEnd at " + mRequestHeadersEndTime + " requestHeadersDuration is " + (mRequestHeadersEndTime - mRequestHeadersStartTime) + " ms");
}
@Override
public void responseHeadersStart(Call call) {
mResponseHeadersStartTime = System.currentTimeMillis();
Log.i(TAG, "Event responseHeadersStart at " + mResponseHeadersStartTime);
}
@Override
public void responseHeadersEnd(Call call, Response response) {
mResponseHeadersEndTime = System.currentTimeMillis();
Log.i(TAG, "Event responseHeadersEnd at " + mResponseHeadersEndTime + " responseHeadersDuration is " + (mResponseHeadersEndTime - mResponseHeadersStartTime) + " ms");
}
@Override
public void responseBodyStart(Call call) {
mResponseBodyStartTime = System.currentTimeMillis();
Log.i(TAG, "Event responseBodyStart at " + mResponseBodyStartTime);
}
public void responseBodyEnd(Call call, Long byteCount) {
mResponseBodyEndTime = System.currentTimeMillis();
Log.i(TAG, "Event responseBodyEnd at " + mResponseBodyEndTime + " responseHeadersDuration is " + (mResponseBodyEndTime - mResponseBodyStartTime) + " ms");
}
@Override
public void callEnd(Call call) {
mCallEndTime = System.currentTimeMillis();
Log.i(TAG, "Event callEnd at " + mCallEndTime + " responseHeadersDuration is " + (mCallEndTime - mCallStartTime) + " ms");
}
@Override
public void callFailed(Call call, IOException ioe) {
Log.i(TAG, "Request Failed: " + ioe.getMessage());
}
}
private OkHttpClient client() {
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder()
.eventListener(new LoggingEventListener())
.retryOnConnectionFailure(true)
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.callTimeout(Duration.ofSeconds(60)).dns(new IPv6Dns());
// .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
// if (authenticator != null) {
// okHttpClient.authenticator(authenticator);
// }
return okHttpClient.build();
}
package cn.netkilller.conference.utils;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class Download {
private static final String TAG = Download.class.getSimpleName();
public Download() {
}
public void downloadToDirectory(final String url, final String directory, final OnDownloadListener listener) throws IOException {
String filename = url.substring(url.lastIndexOf("/") + 1);
String savePath = isExistDir(directory);
File file = new File(savePath, filename);
download(url, file, listener);
}
public void downloadToFile(final String url, final String filename, final OnDownloadListener listener) throws IOException {
File file = new File(Environment.getExternalStorageDirectory() + "/Download", filename);
download(url, file, listener);
}
public void download(final String url, File file, final OnDownloadListener listener) {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
listener.onFailure();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
InputStream inputStream = null;
byte[] buf = new byte[2048];
int len = 0;
FileOutputStream fileOutputStream = null;
try {
inputStream = response.body().byteStream();
long total = response.body().contentLength();
Log.d(TAG, url + " => " + file.getAbsolutePath());
fileOutputStream = new FileOutputStream(file);
long sum = 0;
while ((len = inputStream.read(buf)) != -1) {
fileOutputStream.write(buf, 0, len);
sum += len;
int progress = (int) (sum * 1.0f / total * 100);
listener.onDownloading(progress);
}
fileOutputStream.flush();
listener.onSuccess(file.getAbsolutePath());
} catch (Exception e) {
listener.onFailure();
} finally {
try {
if (inputStream != null)
inputStream.close();
} catch (IOException e) {
}
try {
if (fileOutputStream != null)
fileOutputStream.close();
} catch (IOException e) {
}
}
}
});
}
private String isExistDir(String saveDir) throws IOException {
File downloadFile = new File(Environment.getExternalStorageDirectory(), saveDir);
if (!downloadFile.mkdirs()) {
downloadFile.createNewFile();
}
String savePath = downloadFile.getAbsolutePath();
return savePath;
}
public interface OnDownloadListener {
/**
* 下载成功
*/
void onSuccess(String filename);
/**
* @param progress 下载进度
*/
void onDownloading(int progress);
/**
* 下载失败
*/
void onFailure();
}
}
Download download = new Download();
String url = "https://www.netkiller.cn/android/images/cover.png";
try {
download.downloadToFile(url, "test.png", new Download.OnDownloadListener() {
@Override
public void onSuccess(String filename) {
Log.d(TAG, "下载完成 " + filename);
}
@Override
public void onDownloading(int progress) {
Log.d(TAG, progress + "%");
}
@Override
public void onFailure() {
Log.d(TAG, "下载失败");
}
});
} catch (IOException e) {
throw new RuntimeException(e);
}