-
Notifications
You must be signed in to change notification settings - Fork 1
Core Function & How to build💻
heewon edited this page Jul 17, 2020
·
2 revisions
- firebaseAuth, googleSignInClient, user, RC_SIGN_IN 객체를 전역으로 선언
private lateinit var firebaseAuth: FirebaseAuth
private lateinit var googleSignInClient: GoogleSignInClient
private val RC_SIGN_IN = 99 //private const val TAG = "GoogleActivity"
val user = FirebaseAuth.getInstance().currentUser**
- GoogleSignInOption객체를 구성할 때 requestIdToken을 호출
- 로그인 버튼을 눌렀을 때 signIn 함수 실행되고 구글 계정 인증 Activity가 실행
imagebutton_login_google.setOnClickListener {
signIn()
Log.d("GoogleLogIn", "버튼 눌림")
}
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build()
private fun signIn() {
val signInIntent = googleSignInClient.signInIntent
startActivityForResult(signInIntent, RC_SIGN_IN)
}
- 로그인이 정상적으로 수행되고 requestCode가 RC_SIGN_IN이면 firebaseWithGoogle함수 호출
if (requestCode == RC_SIGN_IN) {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
try {
val account = task.getResult(ApiException::class.java)
firebaseAuthWithGoogle(account!!)
} catch (e: ApiException) {
Log.w("LoginActivity", "Google sign in failed", e)
}
}
- GoogleSignInAccount객체에서 IdToken을 가져와 FirebaseAuth로 교환하고 인증
➡️ 성공적으로 수행되면 RetrofitClient를 통해서 서버로 userName, userTokenGoogle, userUploadUser 송신
private fun firebaseAuthWithGoogle(acct: GoogleSignInAccount) {
Log.d("LoginActivity", "firebaseAuthWithGoogle:" + acct.id!!)
val credential = GoogleAuthProvider.getCredential(acct.idToken, null)
firebaseAuth.signInWithCredential(credential)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
val user = FirebaseAuth.getInstance().currentUser
RetrofitClient.create(InterfaceSignUp::class.java).interfaceSignUp(
userName, userTokenGoogle, null, userUploadImage
)
.enqueue(object : Callback<ResponseSignUpModel> {
override fun onFailure(call: Call<ResponseSignUpModel>, t: Throwable) {
Log.d("SignUp Google", "${t}")
}
override fun onResponse(
call: Call<ResponseSignUpModel>,
response: Response<ResponseSignUpModel>
) {
if(response.isSuccessful){
if(response.body()!!.success){
Log.d("SignUp 통신성공", "통신성공")
preference.setUserIdx(response.body()!!.data.toString().toInt())
Log.w("LoginActivity", "firebaseAuthWithGoogle 성공", task.exception)
toMainActivity(firebaseAuth?.currentUser)
}
}
}
})
} else {
Log.w("LoginActivity", "firebaseAuthWithGoogle 실패", task.exception)
Snackbar.make(constraintlayout_login, "로그인에 실패하였습니다.", Snackbar.LENGTH_SHORT)
.show()
}
}
}
fun toMainActivity(user: FirebaseUser?) {
if (user != null) { // MainActivity 로 이동
startActivity(Intent(this, MainActivity::class.java))
finish()
}
}
Kakao api
-
Application을 상속하는 GlobalAppication.kt
-
KakaoAdapter를 상속하는 KakaoSDKAdapter
-
SessionCallback.kt를 별도로 생성
<SessionCallback.kt>
- SessionCallback.kt에서 로그인 세션이 성공했을 때와 실패했을 때의 행동을 정의
override fun onSessionOpenFailed(exception: KakaoException?) {
Log.e("KaKaoLogin","Session Call back :: onSessionOpenFailed ${exception?.message}")
}
override fun onSessionOpened() {
UserManagement.getInstance().me(object : MeV2ResponseCallback() {
override fun onFailure(erroResult: ErrorResult?) {
Log.i("KaKaoLogin", "Session Call back:: on failed ${erroResult?.errorMessage}")
}
override fun onSessionClosed(errorResult: ErrorResult?) {
Log.i("KaKaoLogin", "Session Call back:: on Closed ${errorResult?.errorMessage}")
}
override fun onSuccess(result: MeV2Response?) {
Log.d("KaKaoLogin","성공했습니다.")
startInetnt()
checkNotNull(result) { "session response null" }
}
})
}
CanvasDrawingFragment.kt
private var isDrew = false
override fun initCanvas() {
signaturepad.setOnSignedListener(object : SignaturePad.OnSignedListener {
override fun onStartSigning() {
isDrew = true
}
override fun onClear() {
isDrew = false
}
override fun onSigned() {
//Doing nothing. prevent error.
signaturepad
}
})
}
override fun onTrashed() {
signaturepad.clear()
}
📌 OnSignedListener를 view에 설정
- onStartSigning() : pad를 터치했을 때 isDrew의 값이 true로 변경
- onClear() : pad에 그려진 내용을 지울 때 이벤트 발생
- onTrached() : pad에 그려진 그림을 전체 삭제
✔️ 그린 그림을 DB에 저장
CanvasDrawingFragment.kt
private fun saveCardIntoDB(bitmap: Bitmap) {
savedCardRepository.insert(
SavedCardEntity(preference.getProjectIdx()!!, preference.getRoundIdx()!!, SavedCardEntity.FALSE, SavedCardEntity.DRAWING,
BitmapConverter.bitmapToString(bitmap), null
)
)
}
✔️ 비트맵을 문자열로 변환하여 DB에 저장
BitmapConverter.kt
object BitmapConverter {
private const val TAG = "BitmapConverter"
private const val QUALITY = 70
// String -> Bitmap
fun stringToBitmap(encodedString: String?): Bitmap? {
return try {
val encodeByte: ByteArray = Base64.decode(encodedString, Base64.DEFAULT)
BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.size)
} catch (e: Exception) {
Log.e(TAG, e.message.toString())
null
}
}
//Bitmap -> String
fun bitmapToString(bitmap: Bitmap): String {
val baos = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, QUALITY, baos)
val bytes: ByteArray = baos.toByteArray()
return Base64.encodeToString(bytes, Base64.DEFAULT)
}
//Bitmap -> ByteArray
fun bitmapToByteArray(bitmap: Bitmap): ByteArray {
val baos = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, QUALITY, baos)
return baos.toByteArray()
}
}
SocketClientObject
object SocketClient {
private val TAG = javaClass.name
//Todo: URL 받으면 추가하기
private const val SERVER_URL = "http://52.78.113.197:3000"
private var socket: Socket? = null
fun getInstance() : Socket? {
if (socket == null) {
socket = init()
}
return socket
}
fun connection(){
socket?.connect()
}
private fun init(): Socket? {
if (socket == null) {
try {
socket = IO.socket(SERVER_URL)
} catch (e: URISyntaxException) {
e.printStackTrace()
}
}
Log.d(TAG, socket.toString())
return socket
}
fun responseEvent(event: String, callback: Emitter.Listener) {
if (init() != null) {
socket!!.on(event, callback)
} else {
Log.d(TAG, "initial is failed")
}
}
fun sendEvent(event: String, data: String) : Boolean {
return if (init() != null) {
try {
socket!!.emit(event, data)
true
} catch (e: JSONException) {
e.printStackTrace()
false
}
} else {
Log.d(TAG, "initial is failed")
false
}
}
}
HostRoundSettingFragment
fun joinRoundRoom(){
SocketClient.getInstance()
SocketClient.connection()
SocketClient.sendEvent("joinRoom", "roomCode")
SocketClient.sendEvent("roundSetting", "roomCode")
SocketClient.responseEvent("roundComplete", Emitter.Listener {
Log.d("SocketJoinRoom", "Success.")
//방에 들어갔으면 프래그먼트 전환
goToFragment(RoundStartFragment::class.java, null)
})
}
fun refreshParticipantSocket() {
SocketClient.getInstance()
SocketClient.connection()
SocketClient.responseEvent("roundComplete", Emitter.Listener {
Log.d("refresh_socket", "참가자가 들어왔습니다.")
showRoundUserLIst(preference.getRoundIdx()!!)
})
}
1️⃣ Lottie Animation : 스플래쉬, 로그인, 라운드 대기 중 로딩
📌 로그인 애니메이션
private fun initView() {
val animationView = findViewById<LottieAnimationView>(R.id.lottieanimation_login)
animationView.setAnimation("login_bg.json")
animationView.repeatCount = INFINITE
animationView.playAnimation()
}
📌 라운드 대기 중 로딩 애니메이션
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/lottieAnimationView"
android:layout_width="45dp"
android:layout_height="15dp"
android:layout_marginStart="10dp"
app:layout_constraintBottom_toBottomOf="@+id/textview_round_ready"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/textview_round_ready"
app:layout_constraintTop_toTopOf="@+id/textview_round_ready"
app:lottie_autoPlay="true"
app:lottie_rawRes="@raw/loading_animation"
app:lottie_loop="true" />
📢Notification