Vintage appMaker의 Tech Blog

Firebase Template with kotlin 본문

Source code or Tip/Android(Java, Kotlin)

Firebase Template with kotlin

VintageappMaker 2020. 7. 18. 21:34

kotlin을 이용한 Firebase의 기초

https://github.com/VintageAppMaker/FireBaseTemplate

 

VintageAppMaker/FireBaseTemplate

Firebase를 빠르게 시작하기 위한 예제. Contribute to VintageAppMaker/FireBaseTemplate development by creating an account on GitHub.

github.com

Firebase Quick Example

Firebase를 빠르게 적용하기

주의

  1. 되도록이면 Android Studio에서 제공하는 Tool보다는 Firebase 사이트에서 직접 수동으로 진행할 것. 버전 충돌이 종 일어남.
  2. 인터넷 예제들은 Firebase 모듈간 호환성도 고려해야 함. Gradle의 버전설정 민감함
  3. app 폴더 및의 google-services.json은 다음과 같이 새롭게 만들어 사용해야 한다(보안문제).
    1. 자신의 Firebase 개발자 콘솔로 접속.
    2. 프로젝트 생성.
    3. 설정 메뉴 이동 후,
    4. google-services.json 다운로드
    5. 지금 프로젝트의 app 폴더에 복사

app 폴더의 build.gradle


    implementation 'com.google.firebase:firebase-auth:16.0.2'
    implementation 'com.google.firebase:firebase-database:16.0.2'
    implementation 'com.google.firebase:firebase-firestore:16.0.0'
    implementation "com.google.firebase:firebase-storage:16.0.2"
  • Firebase auth
  • Firebase RealTime Database
  • Firebase FireStore
  • Firebase FireStorage

MainActivity.kt

package com.psw.adsloader.firebasetemplate

import android.content.Context
import android.graphics.Bitmap
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.*
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.storage.FirebaseStorage
import kotlinx.android.synthetic.main.activity_main.*
import java.io.ByteArrayOutputStream
import java.util.*


class MainActivity : AppCompatActivity() {

    var  mAuth : FirebaseAuth? = null

    data class Item(var name : String, var img : String, var mp3 : String )
    private val posts: MutableList<Item> = mutableListOf()

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

        mAuth = FirebaseAuth.getInstance()

        txtLogin.setOnClickListener {
            LoginUserInfo("snake2@caver.com", "123456mode6")
        }

        btnCreate.setOnClickListener {
            CreateUserInfo("snake2@caver.com", "123456mode6")
        }

        // Realtime Database에 값을 추가하기
        btnSetData.setOnClickListener {
            var fd  = FirebaseDatabase.getInstance()
            var ref = fd.getReference("playlist").push()

            val item = Item(
                    mAuth!!.getCurrentUser().toString(),
                    mAuth!!.getCurrentUser().toString(),
                    mAuth!!.getCurrentUser().toString())

            ref.setValue(item)
        }

        // Realtime Database에 리스트를 가져오기(당황스러움! 많이!!)
        // 현실적으로 사용하기 무척 불쾌함.
        btnGetData.setOnClickListener {
            var fd  = FirebaseDatabase.getInstance()
            var ref = fd.getReference("playlist")
            ref.addListenerForSingleValueEvent( object : ValueEventListener {
                override fun onCancelled(p0: DatabaseError) {

                }

                override fun onDataChange(p0: DataSnapshot) {
                    posts.clear()

                    // 한번에 긁어온다.
                    var str = ""
                    p0.children.forEach {
                        str = str + "\n" + it.toString()

                    }
                    WriteLn(str)

                }
            })

        }

        // firebase의 라이브러리간 버전호환은 아주 안좋다.
        // implementation 'com.google.firebase:firebase-firestore:11.8.0' 기준임.
        btnFireStoreSet.setOnClickListener {
            val myDB = FirebaseFirestore.getInstance()
            val play = myDB.collection("play")

            // 1. 도큐먼트로 추가(존재하면 수정)
            play.document("song").set( mapOf(
                    "title"     to  "문서가 하나만 존재함",
                    "music_url" to  "music 입니다",
                    "pic_url"   to  "사진 입니다"

            ))

            // 2. 이름없이 추가
            var i = play.add(mapOf(
                    "title"     to  "title 입니다. - ${Date().time} "
            ))

            // 2. 추가 후, id 값을 치환( unique key 처리)
            i.addOnSuccessListener {
                it.set(mapOf(
                        "title"     to  "title 입니다. - ${Date().time} ",
                        "music_url" to  "music 입니다",
                        "pic_url"   to  "사진 입니다",
                        "id"        to  it.id)
                )

                WriteLn(it.id)
            }


        }

        // Firestore의 비동기처리를 좀 편하게 ...
        val sm = StateMachine()
        btnFireStoreGet.setOnClickListener {
            sm.doStart()
        }

        btnUploadImage.setOnClickListener {
            // FileStorage 저장하기
            FileUpload()
        }

    }

    // 비동기를 동기적으로 처리하기 위한 클래스
    inner class  StateMachine {
        val myDB = FirebaseFirestore.getInstance()
        val play = myDB.collection("play")

        // 순서대로 진행할 함수(메소드)테이블
        val funcTable = listOf(::step1, ::step2, ::step3)
        var nIndx     = 0

        // 3. get list limited
        fun step3() {
            play.orderBy("title").limit(2).get().addOnSuccessListener {
                WriteLn("step 3 >> 검색된 갯수는 -> ${it.size()}")
                it.forEach { item ->
                    WriteLn(item.get("title") as String)
                }
            }
        }

        // 2. get list with where
        fun step2() {
            play.whereEqualTo("title", "문서가 하나만 존재함")
                    .get().addOnSuccessListener {
                        WriteLn("step 2 >> 검색결과는 -> ${it.size()}")

                        nextAction()
                    }
        }

        // 1. size & list
        fun step1() {
            play.get().addOnSuccessListener {
                WriteLn("step 1 >> ${it.size()}")
                it.forEach { item ->
                    WriteLn(item.get("title") as String)
                }

                nextAction()
            }
        }


        fun doStart(){
            // 비동기를 순서대로 동기처럼 실행하기
            nextAction()
        }

        // List의 확장함수
        fun nextAction(){
            // 크기가 넘어가면 초기화
            nIndx = if( nIndx > funcTable.size -1) 0 else nIndx
            val p = funcTable.get(nIndx) as () -> Unit
            p()
            nIndx++
        }

    }

    override fun onStart() {
        super.onStart()
        val currentUser = mAuth!!.getCurrentUser()
        WriteLn("User 정보: $currentUser")
    }

    // 사용자인증
    fun LoginUserInfo(email : String, password : String){

        mAuth!!.signInWithEmailAndPassword (email, password)
                .addOnCompleteListener(this) { task ->
                    if (task.isSuccessful) {
                        // Sign in success, update UI with the signed-in user's information
                        val user = mAuth!!.getCurrentUser()
                        WriteLn( "$user Login!.")
                    } else {
                        WriteLn( "Login failed")
                    }
                }
    }

    // 사용자추가
    fun CreateUserInfo(email : String, password : String){
        // create가 안된다면.. <- password 길이가 6자이상 필수!!
        mAuth!!.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener(this) { task ->
                    if (task.isSuccessful) {
                        WriteLn("Create success")
                    } else {
                        WriteLn("Create failed")
                    }
                }
    }

    // file Upload
    fun FileUpload(){

        val storage = FirebaseStorage.getInstance()
        var storageRef = storage.reference

        var downUrl = ""

        // 언제나 절대경로명으로 만들어야 한다.
        var spaceRef = storageRef.child("images/space.jpg")

        fun Upload(){
            var uploading = spaceRef.putBytes(SaveImage())
            uploading.addOnFailureListener {

            }.addOnSuccessListener {
                WriteLn("Uploaded ")

                addImageWithLibrary(downUrl, { ctx, url, image ->
                    // Glide로 추가
                    Glide.with(ctx)
                            .load(url)
                            .fitCenter()
                            .into(image)
                })
            }
        }

        // 올라간 주소를 가져온다.
        spaceRef.downloadUrl.addOnSuccessListener {
            WriteLn(it.toString())
            downUrl = it.toString()
            Upload()
        }

    }

    // 함수형 프로그래밍 스타일
    private fun addImageWithLibrary(
            imgUrl: String, func: (Context, String, ImageView) -> Unit) {

        // 넘겨진 함수를 수행
        func(applicationContext, imgUrl, imgDownload)
    }

    // 2. TextClock 화면을 File로 저장하는 메소드 구현
    fun SaveImage(): ByteArray {

        clock.isDrawingCacheEnabled = true
        clock.buildDrawingCache(true)

        val b = Bitmap.createBitmap(clock.drawingCache)

        clock.isDrawingCacheEnabled = false
        clock.buildDrawingCache(false)

        var bs = ByteArrayOutputStream()
        b.compress(Bitmap.CompressFormat.PNG, 85, bs)
        return bs.toByteArray()
    }

    var nCount = 0
    fun Write(s : String ){
        val readString = txtMessage.text.toString()
        txtMessage.text = "${readString}${s}"
    }

    fun WriteLn(s : String ){
        Write("${nCount++}> ")
        Write( "$s\n" )
    }
}

'Source code or Tip > Android(Java, Kotlin)' 카테고리의 다른 글

[Android] appBook source  (0) 2020.07.20
JavaToKotlin  (0) 2020.07.18
[Android] Glide를 이용한 animated gif, webp 이용  (0) 2020.07.18
ConstraintLayout QuickStart  (0) 2020.07.16
AndroidX - DataBinding  (0) 2020.07.16
Comments