on
안드로이드 앱 개발 하기 firebase 에 이미지를 저장해 보자...
안드로이드 앱 개발 하기 firebase 에 이미지를 저장해 보자...
반응형
앱 개발중에는 간혹적으로 이미지 을 불러다가 사용해야 하는 경우들이 종종 발생한다. SQLite 을 이용할 때는 이미지를 byte 형태로 변환한 다음 저장하는 방식으로 이미지를 저장하고 불러오는 기능을 구현 했다.
public long insertDayinfo(String mDate, String msg, byte[] image) { long _id = -1 ; ContentValues values = new ContentValues() ; values.put("mdate", mDate); values.put("msg", msg) ; values.put("image", image); _id = db.insert(tableName, null, values) ; Log.i(TAG, "insert " + _id + " " + image.toString()) ; return _id ; } public byte[] getByteArrayFromBitmap(Bitmap d) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); d.compress(Bitmap.CompressFormat.PNG, 100, stream); return stream.toByteArray() ; } public Bitmap getAppBitmap(byte[] b) { return BitmapFactory.decodeByteArray(b, 0, b.length); }
이미지를 불러와서 SQLite 에 insert 을 할 때 위의 함수를 호출하는 방식으로 insert 을 하는 것이였다.
Bundle bundle = data.getExtras(); assert bundle != null; Bitmap test = bundle.getParcelable("data"); binding.imageView2.setImageBitmap(test); dbHandler = DBHandler.open(CalendarView.this); long lId = dbHandler.insertDayinfo(StringUtil.getDateString(pDate), "", dbHandler.getByteArrayFromBitmap(test)); if (lId > -1) { Toast.makeText(getApplicationContext(), "저장이 되었습니다.", Toast.LENGTH_LONG).show(); } dbHandler.close();
이런식의 호출이 되었지 않을까 싶다.
그럼 이번에는 firebase의 realtime database 을 사용하면서 경험한 부분에 대해서 이야기를 해 보자. 쉽게 생각해서 위의 예시와 같이 imageview 에 들어 있는 것을 byte[] 형식으로 변환한 다음 저장을 하면 되리라... 실제 코딩도 그렇게 해 보았더니...아니나 다를까 오류가 발생했다... 지금의 소스는 수정이 되어 버린 상황이라... 발생했던 오류 코드만 찾아 보겠다.
com.google.firebase.database.DatabaseException: Serializing Arrays is not supported, please use Lists instead ...
firebase 는 Serializing arrays 을 지원하지 않는단다... 그래서 Lists 로 구현을 하라는... 처음에는 이게 뭔 소리인가 하는 생각으로 구굴링을 해 보았는데, 결국 byte 뿐만 아니라 array 형태의 데이터 형식은 지원을 하지 않는다는 것을 알게 되었다...
그래서 다음과 같은 data 구조체를 선언하였다.
import com.billcoreatech.dailylike1010.utils.StringUtil; import java.util.ArrayList; import java.util.Arrays; public class MemberBean { String memberId; String name ; ... String subscriptionDate ; String withdrawalDate ; String imgMyInfo ; // 사진 이미지 public void setImgMyInfo(String imgMyInfo) { this.imgMyInfo = imgMyInfo; } public String getImgMyInfo() { return this.imgMyInfo ; } .... public String getUserType() { return userType; } }
뭐 그냥 쉬운 string 으로만 구현 했다... 그럼 이제 화면의 이미지는 어떻게 저장을 할 것인가 ?
앱에 imageview 을 넣고 그안에 그림이 들어가는 activity을 구현하고 폰에서 저장된 이미지를 가져오고
그것을 저장하기 위해서
이제 어떻게 ?
/** * byte[] 을 string 으로 * @param b * @return */ public static String byteArrayToBinaryString(byte[] b) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < b.length; ++i) { sb.append(byteToBinaryString(b[i])); } return sb.toString(); } public static String byteToBinaryString(byte n) { StringBuilder sb = new StringBuilder("00000000"); for (int bit = 0; bit < 8; bit++) { if (((n >> bit) & 1) > 0) { sb.setCharAt(7 - bit, '1'); } } return sb.toString(); } /** * string 을 byte[] 로 * @param s * @return */ public static byte[] binaryStringToByteArray(String s) { int count = s.length() / 8; byte[] b = new byte[count]; for (int i = 1; i < count; ++i) { String t = s.substring((i - 1) * 8, i * 8); b[i - 1] = binaryStringToByte(t); } return b; } public static byte binaryStringToByte(String s) { byte ret = 0, total = 0; for (int i = 0; i < 8; ++i) { ret = (s.charAt(7 - i) == '1') ? (byte) (1 << i) : 0; total = (byte) (ret | total); } return total; } /** * drawable to string * @param image * @return */ public static String drawableToString(Drawable image) { Bitmap bitmap = ((BitmapDrawable) image).getBitmap(); ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); byte[] reviewImage = stream.toByteArray(); return byteArrayToBinaryString(reviewImage); } /** * drawable to string * @param imgMyInfo * @return */ public static Drawable stringToDrawable(String imgMyInfo) { byte[] bData = binaryStringToByteArray(imgMyInfo); ByteArrayInputStream is = new ByteArrayInputStream(bData); return Drawable.createFromStream(is, "reviewImage"); }
이런 몇가지 함수를 class 에 넣었다... 그것 중에서 활용하는 방식은 다음과 같다.
옆을 들어 위에 함수들이 들어있는 class 가 StringUtil.java 라고 한다면 ...
memberDb.orderByChild("emailAddress").equalTo(mUser.getEmail()).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { for(DataSnapshot ds : snapshot.getChildren()) { mMemberBean = ds.getValue(MemberBean.class); if (mMemberBean != null) { binding.txtEmail.setText(mMemberBean.getEmailAddress()); ... if (mMemberBean.getImgMyInfo() == null) { binding.imgMyinfo.setImageResource(R.drawable.image_512); } else { // 불러온 이미지를 화면의 이미지뷰에 넣기... binding.imgMyinfo.setImageDrawable(StringUtil.stringToDrawable(mMemberBean.getImgMyInfo())); } } } } @Override public void onCancelled(@NonNull DatabaseError error) { } }); ... Bundle bundle = data.getExtras(); assert bundle != null; Bitmap test = bundle.getParcelable("data"); binding.imgMyinfo.setImageBitmap(test); // 이미지뷰에서 이미지를 읽어와서 저장하기 위한 변수에 넣기 mMemberBean.setImgMyInfo(StringUtil.drawableToString(binding.imgMyinfo.getDrawable()));
작업한 소스의 일부만 켭쳐한 것이기는 하지만, 함수 하나로 쓩~ 이미지를 변수에 넣고 뺴고가 가능해 진다.
그럼 실제 화면에는
이렇게 보이게 될 것이고.
firebase 의 데이터에는 어떻게 ?
imgMyInfo 란 변수에는 1과 0으로 구성된 숫자만 가득....
이렇게 해서 firebase 의 realtime database 을 활용하는 작업을 할 때에도 이미지 처리는 무난(?) 하게 할 수 있게 되었다.
반응형
from http://billcorea.tistory.com/75 by ccl(A) rewrite - 2021-10-15 00:01:14