J'utilise la bibliothèque OkHttp dans mon Android pour faire des demandes Web à une API météo. J'ai déjà implémenté mon code et j'obtiens une EXCEPTION FATALE lorsque je fais la demande.
J'ai également ajouté des autorisations INTERNET dans mon manifeste.
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'
}
Ensuite, voici l'exception que je reçois:
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)
Je ne sais pas quoi faire à ce stade. J'ai lu et trouvé quelques articles sur ce sujet. D'après ce que j'ai rassemblé, les changements d'interface utilisateur doivent être effectués dans le bloc runOnUiThread (). Mais je ne fais aucun changement d'interface ici dans mon code et je reçois toujours l'exception.
J'ai également déjà essayé de mettre mon code d'analyse JSON dans runOnUiThread () et j'ai obtenu le même résultat FATAL EXCEPTION. Quelqu'un a une idée?
Response
le corps ne peut être consommé qu'une seule fois. Tu le fais deux fois
Log.v(TAG, response.body().string());
String jsonData = response.body().string();
Plus d'informations dans docs
J'ai eu le même problème et je l'ai résolu en passant à Java 8. Ajoutez options de compilation sous votre build.gradle fichier.
Android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
Assignez la réponse à une variable puis vous pourrez la réutiliser
Cela est dû à l'utilisation de différentes versions d'OkHttp. Assurez-vous que toutes vos dépendances de com.squareup.okhttp3 utilisent la même version.
exemple:
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
implementation 'com.squareup.okhttp3:okhttp:3.8.0'