Fabien Pauvers
Fabien Pauvers

Reputation: 33

Why Android is blocking my OkHttp Request

I tried to call my API with OkHttp But android does not want me to do it! I read that i need to make my class extends AsyncTask but it does not work maybe i just dont know how to make it async but here is the code before i tried to make it async can you help me?

here is my OkHttpHelper class package com.example.mygostyle

import android.content.Context
import android.os.AsyncTask
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import org.json.JSONObject
import java.io.IOException


class OkHttpHelper {

    var client = OkHttpClient()
    var token : String
    init{
        token = ""
    }

    fun login(un: String, pwd: String, context: Context) : Boolean{

        val urlBuilder = HttpUrl.Builder()
            .scheme("https")
            .host("dev.api.gostyle.ovh")
            .addPathSegment("api")
            .addPathSegment("user")
            .addPathSegment("auth")
            .addQueryParameter("username",un)
            .addQueryParameter("password",pwd)
            .build()

        var request = Request.Builder()
            .url(urlBuilder)
            .build()

        client.newCall(request).execute().use { response ->
            if (!response.isSuccessful) throw IOException("Unexpected code $response")
            val responseData = response.body?.string()
            val json = JSONObject(responseData)
            val owner = json.getString("token")
            if(response.code == 200) {
                saveToken(context, owner)
                return true
            }
            return false
        }
    }

    fun saveToken(context: Context, token : String){
        val sharedPreference = SharedPreference(context)
        sharedPreference.save("MyGoStyleToken",token)

    }

}

here is my Login Activity package com.example.mygostyle

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.content.Intent
import android.view.Window
import android.view.WindowManager
import android.widget.EditText


class LoginActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        this.requestWindowFeature(Window.FEATURE_NO_TITLE)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        this.setContentView(R.layout.activity_login);

        val loginbtn = findViewById<Button>(R.id.loginbtn)

        loginbtn.setOnClickListener(){
            login(this)
        }
    }

    fun login(context: Context){
        var okHttpHelper = OkHttpHelper()
        val uninput = findViewById<EditText>(R.id.username_input).text.toString()
        val pwdinput = findViewById<EditText>(R.id.password_input).text.toString()
        if(okHttpHelper.login(uninput,pwdinput,context)) {
            val gameActivity = Intent(this@LoginActivity, MyPromosActivity::class.java)
            startActivity(gameActivity)
        }

    }


}

the error log :

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.mygostyle, PID: 20075
    android.os.NetworkOnMainThreadException
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1450)
        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$SYSTEM$1.lookup(Dns.kt:48)
        at okhttp3.internal.connection.RouteSelector.resetNextInetSocketAddress(RouteSelector.kt:160)
        at okhttp3.internal.connection.RouteSelector.nextProxy(RouteSelector.kt:125)
        at okhttp3.internal.connection.RouteSelector.next(RouteSelector.kt:71)
        at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:199)
        at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:109)
        at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:77)
        at okhttp3.internal.connection.Transmitter.newExchange$okhttp(Transmitter.kt:162)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:35)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:82)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:84)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:71)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.kt:184)
        at okhttp3.RealCall.execute(RealCall.kt:66)
        at com.example.mygostyle.OkHttpHelper.login(OkHttpHelper.kt:36)
        at com.example.mygostyle.LoginActivity.login(LoginActivity.kt:34)
        at com.example.mygostyle.LoginActivity$onCreate$1.onClick(LoginActivity.kt:26)
        at android.view.View.performClick(View.java:6294)
        at android.view.View$PerformClick.run(View.java:24770)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

Upvotes: 0

Views: 2260

Answers (2)

Taha Malas
Taha Malas

Reputation: 200

As the error says, you're making network calls on the main thread, and that's prohibited because a network call is a very long operation to make.

The execute function make the API request in a synchronized manner, whereas the enqueue function make it in an asynchronous way, as you probably know when you want to make an asynchronous call you can't return things from your function because the code is no longer working in a sequential order, so you have to make an interface that's similar to a callback.

interface MyCallback {
    fun onResult(result: bool)
}


fun login(un: String, pwd: String, context: Context, myCallback: MyCallback) {

        val urlBuilder = HttpUrl.Builder()
            .scheme("https")
            .host("dev.api.gostyle.ovh")
            .addPathSegment("api")
            .addPathSegment("user")
            .addPathSegment("auth")
            .addQueryParameter("username",un)
            .addQueryParameter("password",pwd)
            .build()

        var request = Request.Builder()
            .url(urlBuilder)
            .build()

        client.newCall(request).enqueue(object: Callback {
          override public fun onFailure(call: Call, e: IOException) {
             throw IOException("Unexpected code $response")
          }
          override public fun onResponse(call: Call, response: Response) {
             if (!response.isSuccessful) throw IOException("Unexpected code $response")
             val responseData = response.body?.string()
             val json = JSONObject(responseData)
             val owner = json.getString("token")
             if(response.code == 200) {
                  saveToken(context, owner)
                  myCallback,onResult(true)
             }
             myCallback,onResult(false)
         }
       })
    }

So there will be no return type for the login function and you can call this function in this way.

class LoginActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        this.requestWindowFeature(Window.FEATURE_NO_TITLE)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        this.setContentView(R.layout.activity_login);

        val loginbtn = findViewById<Button>(R.id.loginbtn)

        loginbtn.setOnClickListener(){
            login(this, object : MyCallback {
               public override fun onResult(result: Boolean) {
                  // Do something with the result returned
               }
        })
    }

    fun login(context: Context, callback, MyCallback){
        var okHttpHelper = OkHttpHelper()
        val uninput = findViewById<EditText>(R.id.username_input).text.toString()
        val pwdinput = findViewById<EditText>(R.id.password_input).text.toString()
        if(okHttpHelper.login(uninput,pwdinput,context, callback)) {
            val gameActivity = Intent(this@LoginActivity, MyPromosActivity::class.java)
            startActivity(gameActivity)
        }

    }


}

Upvotes: 0

Naveen Niraula
Naveen Niraula

Reputation: 771

As stated you cannot do network requests on MainThread. So one way to do this would be AsyncTask as:

class LoginActivity : AppCompatActivity() {

    fun login(context: Context){

        AsyncTask.execute {

            var okHttpHelper = OkHttpHelper()
            val uninput = findViewById<EditText>(R.id.username_input).text.toString()
            val pwdinput = findViewById<EditText>(R.id.password_input).text.toString()
            if(okHttpHelper.login(uninput,pwdinput,context)) {
                val gameActivity = Intent(this@LoginActivity, MyPromosActivity::class.java)
                startActivity(gameActivity)
            }
        }

    }

}

Upvotes: 3

Related Questions