Reputation: 33
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
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
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