이번 시간에는 이전에 이어서 연락처
등록하는 방법을 알아보겠습니다.
이전 포스팅을 먼저 보고 오시면 됩니다.
2022.03.02 - [안드로이드] - [안드로이드] SQLite RecyclerView 연락처 만드는 방법 part1 - 조회
- 설명 -
1. 사용자가 입력한 이름, 전화번호, 사진을 저장한다.
2. cv.put 를 통해서 저장할 값을 변수에 담는다.
/**
* 연락처 등록
* @param name //이름
* @param phone_number 전화번호
* @param phone_photo // 사진
*/
public void addPhoneNumber(String name, String phone_number, byte[] phone_photo){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME, name);
cv.put(COLUMN_PHONE_NUMBER, phone_number);
cv.put(COLUMN_PHONE_PHOTO, phone_photo);
long result = db.insert(TABLE_NAME, null, cv);
if(result == -1){
Toast.makeText(context, "Failed", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context, "Successfully", Toast.LENGTH_SHORT).show();
}
- 전체 코드 -
public class PhoneBookDB extends SQLiteOpenHelper {
private Context context;
public static final String DATABASE_NAME = "address.db";
public static final int DATABASE_VERSION = 1;
public static final String TABLE_NAME = "phone_info";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_NAME = "phone_name";
public static final String COLUMN_PHONE_NUMBER = "phone_number";
public static final String COLUMN_PHONE_PHOTO = "user_image";
public PhoneBookDB(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
String query = "CREATE TABLE " + TABLE_NAME +
" (" + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COLUMN_NAME + " TEXT, " +
COLUMN_PHONE_NUMBER + " TEXT, " +
COLUMN_PHONE_PHOTO + " BLOP);";
db.execSQL(query);
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
/**
* 연락처 전체 가져오기
* @return
*/
public Cursor readAllData(){
String query = "SELECT * FROM " + TABLE_NAME;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = null;
if(db != null){
cursor = db.rawQuery(query, null);
}
return cursor;
}
/**
* 연락처 등록
* @param name //이름
* @param phone_number 전화번호
* @param phone_photo // 사진
*/
public void addPhoneNumber(String name, String phone_number, byte[] phone_photo){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME, name);
cv.put(COLUMN_PHONE_NUMBER, phone_number);
cv.put(COLUMN_PHONE_PHOTO, phone_photo);
long result = db.insert(TABLE_NAME, null, cv);
if(result == -1){
Toast.makeText(context, "Failed", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context, "Successfully", Toast.LENGTH_SHORT).show();
}
}
}
app -> 마우스 오른쪽 -> New -> Activity -> Empty Activity
Activity Name: AddActivity
- 설명 -
1. 사진 보여줄 이미지뷰, 사진 찍기 기능 버튼, 사진 선택 기능 버튼
이름입력 에디트 텍스트, 전화번호 입력 에디트 텍스트, 저장 버튼으로
구성되어 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:gravity="center"
android:orientation="vertical"
tools:context=".AddActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="128dp"
android:layout_height="128dp"
android:scaleType="centerCrop"
android:src="@drawable/photo" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/picture_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="사진찍기" />
<Button
android:id="@+id/select_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="사진선택" />
</androidx.appcompat.widget.LinearLayoutCompat>
<EditText
android:id="@+id/add_name_edit"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:hint="이름"
android:inputType="text" />
<EditText
android:id="@+id/add_phone_edit"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:hint="전화번호"
android:maxLength="13"
android:inputType="phone" />
<Button
android:id="@+id/add_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="저장" />
</LinearLayout>
이미지 res -> drawable
- 설명 -
1. addTextChangedListener를 통해 전화번호 하이픈 처리를 한다.
2. ACTION_IMAGE_CAPTURE : 사진 찍기 위한 인텐트(Intent)
3. ACTION_PICK: 사진 가져오기위한 인텐트(Intent)
4. imageViewToByte: 이미지를 저장하기 위해서는 타입 변환을 해야 한다.
public class AddActivity extends AppCompatActivity {
Uri uri;
ImageView imageView;
EditText addNameEdit, addPhoneEdit;
Bitmap bitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add);
addNameEdit = findViewById(R.id.add_name_edit);
addPhoneEdit = findViewById(R.id.add_phone_edit);
imageView = findViewById(R.id.imageView);
//전화번호 하이픈(-) 자동입력
addPhoneEdit.addTextChangedListener(new PhoneNumberFormattingTextWatcher());
Button pictureBtn = findViewById(R.id.picture_btn); //사진찍기 버튼
Button selectBtn = findViewById(R.id.select_btn);//사진선택 버튼
//사진찍기
pictureBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
activityResultPicture.launch(intent);
}
});
//사진선택
selectBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
activityResultSelect.launch(intent);
}
});
//저장버튼
Button addBtn = findViewById(R.id.add_btn);
addBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//입력값 변수에 담기
String name = addNameEdit.getText().toString();
String phone = addPhoneEdit.getText().toString();
byte[] data = imageViewToByte(imageView);
//DB 객체 생성
PhoneBookDB addressDB = new PhoneBookDB(AddActivity.this);
//DB에 저장하기
addressDB.addPhoneNumber(name, phone, data);
}
});
}
//사진 찍기
ActivityResultLauncher<Intent> activityResultPicture = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if( result.getResultCode() == RESULT_OK && result.getData() != null){
Bundle extras = result.getData().getExtras();
bitmap = (Bitmap) extras.get("data");
imageView.setImageBitmap(bitmap);
}
}
});
//사진 가져오기
ActivityResultLauncher<Intent> activityResultSelect = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if( result.getResultCode() == RESULT_OK && result.getData() != null){
try {
uri = result.getData().getData();
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
imageView.setImageBitmap(bitmap);
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
}
}
});
/**
* 이미지 바이트로 변환
* @param image 이미지
* @return
*/
public static byte[] imageViewToByte(ImageView image) {
Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byteArray = stream.toByteArray();
return byteArray;
}
}
manifests -> AndroidManifest.xml
- 설명 -
1. 등록화면에서 메인화면으로 가기 위한 뒤로 가기 버튼 구현
<activity
android:name=".AddActivity"
android:exported="false"
android:parentActivityName=".MainActivity"
/>
build.gradle(Module:프로젝트명:app)
dependencies 괄호 안에 아래 코드를 넣어주시면 됩니다.
implementation 'com.google.android.material:material:1.4.0'
( res -> value -> themes)
<style name="Theme.MaterialExam" parent="Theme.MaterialComponents.Light.DarkActionBar">
- 설명 -
1. 등록 화면으로 가기 위한 등록버튼을 플로팅 액션 버튼으로 구현
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/add_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginEnd="16dp"
android:layout_marginBottom="20dp"
android:backgroundTint="@android:color/holo_green_dark"
app:tint="@android:color/white"
app:srcCompat="@drawable/ic_add" />
- 전체 코드 -
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recyclerView"/>
<TextView
android:id="@+id/noData_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No Data"
android:textSize="30sp"
android:layout_centerInParent="true"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/add_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginEnd="16dp"
android:layout_marginBottom="20dp"
android:backgroundTint="@android:color/holo_green_dark"
app:tint="@android:color/white"
app:srcCompat="@drawable/ic_add" />
</RelativeLayout>
아이콘 res -> drawable
- 설명 -
저장된 사진을 불러올때, 크기 때문에 오류가 발생하는 걸 방지하는 코드
//이미지 크기 오류 방지
try {
Field field = CursorWindow.class.getDeclaredField("sCursorWindowSize");
field.setAccessible(true);
field.set(null, 100 * 1024 * 1024); //the 100MB is the new size
} catch (Exception e) {
e.printStackTrace();
}
플로팅액션버튼 클릭 시에 등록 화면으로 이동하는 기능 구현
FloatingActionButton addBtn = findViewById(R.id.add_btn);
addBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//등록화면으로 이동
Intent intent = new Intent(MainActivity.this, AddActivity.class);
startActivity(intent);
}
});
- 전체 코드 -
public class MainActivity extends AppCompatActivity {
PhoneBookDB db;
ArrayList<PhoneBook> phoneList = new ArrayList<>();
RecyclerView recyclerView;
PhoneBookAdapter adapter;
TextView noDataText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//이미지 크기 오류 방지
try {
Field field = CursorWindow.class.getDeclaredField("sCursorWindowSize");
field.setAccessible(true);
field.set(null, 100 * 1024 * 1024); //the 100MB is the new size
} catch (Exception e) {
e.printStackTrace();
}
//데이터 유무 텍스트
noDataText = findViewById(R.id.noData_text);
//리스트 보여줄 화면
recyclerView = findViewById(R.id.recyclerView);
//어뎁터
adapter = new PhoneBookAdapter(MainActivity.this);
//어뎁터 등록
recyclerView.setAdapter(adapter);
//레이아웃 설정
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
//DB 생성성
db = new PhoneBookDB(MainActivity.this);
storeDataInArray();
FloatingActionButton addBtn = findViewById(R.id.add_btn);
addBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//등록화면으로 이동
Intent intent = new Intent(MainActivity.this, AddActivity.class);
startActivity(intent);
}
});
}
/**
* 데이터 가져오기
*/
void storeDataInArray(){
Cursor cursor = db.readAllData();
if(cursor.getCount() == 0){
noDataText.setVisibility(noDataText.VISIBLE);
}else{
noDataText.setVisibility(noDataText.GONE);
while(cursor.moveToNext()){
PhoneBook phone = new PhoneBook(cursor.getString(0),
cursor.getString(1),
cursor.getString(2),
cursor.getBlob(3));
//데이터 등록
phoneList.add(phone);
adapter.addItem(phone);
//적용
adapter.notifyDataSetChanged();
}
}
}
}
2022.03.01 - [안드로이드] - [안드로이드] 온보딩(Onboarding) 페이지 쉽게 만드는 방법
2022.03.01 - [안드로이드] - [안드로이드] 온보딩(Onboarding) 페이지 쉽게 만드는 방법
[안드로이드] SQLite RecyclerView 연락처 만드는 방법 part4 - 수정 (0) | 2022.03.05 |
---|---|
[안드로이드] SQLite RecyclerView 연락처 만드는 방법 part3 - 상세 (0) | 2022.03.04 |
[안드로이드] SQLite RecyclerView 연락처 만드는 방법 part1 - 조회 (2) | 2022.03.02 |
[안드로이드] 온보딩(Onboarding) 페이지 쉽게 만드는 방법 (0) | 2022.03.01 |
[안드로이드] 알림(Alerter) 쉽게 만드는 방법 (0) | 2022.02.28 |
댓글 영역