Response error okhttp3. runOnUiThread/Thread

166 views Asked by At

I want to make a request to the server and get a response from it. Next, display in displayWindow.

I can’t get a response from the server, I understand that I need to process the UI in a separate thread, I generally do this, but I don’t quite understand why I still get such an error, please tell me.

package com.openai.gpt;

import android.os.Bundle;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import java.io.IOException;
import java.util.Objects;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {

    private static final String API_KEY = "API_KEY";
    private static final String API_URL = "API_URL";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView displayWindow = findViewById(R.id.displayWindow);
        EditText textField = findViewById(R.id.textField);
        ImageButton sendButton = findViewById(R.id.sendButton);

        sendButton.setOnClickListener(v -> {
            String message = textField.getText().toString();
            getChatResponse(message, displayWindow);
        });
    }

    private void getChatResponse(String message, TextView displayWindow) {
        OkHttpClient client = new OkHttpClient();
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create("{\"prompt\": \"" + message + "\",\"model\":\"text-davinci-003\", \"temperature\": 1, \"max_tokens\": 1000}", mediaType);
        Request request = new Request.Builder()
                .url(API_URL)
                .post(body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Authorization", "Bearer " + API_KEY)
                .build();

        try (Response response = client.newCall(request).execute()) {
            String responseBody = Objects.requireNonNull(response.body()).string();
            JsonObject jsonObject = JsonParser.parseString(responseBody).getAsJsonObject();
            JsonArray choices = jsonObject.getAsJsonArray("choices");
            JsonObject selectedChoice = choices.get(0).getAsJsonObject();
            String text = selectedChoice.get("text").getAsString();
            runOnUiThread(() -> displayWindow.setText(text));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
Connected to the target VM, address: 'localhost:61975', transport: 'socket'
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/zygote: Late-enabling -Xcheck:jni
W/zygote: Unexpected CPU variant for X86 using defaults: x86
W/ActivityThread: Application com.openai.gpt is waiting for the debugger on port 8100...
I/System.out: Sending WAIT chunk
I/zygote: Debugger is active
I/System.out: Debugger has connected
I/System.out: waiting for debugger to settle...
I/chatty: uid=10084(u0_a84) com.openai.gpt identical 5 lines
I/System.out: waiting for debugger to settle...
I/System.out: debugger has settled (1370)
D/AppCompatDelegate: Checking for metadata for AppLocalesMetadataHolderService : Service not found
D/OpenGLRenderer: HWUI GL Pipeline
D/: HostConnection::get() New Host Connection established 0x9ba64a80, tid 28386
I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 1
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
D/OpenGLRenderer: Swap behavior 0
D/EGL_emulation: eglCreateContext: 0x9bd052a0: maj 2 min 0 rcv 2
D/EGL_emulation: eglMakeCurrent: 0x9bd052a0: ver 2 0 (tinfo 0x9bd031b0)
D/EGL_emulation: eglMakeCurrent: 0x9bd052a0: ver 2 0 (tinfo 0x9bd031b0)
W/View: dispatchProvideAutofillStructure(): not laid out, ignoring
I/AssistStructure: Flattened final assist data: 1992 bytes, containing 1 windows, 8 views
I/zygote: Do partial code cache collection, code=30KB, data=23KB
I/zygote: After code cache collection, code=30KB, data=23KB
I/zygote: Increasing code cache capacity to 128KB
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
W/zygote: Got a deoptimization request on un-deoptimizable method java.net.InetAddress[] libcore.io.Linux.android_getaddrinfo(java.lang.String, android.system.StructAddrinfo, int)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.openai.gpt, PID: 28347
    android.os.NetworkOnMainThreadException
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1448)
        at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:102)
        at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:90)
        at java.net.InetAddress.getAllByName(InetAddress.java:787)
        at okhttp3.Dns$Companion$DnsSystem.lookup(Dns.kt:49)
        at okhttp3.internal.connection.RouteSelector.resetNextInetSocketAddress(RouteSelector.kt:164)
        at okhttp3.internal.connection.RouteSelector.nextProxy(RouteSelector.kt:129)
        at okhttp3.internal.connection.RouteSelector.next(RouteSelector.kt:71)
        at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:205)
        at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
        at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
        at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
        at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
        at com.openai.gpt.MainActivity.getChatResponse(MainActivity.java:56)
        at com.openai.gpt.MainActivity.lambda$onCreate$0$com-openai-gpt-MainActivity(MainActivity.java:41)
        at com.openai.gpt.MainActivity$$ExternalSyntheticLambda1.onClick(Unknown Source:6)
        at android.view.View.performClick(View.java:6256)
        at android.view.View$PerformClick.run(View.java:24701)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Disconnected from the target VM, address: 'localhost:61975', transport: 'socket'

Please tell me what am I doing wrong?

Used both runOnUiThread and Thread nothing helped

1

There are 1 answers

0
TG. Kahsay On

you are getting android.os.NetworkOnMainThreadException because the network call is happening on UI thread. calling runOnUiThread() from within UI thread doesn't help here. you have to first run things on a background thread and then call UI thread from the background thread.

so, may be you can try something like this.


 sendButton.setOnClickListener(v -> {
            String message = textField.getText().toString();
            Thread thread = new Thread(){
            @Override
            public void run() {
               super.run();
               getChatResponse(message, displayWindow); // call this method on a separate thread. 
               }
            };
           thread.start()
        });

P.s, there may be a better way to handle this using the okhttp library itself.