AndroidアプリでOkHttpライブラリを使用してWeather APIへのWebリクエストを作成しています。すでにコードを実装しており、リクエストを実行すると致命的な例外が発生します。
マニフェストにもインターネットアクセス許可を既に追加しています。
MainActivity.Java:
private CurrentWeather currentWeather;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActivityMainBinding binding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);
String apiKey = "xxx";
double latitude = 37.8267;
double longitude = -122.4233;
String forecastURL = String.format("https://api.darksky.net/forecast/%s/%f,%f", apiKey, latitude, longitude);
if (isNetworkAvailable()) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(forecastURL)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
try {
Log.v(TAG, response.body().string());
String jsonData = response.body().string();
if (response.isSuccessful()) {
currentWeather = getCurrentDetails(jsonData);
}
} catch (IOException e) {
Log.e(TAG, e.getLocalizedMessage());
} catch (JSONException e) {
Log.e(TAG, e.getLocalizedMessage());
}
}
});
}
Log.d(TAG, "Main UI code is running");
}
private CurrentWeather getCurrentDetails(String jsonData) throws JSONException {
JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
JSONObject currently = forecast.getJSONObject("currently");
String icon = currently.getString("icon");
String locationLabel = "Alcatraz Island";
String summary = currently.getString("summary");
long time = currently.getLong("time");
double humidity = currently.getDouble("humidity");
double precipProbability = currently.getDouble("precipProbability");
double temperature = currently.getDouble("temperature");
return new CurrentWeather(locationLabel, icon, time, temperature, humidity, precipProbability, summary, timezone);
}
Gradle:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.Android.support:appcompat-v7:28.0.0'
implementation 'com.Android.support.constraint:constraint-layout:1.1.3'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
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'
}
次に、私が得ている例外は次のとおりです。
2018-12-04 20:55:49.969 3314-3330/com.test.starmie E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
Process: com.test.starmie, PID: 3314
Java.lang.IllegalStateException: closed
at okio.RealBufferedSource.rangeEquals(RealBufferedSource.Java:407)
at okio.RealBufferedSource.rangeEquals(RealBufferedSource.Java:401)
at okhttp3.internal.Util.bomAwareCharset(Util.Java:471)
at okhttp3.ResponseBody.string(ResponseBody.Java:175)
at com.test.starmie.MainActivity$1.onResponse(MainActivity.Java:66)
at okhttp3.RealCall$AsyncCall.execute(RealCall.Java:206)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.Java:32)
at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1133)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:607)
at Java.lang.Thread.run(Thread.Java:761)
この時点で何をすべきかわかりません。私は周りを読んで、このトピックに関するいくつかの投稿を見つけました。私が収集したものから、UIの変更はrunOnUiThread()ブロックで行う必要があります。しかし、ここではコードでUIを変更していないため、例外が発生します。
私はすでにJSON解析コードをrunOnUiThread()に入れてみて、同じ致命的な例外の結果を得ました。誰かアイデアはありますか?
Response
ボディは1回のみ使用できます。あなたは二回作る
Log.v(TAG, response.body().string());
String jsonData = response.body().string();
詳細は docs にあります
私は同じ問題を抱えていましたが、Java 8互換性に切り替えることで解決しました。あなたの下にcompileOptionsを追加してくださいbuild.gradleファイル。
Android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
変数に応答を割り当てると、変数を再利用できます
これは、異なるバージョンのOkHttpを使用していることが原因です。 com.squareup.okhttp3からのすべての依存関係が同じバージョンを使用していることを確認してください。
例:
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
implementation 'com.squareup.okhttp3:okhttp:3.8.0'