Demo
0. Firebase 와 Android studio 연동
1. Database 생성
firebase console 에서 create database 를 test 버전으로 Create 해준다.
storage, database rules를 체크한다. 여기서 read, write 제약을 걸 수 있다.
2. Dependencty 추가
android studio tools >> firebase >> database, storage 를 add하면 자동으로 추가된다.
implementation 'com.google.firebase:firebase-database:20.0.0'
implementation 'com.google.firebase:firebase-storage:20.0.0'
3. 데이터베이스에 쓰기, 메모리 데이터에서 업로드
- Database에 쓰기
databaseReference.setValue(data); // data는 따로 Dao 객체만드는게 좋을듯
- 업로드하기
- byte
- stream
- file
byte[]는 파일의 전체 콘텐츠를 메모리에 한 번에 담아서 보내주기때문에 메모리를 절약하려면 putStream()이나 putFile()을 사용하는게 좋다고 한다.
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 바이트 배열을 쓸 수 있는 스트림을 준비
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos); // 50%로 압축하여 jpeg 형식으로 스트림에 비트맵을 저장
byte[] finalimg = baos.toByteArray(); // 스트림을 바이트 배열로 변환
final StorageReference filePath; // 내부적으로 storage reference를 생성 << 파일의 전체 경로를 가리키는 참조
filePath = storageReference.child("Notice").child(finalimg + "jpg"); // notice/finalimg + "jpg"로 저장
final UploadTask uploadTask = filePath.putBytes(finalimg);
UploadNotice.java
package com.sjcoding.admincollegeapp;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.cardview.widget.CardView;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class UploadNotice extends AppCompatActivity {
private CardView addImage; // 이미지 업로드 버튼
private ImageView noticeImageView; // 가져온 사진 그릴 공간
private EditText noticeTitle;
private Button uploadNoticeButton; // notice 업로드 버튼
private final int REQ = 1000; // 응답
private ProgressDialog pd; // 다이알로그
private DatabaseReference databaseReference;
private StorageReference storageReference;
private String downloadUrl = "";
private Bitmap bitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upload_notice);
// 레퍼런스를 가져옴
databaseReference = FirebaseDatabase.getInstance().getReference();
storageReference = FirebaseStorage.getInstance().getReference();
pd = new ProgressDialog(this);
noticeImageView = (ImageView) findViewById(R.id.iv_notice);
noticeTitle = findViewById(R.id.notice_title);
// notice 업로드 버튼 클릭클릭!
uploadNoticeButton = findViewById(R.id.btn_upload_notice);
uploadNoticeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(noticeTitle.getText().toString().isEmpty()) {
noticeTitle.setError("제목은 필수사항입니다.");
noticeTitle.requestFocus();
}else if(bitmap == null) {
uploadData();
}else {
uploadImage();
}
}
});
// image 업로드 버튼 클릭클릭!
addImage = findViewById(R.id.add_image);
addImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openGallery();
}
});
}
// gallery 열기
private void openGallery() {
Intent pickImage = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickImage, REQ);
}
// 결과값 bitmap 변환해서 그려줌
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQ && resultCode == Activity.RESULT_OK) {
Uri uri = data.getData();
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
noticeImageView.setImageBitmap(bitmap);
}
}
// 이미지파일 업로드
private void uploadImage() {
pd.setMessage("Uploading...");
pd.show();
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 바이트 배열을 쓸 수 있는 스트림을 준비
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos); // 50%로 압축하여 jpeg 형식으로 스트림에 비트맵을 저장
byte[] finalimg = baos.toByteArray(); // 스트림을 바이트 배열로 변환
final StorageReference filePath; // 내부적으로 storage reference를 생성 << 파일의 전체 경로를 가리키는 참조
filePath = storageReference.child("Notice").child(finalimg + "jpg"); // notice/finalimg + "jpg"로 저장
final UploadTask uploadTask = filePath.putBytes(finalimg);
uploadTask.addOnCompleteListener(UploadNotice.this, new OnCompleteListener<UploadTask.TaskSnapshot>() {
@Override
public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
if(task.isSuccessful()) {
uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
filePath.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
downloadUrl = String.valueOf(uri);
uploadData(); // 최종 데이터 업로드
}
});
}
});
} else {
pd.dismiss();
Toast.makeText(UploadNotice.this, "Notice uploaded", Toast.LENGTH_SHORT).show();
}
}
});
}
// 최종 데이터 업로드
private void uploadData() {
// Notice 디렉토리 아래에 생성
databaseReference = databaseReference.child("Notice");
// 필드값 key
final String uniqueKey = databaseReference.push().getKey();
// 필드값 title
String title = noticeTitle.getText().toString();
// 필드값 date
Calendar calForDate = Calendar.getInstance();
SimpleDateFormat currentDate = new SimpleDateFormat("dd-MM-yy");
String date = currentDate.format(calForDate.getTime());
// 필드값 time
Calendar calForTime = Calendar.getInstance();
SimpleDateFormat currentTime = new SimpleDateFormat("hh:mm a");
String time = currentDate.format(calForDate.getTime());
NoticeData noticeData = new NoticeData(title, downloadUrl, date, time, uniqueKey);
databaseReference.child(uniqueKey).setValue(noticeData).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void unused) {
pd.dismiss();
Toast.makeText(UploadNotice.this, "Notice uploaded", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener(){
@Override
public void onFailure(@NonNull Exception e) {
pd.dismiss();
Toast.makeText(UploadNotice.this, "Something went wrong", Toast.LENGTH_SHORT).show();
}
});
}
}
activity_upload_notice.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".UploadNotice"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
android:layout_width="130dp"
android:layout_height="150dp"
android:layout_margin="10dp"
android:id="@+id/add_image"
app:cardElevation="5dp"
android:layout_gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:layout_width="64dp"
android:layout_height="64dp"
android:background='@drawable/circle_purple'
android:src="@drawable/ic_notice"
android:padding="15dp"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/lightGray"
android:layout_marginTop="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Image"
android:textStyle="bold"
android:padding="5dp"
android:layout_marginTop="10dp"
android:textColor="@color/textColor"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="16dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Notice title"
android:id="@+id/notice_title"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Upload Notice"
android:layout_marginTop="16dp"
android:textAllCaps="false"
android:id="@+id/btn_upload_notice"/>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="400dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:id="@+id/iv_notice"/>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>
Ref
'System Programming > Android' 카테고리의 다른 글
[Android/Firebase] Firebase CRUD (0) | 2021.07.03 |
---|---|
[Android/Firebase] Firebase Upload pdf (0) | 2021.07.01 |
[Android/Java] 갤러리 열고 그리기 MediaStore, bitmap (0) | 2021.06.29 |
[Android/Java] Fragment Bottom Navigation view (0) | 2021.06.28 |
[Android/Java] Fragment간 값 전달 (0) | 2021.06.28 |