안녕하세요,
오늘은 로그인, 로그아웃, Shared Preference, visibility,Interceptor, GONE,
Retrofit, OkHttpClient 에 대해서 정리해보겠습니다.
간단히 제 코드만 올린 상태이고, 추가 설명은 주석처리 해놨습니다.
MainActivity에 관한 내용입니다.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btnSignUp = findViewById<Button>(R.id.btnSignUp) as Button // 첫 번째 회원가입을 누르면 JoinActivity
val email = MyApplication.prefs.getString("email", "") // 로그인이 되어 있다면 값을 가져오고, 안되어 있다면 ""를 설정한다.
val password = MyApplication.prefs.getString("password", "")
if (email == "" && password == ""){ // 로그인이 안되어 있다고 과정하고 로그인 페이지를 띄운다.
val btnLogin = findViewById<Button>(R.id.btnLogin) as Button
btnLogout.visibility = View.GONE // GONE-사라지다. 로그인이 안되어 있으면 로그아웃을 볼 필요가 없으므로 GONE 한다.
btnLogin.setOnClickListener{
val intent = Intent(this, LoginActivity::class.java)
startActivity(intent)
}
} else {
val btnLogout = findViewById<Button>(R.id.btnLogout) as Button
btnLogin.visibility = View.GONE // 반대로 로그인이 되어 있는 상태에서 로그인을 볼 필요가 없기에 GONE 한다.
btnLogout.setOnClickListener{
val intent = Intent(this, LogoutActivity::class.java)
startActivity(intent)
}
}
btnSignUp.setOnClickListener{ // 요건 회원가입
val intent = Intent(this, JoinActivity::class.java)
startActivity(intent)
}
}
}
다음 LoginActivity
class LoginActivity : AppCompatActivity() {
// Login 에서 Shared Preferences
// Shared Preferences 는 간단한 값을 저장할 때 주로 사용한다. 초기 설정 값이나 **자동 로그인 여부** 등 간단한 값을
// 저장할 때 DB를 사용하면 복잡하기 때문에 Shared Preferences 를 사용하면 적합하다.
// 로그아웃 할 때 Shared Preferences 데이터를 가져와 세션을 같으 삭제하면 완벽한 로그아웃이 완성?!
lateinit var email: EditText
lateinit var password: EditText
lateinit var loginBtn: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
email = findViewById(R.id.login_email)
password = findViewById(R.id.login_password)
loginBtn = findViewById(R.id.login_btnLogin)
loginBtn.setOnClickListener {
val email = email.text.toString().trim()
val password1 = password.text.toString().trim()
var state: Boolean?
val api = Api.create() // 여기에 보이는 Api가 headerInterceptor, OkHttpClient, Retrofit 을 갖고 있다.
val data = LoginResponse(email, password1) // 로그인 data class를 가져온다.
api.userLogin(data).enqueue(object: Callback<LoginBackendResponse> {
// userLogin @Body에는 request 값을 넣어주고,
// ): Call<> 에는 리스폰스 값을 넣어준다.
// data class LoginResponse(val email: String, val password: String)
// data class LoginBackendResponse(val code: String, val message: String, val token: String? = null)
override fun onResponse(call: retrofit2.Call<LoginBackendResponse>, response: Response<LoginBackendResponse>) { // 성공한 경우
state = if(response.body()?.code == "200"){ // Node.js 에서 200값이 response로 오게되면 if
MyApplication.prefs.setString("email", email) // Shared Preferences setString
MyApplication.prefs.setString("password", password1)
val intent = Intent(this@LoginActivity, HomeActivity::class.java) // 화면을 이동한다.
startActivity(intent)
Toast.makeText(this@LoginActivity, "로그인에 성공하였습니다.", Toast.LENGTH_SHORT).show() // 알림 발생
true
} else {
Toast.makeText(this@LoginActivity, "로그인에 실패하였습니다.", Toast.LENGTH_SHORT).show()
false
}
}
override fun onFailure(call: retrofit2.Call<LoginBackendResponse>, t: Throwable) { // 실패한 경우
false.also { state = it }
}
})
}
}
}
다음 LogoutActivity
class LogoutActivity : AppCompatActivity() { // 로그아웃 페이지
// TODO(problem): Logout two click why? No Screen / dialog
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_logout)
val btnLogout = findViewById<Button>(R.id.logout_btnLogout) as Button
btnLogout.setOnClickListener{
var dialog = AlertDialog.Builder(this)
dialog.setTitle("로그아웃을 하시겠습니까?")
dialog.setMessage("서비스를 이용해주셔서 감사합니다.")
// dialog.setIcon 추후에 아이콘 삽입
fun toast() {
Toast.makeText(this, "로그아웃 되었습니다.", Toast.LENGTH_SHORT).show()
MyApplication.prefs.edit.remove("email") // 여기서 Shared Preference 를 remove 한다!
MyApplication.prefs.edit.remove("password")
MyApplication.prefs.edit.commit() // SP 삭제되는 것을 확인
val intent = Intent(this, HomeActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
startActivity(intent)
}
var dialogLister = DialogInterface.OnClickListener { p0, p1 ->
when (p1) {
DialogInterface.BUTTON_POSITIVE -> toast()
}
}
dialog.setPositiveButton("YES", dialogLister)
dialog.setNegativeButton("NO", null)
dialog.show()
}
}
}
다음 Api (Interceptor, OkHttpClient, Retrofit)
interface Api {
// 내용 정리
// Retrofit, 송신 시 우리는 값을 디코딩한 상태로 보였지만, OkHttpClient 에서는 인코딩 된 상태로 확인되었고,
// 그게 백엔드로 전송이되면 당연히 오류가 발생했고, 인코딩 문제를 해결하려고 하였음
// 최종 정리
// postman 으로도 원하는 값을 넣어 보내도 오류가 발생하는 문제 확인완료.
// OkHttpClient 는 @FormUrlEncoded 로 인코딩이 된 걸로 확인(확실하지 않음) 그래서 백엔드에서 인코딩 된 걸 디코딩하여
// 받아야 되는 걸로 확인 - help 조이스
// @FormUrlEncoded
// @POST("/api/auth/signup/")
// fun createUser(
// @Field("email") email:String,
// @Field("password") password1:String
// ): Call<SignUpResponse>
@Headers("content-type: application/json")
@POST("/api/auth/signup/")
fun createUser(
@Body jsonParams:SignUpResponse,
): Call<SignUpResponse>
@Headers("content-type: application/json")
@POST("/api/auth/signin")
fun userLogin(
@Body jsonParams: LoginResponse,
): Call<LoginBackendResponse>
companion object {
private const val BASE_URL = "http://0.0.0.0"
fun create(): Api {
val httpLoggingInterceptor = HttpLoggingInterceptor()
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
val headerInterceptor = Interceptor {
val request = it.request()
.newBuilder()
.addHeader("Content-Type", "application/json; charset=utf-8")
.build()
return@Interceptor it.proceed(request)
}
val client = OkHttpClient.Builder()
.addInterceptor(headerInterceptor)
.addInterceptor(httpLoggingInterceptor)
.addNetworkInterceptor(headerInterceptor)
.build()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(Api::class.java)
}
}
}
'Mobile > Kotlin' 카테고리의 다른 글
| Kotlin @Body와 @Field 차이 (0) | 2022.04.12 |
|---|
댓글