아직 게시판 이미지 업로드부분은 하지 않았기때문에 지금 해볼것이다
이미지 업로드를 하기위해서는 권한추가를 해줘야되기때문에 메니페스트로 이동해서 아래 코드를 추가해준다
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
AndroidManifest.xml
+ 이미지를 클릭시 갤러리로 이동할수있게했고, 갤러리에서 데이터를 받아와서 받아온 데이터가 + 이미지쪽에 표시되도록 코드를 짜주었다
// imageArea 클릭시
binding.imageArea.setOnClickListener {
// 갤러리로 이동
val gallery = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI)
startActivityForResult(gallery, 100)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// 갤러리에서 데이터 받아오기
if(resultCode == RESULT_OK && requestCode == 100){
// 받아온 데이터를 레이아웃에 표시(갤러리 데이터가 imageArea에 표시)
binding.imageArea.setImageURI(data?.data)
}
BoardWriteActivity.kt
여기까지하면 아래와같이 갤러리에서 이미지를 클릭하면 이미지가 잘 나오는을 확인할수있다
이제 이 이미지를 파이어베이스에 저장하는 작업을 할것이다
파이어베이스 이미지 업로드를 시켜주기위해서 storage를 활성화시켜준뒤 로그인한 경우에만 읽고 쓰기가 가능하도록 아래와같이 규칙을 수정해준다
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
firebase storage 공식문서를 참고해서 build에 아래 두줄의 코드를 추가해주고, BoardWriteActivity로 이동해서 storage를 선언해준다
dependencies {
implementation(platform("com.google.firebase:firebase-bom:32.7.1"))
implementation("com.google.firebase:firebase-storage")
}
build.gradle(app)
firebase storage 공식문서를 참고해서 imageUpload()함수를 생성해서 이미지 업로드 함수를 작성해준다
그리고 이미지 이름을 게시글의 키값으로 정할것이다
그러기 위해서는 키값이 필요한데, 키값은 게시글이 생성될때 생성된다. 따라서 게시글이 생성되기전에 아래 코드를 통해서 키값을 받아온다
// 키값 받아오기
val key = FBRef.boardRef.push().key.toString()
// 데이터 집어넣기
FBRef.boardRef
.child(key)
.setValue(BoardModel(title,content,uid,time))
이렇게 가져온 키값을 토대로 이미지 이름을 지정해준다
전체 코드이다
package com.example.mysololife.board
class BoardWriteActivity : AppCompatActivity() {
private lateinit var binding : ActivityBoardWriteBinding
private val TAG = BoardWriteActivity::class.java.simpleName
val storage = Firebase.storage
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_board_write)
binding.writeBtn.setOnClickListener {
// titleArea,contentArea 값을 받아옴
val title = binding.titleArea.text.toString()
val content = binding.contentArea.text.toString()
// uid값 가져오기
val uid = FBAuth.getUid()
// tiem값 가져오기
val time = FBAuth.getTime()
Log.d(TAG, title)
Log.d(TAG, content)
// 키값 받아오기 (키값 알아내기)
val key = FBRef.boardRef.push().key.toString()
// 데이터 집어넣기
FBRef.boardRef
.child(key)
.setValue(BoardModel(title,content,uid,time))
Toast.makeText(this, "게시글 입력완료", Toast.LENGTH_SHORT).show()
// 이미지 업로드(키값을 기준으로)
imageUpload(key)
// 엑티비티 사라짐
finish()
}
// imageArea 클릭시
binding.imageArea.setOnClickListener {
// 갤러리로 이동
val gallery = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI)
startActivityForResult(gallery, 100)
}
}
// 이미지 업로드 함수
private fun imageUpload(key :String){
val storageRef = storage.reference
val mountainsRef = storageRef.child(key + ".png")
val imageView = binding.imageArea
imageView.isDrawingCacheEnabled = true
imageView.buildDrawingCache()
val bitmap = (imageView.drawable as BitmapDrawable).bitmap
val baos = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val data = baos.toByteArray()
var uploadTask = mountainsRef.putBytes(data)
uploadTask.addOnFailureListener {
// Handle unsuccessful uploads
}.addOnSuccessListener { taskSnapshot ->
// taskSnapshot.metadata contains file metadata such as size, content-type, etc.
// ...
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// 갤러리에서 데이터 받아오기
if(resultCode == RESULT_OK && requestCode == 100){
// 받아온 데이터를 레이아웃에 표시(갤러리 데이터가 imageArea에 표시)
binding.imageArea.setImageURI(data?.data)
}
}
}
BoardWriteActivity.kt
여기까지하고 앱을 실행해 게시물을 작성한뒤 파이어베이스를 확인해보면 이미지의 이름이 key값으로 잘 들어가있는걸 확인할수있다
이제 게시글을 클릭했을때 나타나는 화면에 업로드한 이미지가 보여지도록 해볼것이다
파이어베이스 공식문서 "파일 다운로드" 부분을 참고해서 코드를 작성해준다
build.gradle(app)에 아래와 같은 코드를 추가해준다
dependencies {
implementation 'com.firebaseui:firebase-ui-storage:7.2.0'
}
build.gradle(app)
또 파이어베이스 공식문서를 참고해서 getImageData()라는 함수를 생성해준뒤 이미지 다운로드하는 코드를 작성해준다
여기서 child라고 경로설정을해서 key값을 가져왔다(이미지를 가져왔다)
아래와 같이 이미지를 받아오는 코드를 써준다
package com.example.mysololife.board
class BoardInsideActivity : AppCompatActivity() {
private val TAG = BoardInsideActivity::class.java.simpleName
private lateinit var binding : ActivityBoardInsideBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this,R.layout.activity_board_inside )
// TalkFragment에서 보낸 key데이터 받아오기
val key = intent.getStringExtra("key")
getBoardData(key.toString())
getImageData(key.toString())
}
// 이미지 다운로드 함수(게시글 작성한 이미지 클릭했을때 보이게)
private fun getImageData(key : String){
// Reference to an image file in Cloud Storage
val storageReference = Firebase.storage.reference.child(key + ".png")
// ImageView in your Activity
val imageViewFromFB = binding.getImageArea
storageReference.downloadUrl.addOnCompleteListener (OnCompleteListener { task ->
// 이미지 업로드 성공
if(task.isSuccessful){
// Glide를 사용하여 task에서 이미지 직접 다운로드
Glide.with(this)
.load(task.result)
.into(imageViewFromFB)
// 이미지 업로드 실패
}else{
}
})
}
...
}
BoardInsideActivity.kt
이렇게 코드를 써주면 게시글을 클릭했을때 내가 업로드한 이미지가 잘 보여지는 것을 확인할수있다
근데 여기서 문제가있는데 이미지를 업로드하지 않은 게시물은 이미지가 검정색으로 표시가 된다는 것이다
아래와 같이 이렇게 사진이 검정색으로 표시가 된다
이미지를 업로드하지 않았는데 무조건 코드가 실행이되서 업로드가 되기때문에 발생하는 문제이다
즉, 이미지를 업로드하지 않았는데도 BoardWriteActivity에 있는 이미지 업로드 함수가 무조건 실행이 되는것이다
그래서 +이미지버튼을 클릭을 했으면 이미지 업로드를 해주고, 클릭을 하지 않았다면 이미지 업로드를 하지 않는 방식으로 코드를 짜줄것이다.
package com.example.mysololife.board
class BoardWriteActivity : AppCompatActivity() {
private lateinit var binding : ActivityBoardWriteBinding
private val TAG = BoardWriteActivity::class.java.simpleName
val storage = Firebase.storage
// 이미지 업로드 노
private var isImageUploade = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_board_write)
binding.writeBtn.setOnClickListener {
// titleArea,contentArea 값을 받아옴
val title = binding.titleArea.text.toString()
val content = binding.contentArea.text.toString()
// uid값 가져오기
val uid = FBAuth.getUid()
// tiem값 가져오기
val time = FBAuth.getTime()
Log.d(TAG, title)
Log.d(TAG, content)
// 키값 받아오기 (키값 알아내기)
val key = FBRef.boardRef.push().key.toString()
// 데이터 집어넣기
FBRef.boardRef
.child(key)
.setValue(BoardModel(title,content,uid,time))
Toast.makeText(this, "게시글 입력완료", Toast.LENGTH_SHORT).show(
if (isImageUploade == true){
// 이미지 업로드(키값을 기준으로)
imageUpload(key)
}
// 엑티비티 사라짐
finish()
}
// imageArea 클릭시
binding.imageArea.setOnClickListener {
// 갤러리로 이동
val gallery = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI)
startActivityForResult(gallery, 100)
isImageUploade = true
}
}
// 이미지 업로드 함수
private fun imageUpload(key :String){
val storageRef = storage.reference
val mountainsRef = storageRef.child(key + ".png")
val imageView = binding.imageArea
imageView.isDrawingCacheEnabled = true
imageView.buildDrawingCache()
val bitmap = (imageView.drawable as BitmapDrawable).bitmap
val baos = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val data = baos.toByteArray()
var uploadTask = mountainsRef.putBytes(data)
uploadTask.addOnFailureListener {
// Handle unsuccessful uploads
}.addOnSuccessListener { taskSnapshot ->
// taskSnapshot.metadata contains file metadata such as size, content-type, etc.
// ...
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// 갤러리에서 데이터 받아오기
if(resultCode == RESULT_OK && requestCode == 100){
// 받아온 데이터를 레이아웃에 표시(갤러리 데이터가 imageArea에 표시)
binding.imageArea.setImageURI(data?.data)
}
}
}
BoardWirteActivity.kt
이렇게 해주면 이미지 업로드를 안해도 검정이미지가 안나오는것을 알수있다
근데 지금 이 방식은 클릭하면 무조건 이미지를 업로드를 하는 아주 단순한 방식이다.
클릭은 했지만 이미지 업로드를 안할수도 있기때문에 좋은방법은 아닌것같다
좀더 좋은방식은 아래와같은 순서로하는것이라고 볼수있을것이다
1. 현재 이미지의 이름을 가져온다
2. 이미지 업로드 버튼을 눌렀을 때, 기본 이미지(플러스버튼 모양)와 이름이 같은지 비교
3. 만약 같다면 이미지 업로드하지않고, 같지 않으면 업로드한다
* 현재 이미지 이름 가져오는거 참고링크 ( https://www.google.com/search?q=android+imageview+get+resource+name&rlz=1C5CHFA_enKR943KR943&oq=android+imageview+get+resource+name&aqs=chrome..69i57j0i8i30j69i60.325j0j7&sourceid=chrome&ie=UTF-8 )
(https://stackoverflow.com/questions/31651209/how-to-get-the-image-name-of-the-imageview-in-android)
이 방식으로 시도를해서 따로 포스팅을 해봐야겠다
'Android Project' 카테고리의 다른 글
[Android/Kotlin] 커뮤니티앱(11) - 로그아웃 (0) | 2024.01.28 |
---|---|
[Android/Kotlin] 커뮤니티앱(10) - 게시글 삭제, 수정 (0) | 2024.01.28 |
[Android/Kotlin] 커뮤니티앱(8) - 게시글 클릭 (0) | 2024.01.28 |
[Android/Kotlin] 커뮤니티앱(7) - 게시글 만들기 (0) | 2024.01.28 |
[Android/Kotlin] 커뮤니티앱(6) - 북마크탭 만들기 (0) | 2024.01.28 |