I am currently developing an Android program using Retrofit2. The module works well, but when I register the app on the Google Play Store and run internal tests, I get an error:
Exception Process: com.project.tosspayment, PID: 14085 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.project.tosspayment/com.project.tosspayment.MainActivity}: java.lang.IllegalArgumentException: Unable to create call adapter for interface s4.f for method a.b
I'm looking for opinions from everyone on this issue.
Here is my NetworkService.kt.
package com.project.kioask.retrofit
import com.google.gson.JsonObject<br>
import com.project.kioask.model.orderModel<br>
import retrofit2.Call<br>
import retrofit2.http.Body<br>
import retrofit2.http.Header<br>
import retrofit2.http.Headers<br>
import retrofit2.http.POST<br>
interface NetworkService {
@POST("/order/additem")
fun doPostList(@Header("Authorization") token: String?, @Body dto: orderModel?): Call<orderModel>
@Headers("Content-Type:application/json")
@POST("/user/signpass")
fun doPostToken(@Body passkey: String): Call<JsonObject>
}
Here is my MainActivity.kt.
package com.project.tosspayment<br>
import android.Manifest<br>
import android.content.Intent<br>
import android.content.SharedPreferences<br>
import android.content.pm.PackageManager<br>
import android.os.Bundle<br>
import android.util.Log<br>
import android.view.LayoutInflater<br>
import android.view.View<br>
import android.widget.Toast<br>
import androidx.appcompat.app.AlertDialog<br>
import androidx.appcompat.app.AppCompatActivity<br>
import androidx.core.app.ActivityCompat<br>
import androidx.core.content.ContextCompat<br>
import com.google.gson.JsonObject<br>
import com.google.zxing.integration.android.IntentIntegrator<br>
import com.google.zxing.integration.android.IntentResult<br>
import com.project.kioask.retrofit.NetworkService<br>
import com.project.tosspayment.databinding.ActivityMainBinding<br>
import com.project.tosspayment.databinding.CustomDialogBinding<br>
import retrofit2.Call<br>
import retrofit2.Callback<br>
import retrofit2.Response<br>
import retrofit2.Retrofit<br>
import retrofit2.converter.gson.GsonConverterFactory<br>
import java.util.regex.Pattern<br>
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
lateinit var customDialogBinding: CustomDialogBinding
private var backPressTime:Long = 0
private val REQUEST_CAMERA_PERMISSION = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
customDialogBinding =
CustomDialogBinding.inflate(LayoutInflater.from(this@MainActivity))
if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA),REQUEST_CAMERA_PERMISSION)
} else {
openScanner()
}
val passkey = getString(R.string.backend_secretKey)
val tokenRetrofit = Retrofit.Builder()
.baseUrl("https://api.format.kro.kr")
.addConverterFactory(GsonConverterFactory.create())
.build();
val jsonObject = JsonObject()
jsonObject.addProperty("passkey",passkey)
val tokenService = tokenRetrofit.create(NetworkService::class.java)
val tokenCall: Call<JsonObject> = tokenService.doPostToken(passkey)
try {
tokenCall.enqueue(object : Callback<JsonObject> {
override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
if(response.isSuccessful){
val token = response.body()?.get("token")?.asString
val tokenSaved = getSharedPreferences("token", MODE_PRIVATE)
val tokenEdit: SharedPreferences.Editor = tokenSaved.edit()
tokenEdit.putString("token",token)
tokenEdit.apply()
Log.w("zio","token: $token")
}else{
Log.w("zio","인증실패 : ${response.code()}")
}
}
override fun onFailure(call: Call<JsonObject>, t: Throwable) {
Log.w("zio","접속실패 : ${t.message}")
}
})
}catch (e: Exception){
e.printStackTrace()
Log.w("zio","error : ${e.message}")
}
}
private fun openScanner(){
val QrScan = IntentIntegrator(this)
QrScan.setCameraId(0) //후방카메라 사용
QrScan.setBeepEnabled(false) //스캔할때 소리 끄기
QrScan.addExtra("PROMPT_MESSAGE","QR코드를 스캔해주세요")
QrScan.setOrientationLocked(false)
QrScan.initiateScan()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
val result: IntentResult =
IntentIntegrator.parseActivityResult(requestCode, resultCode, data)
val scannerData = result.contents
if (scannerData == null) {
dialog("QR코드 확인","QR코드를 다시 스캔해 주세요",
customDialogBinding.dialogButton.setOnClickListener {
intent = Intent(this, MainActivity::class.java)
startActivity(intent)
})
return
}
if (requestCode == IntentIntegrator.REQUEST_CODE && resultCode == RESULT_OK) {
val pattern =
Pattern.compile("\\{\"orderId\":\"([A-Za-z0-9]+)\",\"price\":(\\d+),\"orderName\":\"([^\"]+)\",\"customerKey\":\"([A-Za-z0-9]+)\"\\}")
val matcher = pattern.matcher(scannerData ?: "")
if (matcher.find()) {
val orderid = matcher.group(1)
val price = matcher.group(2)?.toInt()
val ordername = matcher.group(3)
val customerKey = matcher.group(4)
intent = Intent(this, PayActivity::class.java)
intent.putExtra("orderId", orderid)
intent.putExtra("price", price)
intent.putExtra("orderName", ordername)
intent.putExtra("customerKey", customerKey)
startActivity(intent)
}
super.onActivityResult(requestCode, resultCode, data)
}else{
dialog("QR코드 확인","잘못된 QR코드 입니다.",
customDialogBinding.dialogButton.setOnClickListener {
intent = Intent(this, MainActivity::class.java)
startActivity(intent)
})
}
}
override fun onBackPressed() {
if(System.currentTimeMillis() - backPressTime < 2_000){
finish()
}else{
Toast.makeText(this,"한번 더 누르면 앱이 종료됩니다.",Toast.LENGTH_SHORT).show()
backPressTime = System.currentTimeMillis()
}
}
fun dialog(title:String,message:String, OnClickListener: Unit) {
val alertDialog = AlertDialog.Builder(this)
.setView(customDialogBinding.customDialog)
.create()
customDialogBinding.dialogTitle.text = title
customDialogBinding.dialogMessage.text = message
customDialogBinding.dialogButton.text = "확인"
customDialogBinding.dialogMessage.visibility = View.VISIBLE
customDialogBinding.dialogButton.visibility = View.VISIBLE
alertDialog.show()
}
}