implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
<uses-permission android:name="android.permission.INTERNET" />
登入之前須要先有帳號,所以要先註冊
提供註冊的網址是https://k88d02.ml/api/register
因爲後端的註冊請求方法是POST,發request須要帶BODY的資料
格式爲formdata如下
建立interface包含一個register funtion
還有使用@FormUrlEncoded搭配各欄位@Field的annotation
private const val BASE_URL = "https://k88d02.ml/api/"
interface ApiService {
@Headers("Content-type: application/json","Accept: application/json")
@POST("register")
@FormUrlEncoded
fun register(
@Field("name") name: String,
@Field("password") password: String,
@Field("email") email: String
): Call<RegisterResponse>
}
object Api {
private val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
val retrofitService: ApiService = retrofit.create(ApiService::class.java)
}
伺服器送回的response是JSON
所以建立一個data class RegisterResponse
data class RegisterResponse(
@SerializedName("success")
var isSuccess: Boolean = true,
@SerializedName("message")
var message: String = "",
@SerializedName("data")
var data: Nothing? = null
)
建議先測試連線是否正常,使用postman這個軟體
Send發送
可獲得response,表示連線正常
{
"success": false,
"message": "email已使用",
"data": null
}
接著就做一個登入頁面,在程式呼叫api
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
btn_register.setOnClickListener {
hideKeyboard(textView, textView)
Api.retrofitService
.register(
ed_account.text.toString(),
ed_password.text.toString(),
ed_email.text.toString()
)
.enqueue(object : retrofit2.Callback<RegisterResponse> {
override fun onFailure(call: Call<RegisterResponse>, t: Throwable) {
Log.e("Failed", t.toString())
}
override fun onResponse(call: Call<RegisterResponse>, response: Response<RegisterResponse>) {
if (response.isSuccessful) { //request 200,註冊成功
Toast.makeText(requireActivity(), response.body()?.message, Toast.LENGTH_SHORT).show()
Log.d("Success!", response.body().toString())
}else{ //request 400,註冊失敗
Toast.makeText(requireActivity(), response.body()?.message, Toast.LENGTH_SHORT).show()
Log.d("Success!", response.body().toString())
Toast.makeText(requireActivity(), "註冊失敗", Toast.LENGTH_SHORT).show()
}
}
})
}
}
密碼欄位可以加一個屬性,讓輸入隱藏
android:inputType="textPassword"
可以看到第一次顯示註冊失敗,因爲密碼只輸入了4個
而伺服器要求6-12個,改爲8個後就顯示註冊成功了
logcat
D/Success!: RegisterResponse(isSuccess=true, message=register success , please login, data=null)
這邊有點搞錯,原來是用email加password登入
所以我的版面欄位稍微改一下
一樣是POST,要帶的資料是formdata
所以interface加一個login funtion
interface ApiService {
// @Headers("Content-type: application/json","Accept: application/json")
@POST("register")
@FormUrlEncoded
fun register(
@Field("name") name: String,
@Field("password") password: String,
@Field("email") email: String
): Call<RegisterResponse>
@POST("login")
@FormUrlEncoded
fun login(
@Field("email") name: String,
@Field("password") password: String
): Call<LoginResponse>
}
伺服器login獲得的response
再建立一個data class LoginResponse
裡面的rememberToken是每次登入成功時,會取得的一組token
data class LoginResponse(
@SerializedName("data")
val `data`: Data = Data(),
@SerializedName("message")
val message: String = "",
@SerializedName("success")
val success: Boolean = false // true
) {
data class Data(
@SerializedName("remember_token")
val rememberToken: String = "", // TeR5GEi4ftp4BtKqM65Q7LYB1R0dbeY5n22ZVCulgokPigme2UFOH12VEVol
@SerializedName("token_expire_time")
val tokenExpireTime: String = "", // 2020/09/19 23:10:13
@SerializedName("user_id")
val userId: Int = 0 // 3
)
}
先註冊一組帳號asdf@asdf.com / 密碼asdfasdf
並確認註冊成功D/Success!: RegisterResponse(isSuccess=true, message=register success , please login, data=null)
再按下登入,可以看到顯示login的Toast有取得token
Toast.makeText(requireActivity(), response.body()?.data?.rememberToken, Toast.LENGTH_SHORT).show()
多按幾次登入,每次拿到的token都會不一樣
D/Success!: RegisterResponse(isSuccess=true, message=register success , please login, data=null)
D/Success!: LoginResponse(data=Data(rememberToken=Zs5H2xrUh7ZYIW95urGJvY2G4rozZbvtfwIqNdZ6oz1TlmLM93pyILKZUVSt, tokenExpireTime=2020/10/05 15:40:45, userId=36), message=, success=true)
D/Success!: LoginResponse(data=Data(rememberToken=yec7MPpzKUELbBOwLYge7CmDSXnrKlXUdmQGI0VEL2z4gpg7mnhMqFZzWb6t, tokenExpireTime=2020/10/05 15:40:52, userId=36), message=, success=true)
D/Success!: LoginResponse(data=Data(rememberToken=gRA8pwe33OStUjG0XbQEFQvzTtZpECW0mAh1oXmhcgOcSpo2Xuz7tojSsN4W, tokenExpireTime=2020/10/05 15:41:28, userId=36), message=, success=true)
感謝工作室與鐵人賽,雖然30天還只是一個起點
但讓我有養成學習後要記錄的習慣,感覺能夠更幫助吸收
期望能持續下去!