首页 > 解决方案 > 使用 Kotlin 在 Android 中使用 Body 制作 Retrofit2 POST

问题描述

我正在尝试在使用 Kotlin 的 Android 应用程序中使用 Retrofit 调用 API。API 需要类似于以下示例输入的标头和正文:

样本输入

标题:

登录名:65848614-6697-4cf7-a64a-e0b9374c4aee

身体:

客户 ID:DKOKTrykIQ987yQcLNehT8SWJRMyQLdP 秘密:6Jt1ENlDn9gxPu5f

内容类型必须作为 application/x-www-form-urlencoded 传递。

目前,我正在使用以下类:

YodleeService.kt

interface YodleeService {

        @Headers(
            "loginName: de5559cc-5375-4aca-8224-990343774c08_ADMIN",
            "Api-Version: 1.1",
            "Content-Type: application/x-www-form-urlencoded"
        )
        @POST("auth/token")
        fun generateLoginToken(
            @Body postBody: PostBody
        ) : Call<LoginToken>
}

AccountRetriever.kt

class AccountRetriever {
    private val service: YodleeService

    companion object {
        const val BASE_URL = "https://sandbox.api.yodlee.com:443/ysl/"
    }

    init {
        val retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        service = retrofit.create(YodleeService::class.java)
    }

    fun login(callback: Callback<LoginToken>) {
        val postBody = PostBody("TG86ljAk6lt28GYZlRTQWssaLmGpS6jV", "A2P9ZPEqB4uos1nv")
        val call = service.generateLoginToken(postBody)
        call.enqueue(callback)
    }
}

邮筒

data class PostBody(
    val clientId: String?,
    val secret: String?
)

主要活动

class MainActivity : AppCompatActivity() {

    private val accountRetriever = AccountRetriever()

    private val loginCallback = object : Callback<LoginToken> {
        override fun onFailure(call: Call<LoginToken>, t: Throwable) {
            Log.e("MainActivity", "Problem calling Yodlee API {${t.message}")
        }

        override fun onResponse(call: Call<LoginToken>?, response: Response<LoginToken>?) {
            response?.isSuccessful.let {
                Log.i("MainActivity", "errorBody - Content = ${response?.raw()}")
                val loginToken = LoginToken(
                    response?.body()?.accessToken ?: "",
                    response?.body()?.expiresIn ?: "",
                response?.body()?.issuedAt ?: "")
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        accountsList.layoutManager = LinearLayoutManager(this)

        if (isNetworkConnected()) {
            accountRetriever.login(loginCallback)
        } else {
            AlertDialog.Builder(this).setTitle("No Internet Connection")
                .setMessage("Please check your internet connection and try again")
                .setPositiveButton(android.R.string.ok) { _, _ -> }
                .setIcon(android.R.drawable.ic_dialog_alert).show()
        }
    }

    private fun isNetworkConnected(): Boolean {
        val connectivityManager =
            getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val activeNetwork = connectivityManager.activeNetwork
        val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork)
        return networkCapabilities != null &&
                networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    }
}

当我调试我的应用程序时,我收到了[size=213 text=\n {\n "errorCode": "Y303",\n …]. API 的文档说这个错误代码意味着缺少 clientId 或 secret。

当我通过调试器挖掘时,我看到原始调用读取为

Request {
    method = POST, url = https: //sandbox.api.yodlee.com/ysl/auth/token, 
        tags = {
            class retrofit2.Invocation =
            com.example.budgettracker.api.YodleeService.generateLoginToken()[PostBody(
                clientId = TG86ljAk6lt28GYZlRTQWssaLmGpS6jV, secret = A2P9ZPEqB4uos1nv)]
        }
}

我无法确定 API 看不到 POST 正文内容的原因。任何帮助将不胜感激。

标签: androidkotlinretrofit2

解决方案


推荐阅读