https://github.com/FirebaseExtended/custom-auth-samples
이 예제로 테스트로 만들었는데
로그에서는 아래의 에러메시지가 뜹니다.
E/com.example.kakaologintest.MainActivity: com.android.volley.TimeoutError
그리고 웹스톱의 end serverpoint에서는 아래와 같은 코드가 뜹니다.
Unhandled rejection StatusCodeError: 400 - “{“msg”:“application(id=405531, name=‘테스트’) using deprecated api(/v1/user/me)”,“code”:-9}”
뭐가 문제일까요?
아 ~ 해결했습니다…
예제 서버에서
const requestMeUrl = ‘https://kapi.kakao.com/v1/user/me?secure_resource=true’;
으로 되어있는데
카카오 rest API를 가보니 아래더군요…에잇!!!
const requestMeUrl = ‘https://kapi.kakao.com/v2/user/me?secure_resource=true’;
서버는 http://192.168.1.10:8000입니다.
package com.example.kakaologintest
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.databinding.DataBindingUtil.setContentView
import com.android.volley.DefaultRetryPolicy
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.JsonObjectRequest
import com.android.volley.toolbox.Volley
import com.bumptech.glide.Glide
import com.example.kakaologintest.databinding.ActivityMainBinding
import com.google.android.gms.tasks.Continuation
import com.google.android.gms.tasks.OnCompleteListener
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.TaskCompletionSource
import com.google.firebase.auth.AuthResult
import com.google.firebase.auth.FirebaseAuth
import com.kakao.auth.ISessionCallback
import com.kakao.auth.Session
import com.kakao.usermgmt.UserManagement
import com.kakao.usermgmt.callback.LogoutResponseCallback
import com.kakao.util.exception.KakaoException
import kotlinx.android.synthetic.main.activity_main.*
import org.json.JSONObject
class MainActivity : AppCompatActivity() {
private val TAG = MainActivity::class.java.name
var binding: ActivityMainBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolBar =
findViewById(R.id.toolbar) as Toolbar
setSupportActionBar(toolBar)
binding = setContentView(this, R.layout.activity_main);
logout_button.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
UserManagement.getInstance().requestLogout(object : LogoutResponseCallback() {
override fun onCompleteLogout() {
FirebaseAuth.getInstance().signOut()
val handler = Handler(Looper.getMainLooper())
handler.post(Runnable { updateUI() })
}
})
}
})
Session.getCurrentSession().addCallback(KakaoSessionCallback())
}
override fun onStart() {
super.onStart()
updateUI()
}
/**
* Update UI based on Firebase's current user. Show Login Button if not logged in.
*/
private fun updateUI() {
val currentUser = FirebaseAuth.getInstance().currentUser
if (currentUser != null) {
binding?.setCurrentUser(currentUser)
if (currentUser.photoUrl != null) {
Glide.with(this)
.load(currentUser.photoUrl)
.into(profile_image_view)
}
login_button.setVisibility(View.INVISIBLE)
logged_in_view.setVisibility(View.VISIBLE)
logout_button.setVisibility(View.VISIBLE)
} else {
login_button.setVisibility(View.VISIBLE)
logged_in_view.setVisibility(View.INVISIBLE)
logout_button.setVisibility(View.INVISIBLE)
}
}
/**
* OnActivityResult() should be overridden for Kakao Login because Kakao Login uses startActivityForResult().
*/
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
super.onActivityResult(requestCode, resultCode, data)
Session.getCurrentSession()
.handleActivityResult(requestCode, resultCode, data)
}
inner class KakaoSessionCallback : ISessionCallback {
override fun onSessionOpened() {
Toast.makeText(
this@MainActivity,
"Successfully logged in to Kakao. Now creating or updating a Firebase User.",
Toast.LENGTH_LONG
).show()
val accessToken = Session.getCurrentSession().accessToken
getFirebaseJwt(accessToken)?.continueWithTask(object :
Continuation<String, Task<AuthResult>> {
override fun then(task: Task<String>): Task<AuthResult> {
val firebaseToken = task.result
val auth = FirebaseAuth.getInstance()
return auth.signInWithCustomToken(firebaseToken.toString())
}
})?.addOnCompleteListener(object : OnCompleteListener<AuthResult> {
override fun onComplete(task: Task<AuthResult>) {
if (task.isSuccessful) {
updateUI()
} else {
Toast.makeText(
this@MainActivity,
"Failed to create a Firebase user.",
Toast.LENGTH_LONG
).show()
if (task.exception != null) {
Log.e(TAG, task.exception.toString());
}
}
}
})
}
override fun onSessionOpenFailed(exception: KakaoException) {
Log.e(TAG, exception.toString())
}
}
fun getFirebaseJwt(kakaoAccessToken: String): Task<String>? {
val source = TaskCompletionSource<String>()
val queue = Volley.newRequestQueue(this@MainActivity)
val url =
resources.getString(R.string.validation_server_domain) + "/verifyToken"
val validationObject: HashMap<String?, String?> = HashMap()
validationObject["token"] = kakaoAccessToken
val request: JsonObjectRequest = object : JsonObjectRequest(
Request.Method.POST,
url,
JSONObject(validationObject as Map<*, *>),
Response.Listener { response ->
try {
val firebaseToken = response?.getString("firebase_token")
source.setResult(firebaseToken)
} catch (e: java.lang.Exception) {
source.setException(e)
}
},
Response.ErrorListener { error ->
Log.e(TAG, error.toString())
source.setException(error)
}) {
override fun getParams(): Map<String, String> {
val params: MutableMap<String, String> = HashMap()
params["token"] = kakaoAccessToken
return params
}
}
queue.add(request)
return source.task
}
}