앱 개발중에는 간혹적으로 이미지 을 불러다가 사용해야 하는 경우들이 종종 발생한다. 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 을 활용하는 작업을 할 때에도 이미지 처리는 무난(?) 하게 할 수 있게 되었다.
'모바일 앱(안드로이드)' 카테고리의 다른 글
안드로이드 앱 만들기 bottomnavigationview 의 기능 구현 등등 (4) | 2021.10.16 |
---|---|
안드로이드 앱 만들기 Android Studio Update ... Bumblebee (0) | 2021.10.15 |
안드로이드 앱 개발 AdMob (애드몹) 정책 위반에 걸리다 (5) | 2021.10.09 |
안드로이드 앱 개발 하기 onestore 등록 안내 메일을 받다. (2) | 2021.10.08 |
안드로이드 개발 onestore 등록해 보기 2일차 검증요청 완료 하기 (2) | 2021.10.07 |