Android Studio 상에서 코드 구현 작업을 하던 것을 집과 사무실에서 하다보면 코드를 변경한 것이 어떤 것이 최종인지 헷갈리는 경우가 생긴다.


이럴 경우에는 코드를 육안으로 일일이 비교한다는 건 정말 힘들다.

그렇다고 날짜로만 최신날짜로 덮어쓴다(?)는 것은 정말 위함한 생각이다.


내가 사용하는 방법은 AcroEdit 를 설치하면 포함되어 있는 AcroDiff.exe 파일을 이용한다.


더 좋은 파일 내용비교 프로그램이 있을 수도 있지만, 몇개의 프로그램을 사용해본 결과 이것이 최고로 편하더라.

AcroDiff.exe

첨부된 이 파일만 받아서 이걸 실행하고 파일을 마우스로 Drag & Drop 하여 비교하면 된다.



Total Commander 로 양쪽 파일을 선택하여 마우스로 끌어다가 AcroDiff.exe 파일에 Drop 한다.

화면상에 보면 노란색으로 표시된 부분이 보인다. 명칭을 변경하여 서로 다른 걸 알 수 있다.

달라진 부분을 Android Studio  상에서 Shift + F6 를 눌러서 명칭을 변경해준다.

이렇게 해야만 코드상에서 달라진 명칭을 한번에 모두 변경할 수 있다.

그런 다음 위 그림 1번을 다시 누르면 서로 100% 일치한다고 나오면 양쪽 코드는 동일하다는 결과다.


구글링이나 블로그에서 찾은 코드를 붙여넣기, 프로젝트 읽어오기 등을 하다보면 본인이 원하는 명칭과 다르면 코드 분석이나 작업하는데 불편해서 Android Studio 에서 Shift + F6 으로 명칭을 일괄 변경하면 매우 편하더라.


집과 사무실에서 작업한 코드가 다를 수도 있을 경우에는 이런 방법으로 하면 되지만...

집에서 작업하던 걸 사무실에 가서 작업을 한다고 할 경우에는

src 폴더 밑에 main 폴더만 복사해서 사무실 노트북에 덮어쓰기 또는 사무실 해당 main 폴더를 삭제하고 복사하기를 하면 바로 인식한다.


이렇게 하는 것은 Android Studio 환경이 서로 거의 유사하다는 조건에서 가능하다.

gradle 설정 정보 등은 동일하므로 굳이 Project 내 모든 폴더 파일을 다 옮길 필요가 없더라.

간단하게 핵심이 되는 main 폴더만 복사하면 된다.



728x90
블로그 이미지

Link2Me

,

Android Studio 에서 폴더를 정리하는 방법이다.

코드를 이것 저것 추가하다보니 한 폴더에 너무 많은 내용이 있어서 내용 열람이 깔끔하지 않다.

그래서 새로운 폴더 common 을 윈도우 폴더 만들기에서 생성하고 나서 java 코드를 옮기는 작업을 했다.


옮기고자 하는 파일을 선택한 다음, 마우스로 common 폴더로 Drag & Drop 을 한다.



4번을 누르면.....


파일이 옮겨진 것을 확인할 수 있다.

파일내 package 경로명은 자동으로 변경된다.


마우스 Drag & Drop 으로 옮길 수 있어서 너무 편하고 좋다.


728x90
블로그 이미지

Link2Me

,

Android Studio 에서 모듈 삭제 방법이다.




모듈 삭제해서 화면에서는 안보이지만 실제 폴더에 가면 파일명은 그대로 있다.

즉 연결된 정보만 삭제되었을 뿐이라는 거다.

불필요하면 위 과정후에 실제 파일 경로를 직접 삭제처리 한다.

728x90
블로그 이미지

Link2Me

,

C:/Users/(계정 이름) 폴더에 들어가보면 .AndroidStudio라는 폴더가 보인다.

이 폴더를 변경하는 방법이다.


EditPlus 를 이용해서 아래 그림 파일을 연다.


아래와 같이 되어 있는 곳을 수정한다.


옮기고자 하는 폴더 경로를 적어준다.


728x90
블로그 이미지

Link2Me

,

Android Studio gradle 경로 변경 방법이다.



변경하고 싶은 폴더명을 적어주고 OK를 누르면 된다.



728x90
블로그 이미지

Link2Me

,

AVD configuration folder (.android) 설치경로가 C 드라이브 사용자 환경에 저장된다.

이 폴더에 Emulator 가 설치되는데 C 드라이드 용량을 엄청 많이 점유한다.

따라서 이 폴더를 다른 하드디스크로 옮겨야 한다. C 드라이브 용량이 절대적으로 부족하기 때문이다.

노트북 SSD를 교체하려고 뜯어보니까 일반 SSD 가 아니더라. 그래서 포기하고 F 드라이브(용량 500GB HDD)로 옮기기로 했다. Android Studio 및 sdk 는 이미 옮겨서 설치한 상태인데 환경설정에 대한 용량도 커서 C드라이 공간 확보가 절대적으로 필요하다.


옮기는 방법은

C 드라이드 User 환경에 있는 .android folder를 옮기고자 하는 드라이드(ex, D 드라이드, F드라이브 등)로 복사하거나 이동시킨다.

이동을 시킬 경우에는 Android Studio 가 실행되지 않는 상태에서 하는게 좋다.

F:\Android\AndroidStudio_config 로 옮겼다.



다음에 할 일은 default 경로를 변경해야 한다.

윈도우 설정 아이콘을 누른다.


설정화면에서 system 을 입력한다.


고급 시스템 설정보기를 클릭한다.


고급 탭에서 환경변수를 클릭한다.



윈도우 폴더에서 .android 를 옮긴 폴더명이 있는 곳에서 마우스 우클릭하여 주소 복사를 한다.


변수이름에 ANDROID_SDK_HOME 을 입력하고 변수 값에는 복사한 경로를 붙여넣기 한다.

여기까지 하고 확인버튼 누르고 다시 확인 버튼을 누르면 끝이다.


이제 제대로 변경된 것인지 확인해보자.

AVD Manager.exe 파일을 실행하면...


2번과 같이 경로가 변경된 것을 확인할 수 있다.


728x90
블로그 이미지

Link2Me

,

안드로이드 연락처(Contacts) 에 있는 데이터를 메모리로 읽어오기 위한 방법은 ArrayList 를 여러개 선언하는 방법도 있지만, Contact_Item 클래스를 만들고 HashTable 를 사용해서 메모리에 저장하는 방법이 좋다.


Contacts_Item 클래스를 정의하는 방법은 http://link2me.tistory.com/1251 게시글을 참조하면 된다.

여기서는 결과를 적는다.

단순하게 연락처에 있는 데이터를 가져오는 클래스가 아니라 서버에 있는 데이터를 연락처에 내려받아 저장한 데이터를 가져오기 위한 것이라 형태가 다른 contactKey 를 추가했다.


 public class Contacts_Item {   
    String contactId; // 연락처(Contacts) Contact_ID 로 데이터 수정/삭제 키 값
    String contactName; // 연락처 표시이름
    String contactmobileNO; // 연락처 휴대폰번호
    String contactofficeNO; // 연락처 사무실번호
    String contactKey; // 서버와의 데이터 동기화를 위한 키

    public Contacts_Item() {
    }

    public Contacts_Item(String contactId, String contactName, String contactmobileNO, String contactofficeNO, String contactKey) {
        this.contactId = contactId;
        this.contactName = contactName;
        this.contactmobileNO = contactmobileNO;
        this.contactofficeNO = contactofficeNO;
        this.contactKey = contactKey;
    }

    public String getContactId() {
        return contactId;
    }

    public void setContactId(String contactId) {
        this.contactId = contactId;
    }

    public String getContactName() {
        return contactName;
    }

    public void setContactName(String contactName) {
        this.contactName = contactName;
    }

    public String getContactmobileNO() {
        return contactmobileNO;
    }

    public void setContactmobileNO(String contactmobileNO) {
        this.contactmobileNO = contactmobileNO;
    }

    public String getContactofficeNO() {
        return contactofficeNO;
    }

    public void setContactofficeNO(String contactofficeNO) {
        this.contactofficeNO = contactofficeNO;
    }

    public String getContactKey() {
        return contactKey;
    }

    public void setContactKey(String contactKey) {
        this.contactKey = contactKey;
    }
}


연락처 Hashtable 를 선언, 등록, 사용하는 방법이다.

HashMap 에 대한 기본 개념은 http://link2me.tistory.com/1210 참조하면 된다.


선언

HashMap<String, Contacts_Item> contactMap = new HashMap<String, Contacts_Item>();


등록

temp_ID 와 temp_keyIDX 는 개념 설명이므로 실 코드는 기록하지 않는다.

Contacts_Item item = new Contacts_Item(); 객체를 생성하고 데이터를 저장한 다음, 선언한 HashMap 에 저정한다. contactMap.put(temp_key, item);


public void Contacts2ArrayList() {
    contactMap.clear(); // 메모리 초기화
    Cursor cursor = ContactHelper.LoadContactsCursor(context.getContentResolver(), search_name);
    cursor.moveToFirst();
    System.out.println("연락처 개수 = " + cursor.getCount());
    while (!cursor.isAfterLast()) {
        String ContactId = cursor.getString(0);
        String temp_key = "";
        if (temp_ID.indexOf(ContactId) > -1) {
            temp_key = temp_keyIDX.get(temp_ID.indexOf(ContactId));
        }
        if (!temp_key.equals("")) { // if 문은 상황에 따라 사용여부 결정하면 된다.
            Contacts_Item item = new Contacts_Item();
            item.setContactId(ContactId);
            item.setContactName(cursor.getString(1));
            item.setContactmobileNO(cursor.getString(2));
            item.setContactofficeNO(cursor.getString(3));
            item.setContactKey(temp_key);
            contactMap.put(temp_key, item);
        }
        cursor.moveToNext();
    }
    cursor.close();
}


검색

if (contactMap.containsKey(idx)) {
    Contacts_Item item = contactMap.get(idx);
    String contactName = item.getContactName();
    String contactId = item.getContactId();
    String contactmNO = item.getContactmobileNO();
    String contactoNO = item.getContactofficeNO();

   

    // 실제 처리할 메소드 추가하면 된다.

}


728x90
블로그 이미지

Link2Me

,

안드로이드 연락처(Contacts)를 추가시 사진 이미지를 다운로드 하는 메소드를 추가했다.

안드로이드에서 이미지를 다루기 위한 객체로 Bitmap을 많이 사용한다.
실질적으로 파일을 저장할 때 jpeg을 많이 사용하므로 관련 코드를 고려했다.


 public class ContactHelper {
    // 신규 추가(성명, 휴대폰번호, 사무실번호, 이메일, 사진, IDX, groupId)
    public static void insertPhoneContacts(Context context, String display_name, String mobileNO, String officeNO,
            String strEmail, String strPhoto, String strIDX, long groupId) {

        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        ContentProviderOperation.Builder op = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null);
        ops.add(op.build());

        // DISPLAY NAME(성명)
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, display_name);
        ops.add(op.build());

        // 그룹 세팅
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID, groupId);
        ops.add(op.build());

        // 휴대폰 번호
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, mobileNO)
                .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, strIDX)
                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
        ops.add(op.build());

        // 사무실 번호
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, officeNO)
                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_WORK);

        op.withYieldAllowed(true);
        ops.add(op.build());

        // EMAIL
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Email.DATA, strEmail)
                .withValue(ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.TYPE_WORK);
        ops.add(op.build());

        // Photo Image
        Bitmap cachedImage = DownloadImageFromPath(strPhoto);
        if (cachedImage != null) {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            cachedImage.compress(CompressFormat.JPEG, 100, out);

            byte[] b = out.toByteArray();

            op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                    .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.Photo.DATA15, b);
            ops.add(op.build());

        }

        try {
            context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (OperationApplicationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            Log.e("ContactsAdder", "Exceptoin encoutered while inserting contact: " + e);
        }

    }

    // 이미지 다운로드
    private static Bitmap DownloadImageFromPath(String path) {
        InputStream instream = null;
        Bitmap image = null;
        int responseCode = -1;
        try {

            URL url = new URL(path); // "http://192.168.xx.xx/imagepath/img1.jpg
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoInput(true);
            conn.connect();
            responseCode = conn.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // download
                instream = conn.getInputStream();
                image = BitmapFactory.decodeStream(instream);
                instream.close();
            }

        } catch (Exception ex) {
            Log.e("Exception", ex.toString());
        }
        return image;
    }
   
}


이미지 크기와 높이를 조정하는 코드는 https://stackoverflow.com/questions/18210700/best-method-to-download-image-from-url-in-android 참조하면 된다.

728x90
블로그 이미지

Link2Me

,

안드로이드 연락처에 그룹명을 생성하고, 그룹에 인원을 추가하는 코드다.


사용법

String group_name ="그룹명";
long groupId = ContactHelper.getGroupId(getContentResolver(), group_name);
if(groupId == 0){ // 해당 그룹이 없으면 추가
    ContactHelper.createNewGroup(getContentResolver(), group_name);

    groupId = ContactHelper.getGroupId(getContentResolver(), group_name);

}
long rawId = ContactHelper.getrawIdFromContactId(getContentResolver(),30255);

// 그룹에 인원 추가
ContactHelper.addContactToGroup(getContentResolver(),rawId,groupId);

※ 이 코드를 계속 실행하면 데이터가 계속 추가되는 현상이 있는데 해결 코드를 추가로 구현해야 할 거 같다.


//****************** Contact Group ***************************/
// 그룹에 인원 추가하기
public static boolean addContactToGroup(ContentResolver contactHelper,long rawId, long groupId) {
    try {
        ContentValues values = new ContentValues();
        values.put(RawContacts.Data.RAW_CONTACT_ID, rawId);
        values.put(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID, groupId);
        values.put(RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE);
        contactHelper.insert(ContactsContract.Data.CONTENT_URI, values);
        return true;
    } catch (Exception e){
        e.printStackTrace();
    }
    return false;
}

// 그룹 ID 조회
public static long getGroupId(ContentResolver contactHelper, String group_name) {
    long group_id = 0;

    Uri contactUri = ContactsContract.Groups.CONTENT_URI;
    String[] projection = {ContactsContract.Groups._ID};
    String where = ContactsContract.Groups.TITLE + " = ?";
    String[] whereParams = {group_name};

    Cursor cursor = contactHelper.query(contactUri, projection, where, whereParams, null);
    if (cursor.moveToFirst()) {
        do {
            group_id = cursor.getLong(0);
            Log.e("title", group_name);
            Log.e("id", Long.toString(group_id));
        } while (cursor.moveToNext());
    }

    return group_id;
}

// 그룹 추가
public static void createNewGroup(ContentResolver contactHelper, String group_name) {
    ContentValues cv = new ContentValues();
    cv.put(ContactsContract.Groups.TITLE, group_name);
    cv.put(ContactsContract.Groups.DELETED, 0);
    cv.put(ContactsContract.Groups.SHOULD_SYNC, true);
    cv.put(ContactsContract.Groups.GROUP_VISIBLE, 1);
    contactHelper.insert(ContactsContract.Groups.CONTENT_URI, cv);
}

// 그룹명 수정
public static void updateGroup(ContentResolver contactHelper, String name, long groupId) {
    ContentValues cv = new ContentValues();
    cv.put(ContactsContract.Groups.TITLE, name);
    contactHelper.update(ContactsContract.Groups.CONTENT_URI, cv,
            ContactsContract.Groups._ID + " = " + groupId, null);
}

// 그룹 삭제
public static void deleteGroup(ContentResolver contactHelper, long groupId) {
    Uri contactUri = ContactsContract.Groups.CONTENT_URI;
    String where = ContactsContract.Groups._ID + " = " + groupId;
    contactHelper.delete(contactUri, where, null);
}

public static long getrawIdFromContactId(ContentResolver contactHelper, long contactId) {
    // ContactsContract.RawContacts._ID = ContactsContract.Data.RAW_CONTACT_ID
    long rawId = -1;
    Uri contactUri = ContactsContract.RawContacts.CONTENT_URI;
    String[] projection = {RawContacts._ID};
    String where = RawContacts.CONTACT_ID + "=?";
    String[] whereParams = new String[]{String.valueOf(contactId)};
    Cursor cursor = null;

    try {
        cursor = contactHelper.query(contactUri, projection, where, whereParams, null);
        if (cursor.moveToFirst()) {
            rawId = cursor.getLong(cursor.getColumnIndex(RawContacts._ID));
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
    return rawId;
}




728x90
블로그 이미지

Link2Me

,

안드로이드 연락처(Contacts)를 신규 추가하는 코드다.

메소드 Overloading 을 사용해서 신규 저장하는 코드를 여러개 만들었다.

※ 메소드 오버로딩 : 같은 클래스내 같은 메소드명, 매개변수명이 다르거나 개수가 다르다.


본 코드가 구글 검색으로 찾은 코드와 다른 점 한가지가 있다.

.withValue(ContactsContract.CommonDataKinds.Phone.LABEL, strIDX)

서버 데이터를 Contacts 에 저장하고 비교를 해서 없는 것은 추가하고 있는 것은 달라진 정보만 업데이트하는 로직으로 구현하려고 이름 + 휴대폰번호 정보를 key 로 사용하고자 했으나,

서버 데이터에서 이름 + 휴대폰번호 중 한가지 정보가 달라지면 Contacts 에서는 처리하기가 어려울 거 같았다.

그래서 Contacts 에서 key로 사용할 칼럼을 고민하다가 휴대폰 번호가 가장 검색하기가 쉬운 점에 착안하여 위 칼럼을 key 로 사용했고, 결과는 대성공이다.


import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.PhoneLookup;
import android.provider.ContactsContract.RawContacts;
import android.util.Log;

public class ContactHelper {

    // 연락처 신규 저장
    public static void insertPhoneContacts(Context context, String strName, String mobileNO, String officeNO, String strIDX) {

        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        ContentProviderOperation.Builder op = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null);
        ops.add(op.build());

        // DISPLAY NAME(성명)
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, strName);
        ops.add(op.build());

        // 휴대폰 번호
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, mobileNO)
                .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, strIDX)
                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
        ops.add(op.build());

        // 사무실 번호
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, officeNO)
                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_WORK);

        op.withYieldAllowed(true);
        ops.add(op.build());

        try {
            context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (OperationApplicationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            Log.e("ContactsAdder", "Exceptoin encoutered while inserting contact: " + e);
        }

    }

    public static void insertPhoneContacts(Context context, String strName, String mobileNO, String officeNO,
            String strEmail, String strTeam, String strPosition, String strMission, String strPhoto, String strIDX) {

        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        ContentProviderOperation.Builder op = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null);
        ops.add(op.build());

        // DISPLAY NAME(성명)
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, strName);
        ops.add(op.build());

        // 휴대폰 번호
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, mobileNO)
                .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, strIDX)
                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
        ops.add(op.build());

        // 사무실 번호
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, officeNO)
                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_WORK);
        ops.add(op.build());

        // EMAIL
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Email.DATA, strEmail)
                .withValue(ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.TYPE_WORK);
        ops.add(op.build());

        // Photo Image
        MemoryCache memoryCache = new MemoryCache();
        Bitmap cachedImage = memoryCache.get(strPhoto);
        if (cachedImage != null) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            cachedImage.compress(CompressFormat.JPEG, 100, baos);

            byte[] b = baos.toByteArray();

            op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                    .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.Photo.DATA15, b);
            ops.add(op.build());
        }

        /* Organization */
        op = ContentProviderOperation
                .newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Organization.TITLE, strPosition)
                .withValue(ContactsContract.CommonDataKinds.Organization.COMPANY, "회사명")
                .withValue(ContactsContract.CommonDataKinds.Organization.DEPARTMENT, strTeam)
                .withValue(ContactsContract.CommonDataKinds.Organization.JOB_DESCRIPTION, strPosition)
                .withValue(ContactsContract.CommonDataKinds.Organization.TYPE,
                        ContactsContract.CommonDataKinds.Organization.TYPE_WORK);
        op.withYieldAllowed(true);
        ops.add(op.build());

        try {
            context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (OperationApplicationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            Log.e("ContactsAdder", "Exceptoin encoutered while inserting contact: " + e);
        }

    }
    
    // 연락처 신규 저장
    public static void insertPhoneContacts(Context context, String strName, String mobileNO, String officeNO, String strEmail,
            String strTeam, String strPosition, String strMission, String strPhoto, String strNote, String strIDX) {

        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null).build());
        // DISPLAY NAME(성명)
        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, strName).build());
        // 휴대폰 번호
        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, mobileNO)
                .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, strIDX)
                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
                .build());
        // 사무실 번호
        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, officeNO)
                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_WORK).build());
        // EMAIL
        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Email.DATA, strEmail)
                .withValue(ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.TYPE_WORK).build());

         //메모
         ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
         .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
         .withValue(ContactsContract.Data.MIMETYPE,
         ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE)
         .withValue(ContactsContract.CommonDataKinds.Note.NOTE, strNote).build());

        /* Organization */
        ops.add(ContentProviderOperation
                .newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Organization.TITLE, strPosition)
                .withValue(ContactsContract.CommonDataKinds.Organization.COMPANY, "회사명")
                .withValue(ContactsContract.CommonDataKinds.Organization.DEPARTMENT, strTeam)
                .withValue(ContactsContract.CommonDataKinds.Organization.JOB_DESCRIPTION, strPosition)
                .withValue(ContactsContract.CommonDataKinds.Organization.TYPE,
                        ContactsContract.CommonDataKinds.Organization.TYPE_WORK).build());

        // Photo Image
        MemoryCache memoryCache = new MemoryCache();
        Bitmap cachedImage = memoryCache.get(strPhoto);
        if (cachedImage != null) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            cachedImage.compress(CompressFormat.JPEG, 100, baos);

            byte[] b = baos.toByteArray();

            ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                    .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.Photo.DATA15, b).build());
        }

        try {
            // 연락처 제공자는 applyBatch()에서의 모든 작업을 하나의 트랜잭션으로서 수행
            context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (OperationApplicationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            Log.e("ContactsAdder", "Exceptoin encoutered while inserting contact: " + e);
        }

    }
}



728x90
블로그 이미지

Link2Me

,

성명(표시이름)과 휴대폰번호가 동일한 자료 기준으로 다른 정보들이 다를 경우, 없을 경우 수정(Update)하는 메소드다.

본 코드는 테스트시 성공적으로 잘 업데이트되는 걸 확인하고 적어둔다.

contactId, rawContactId 구하는 메소드는 다른 게시글에 올려져 있다.


public static boolean UpdateContactsInfo(ContentResolver contactHelper, String display_name, String mobileNO,
                                         String officeNO, String email, String OgnizationTitle, String OgnizationData, String contactNote) {
    if (mobileNO.equals("")) {
        return false;
    }
    long contactId = -1;

    // 성명과 휴대폰번호 기준으로 rawContactId 를 구한다.
    contactId = getContactIdFromNameAndNumber(contactHelper, display_name, mobileNO);
    if (contactId < 1) return false; // 데이터가 존재하지 않으면 바로 빠져나온다.
    long rawContactId = getrawIdFromContactId(contactHelper, contactId);

    ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
    Uri contactUri = ContactsContract.Data.CONTENT_URI;
    String where = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Contacts.Data.MIMETYPE + "=?";

    // work number
    if (!officeNO.equals("")) {
        // 사무실 전화의 where 조건은 달라서 별도로 지정
        String selectPhone = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='" +
                Phone.CONTENT_ITEM_TYPE + "'" + " AND " + Phone.TYPE + "=?";
        String[] phoneNumParams = new String[]{String.valueOf(contactId), String.valueOf(Phone.TYPE_WORK)};
        Cursor phoneNumCursor = contactHelper.query(contactUri, null, selectPhone, phoneNumParams, null);
        if (phoneNumCursor.getCount() > 0) {
            ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
                    .withSelection(selectPhone, phoneNumParams)
                    .withValue(Phone.NUMBER, officeNO)
                    .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_WORK)
                    .build());
        } else {
            ContentValues cv = new ContentValues();
            cv.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
            cv.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
            cv.put(ContactsContract.CommonDataKinds.Phone.DATA, officeNO);
            cv.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_WORK);
            ops.add(android.content.ContentProviderOperation.newInsert(android.provider.ContactsContract.Data.CONTENT_URI)
                    .withValues(cv).build());
        }
    }

    // email
    if (!email.equals("")) {
        String[] emailParams = new String[]{String.valueOf(contactId), ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE};
        Cursor emailCursor = contactHelper.query(contactUri, null, where, emailParams, null);
        if (emailCursor.getCount() > 0) {
            ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
                    .withSelection(where, emailParams)
                    .withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
                    .build());
        } else {
            ContentValues cValues = new ContentValues();
            cValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
            cValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
            cValues.put(ContactsContract.CommonDataKinds.Email.DATA, email);
            ops.add(android.content.ContentProviderOperation.newInsert(android.provider.ContactsContract.Data.CONTENT_URI)
                    .withValues(cValues)
                    .build());
        }
    }

    // 조직(organization)
    if (OgnizationData != "" || OgnizationTitle != "") {
        String[] orgParams = new String[]{String.valueOf(contactId), ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE};
        Cursor orgCursor = contactHelper.query(contactUri, null, where, orgParams, null);
        if (orgCursor.getCount() > 0) {
            ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
                    .withSelection(where, orgParams)
                    .withValue(ContactsContract.CommonDataKinds.Organization.DATA, OgnizationData)
                    .withValue(ContactsContract.CommonDataKinds.Organization.TITLE, OgnizationTitle)
                    .build());
        } else {
            ContentValues cValues = new ContentValues();
            cValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
            cValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
            cValues.put(ContactsContract.CommonDataKinds.Organization.DATA, OgnizationData);
            cValues.put(ContactsContract.CommonDataKinds.Organization.TITLE, OgnizationTitle);
            ops.add(ContentProviderOperation.newInsert(android.provider.ContactsContract.Data.CONTENT_URI)
                    .withValues(cValues)
                    .build());
        }
    }

    // note
    if (!contactNote.equals("")) {
        String[] noteParams = new String[]{String.valueOf(contactId), ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE};
        Cursor noteCursor = contactHelper.query(contactUri, null, where, noteParams, null);
        if (noteCursor.getCount() > 0) {
            ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
                    .withSelection(where, noteParams)
                    .withValue(ContactsContract.CommonDataKinds.Note.NOTE, contactNote)
                    .build());
        } else {
            ContentValues cValues = new ContentValues();
            cValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
            cValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE);
            cValues.put(ContactsContract.CommonDataKinds.Note.NOTE, contactNote);
            ops.add(ContentProviderOperation.newInsert(android.provider.ContactsContract.Data.CONTENT_URI)
                    .withValues(cValues)
                    .build());
        }
    }

    try {
        // 연락처 제공자는 applyBatch()에서의 모든 작업을 하나의 트랜잭션으로서 수행
        contactHelper.applyBatch(ContactsContract.AUTHORITY, ops);
        return true;
    } catch (RemoteException e) {
        e.printStackTrace();
    } catch (OperationApplicationException e) {
        e.printStackTrace();
    }
    return false;
} 


728x90
블로그 이미지

Link2Me

,

연락처 수정 기능 테스트를 하다보니 rawId를 구해야 하는 경우가 있어서 코드를 추가했다.

ContactsContract.RawContacts._ID = ContactsContract.Data.RAW_CONTACT_ID


public static long getrawIdFromContactId(ContentResolver contactHelper, long contactId) {
    // ContactsContract.RawContacts._ID = ContactsContract.Data.RAW_CONTACT_ID
    long rawId = -1;
    Uri contactUri = ContactsContract.RawContacts.CONTENT_URI;
    String[] projection = {RawContacts._ID};
    String where = RawContacts.CONTACT_ID + "=?";
    String[] whereParams = new String[]{String.valueOf(contactId)};
    Cursor cursor = null;

    try {
        cursor = contactHelper.query(contactUri, projection, where, whereParams, null);
        if (cursor.moveToFirst()) {
            rawId = cursor.getLong(cursor.getColumnIndex(RawContacts._ID));
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if(cursor != null){
            cursor.close();
        }
    }
    return rawId;
}

 public static long getContactIDFromrawId(ContentResolver contactHelper, long rawId) {
    long rawContactId = -1;
    Uri contactUri = ContactsContract.RawContacts.CONTENT_URI;
    String[] projection = {RawContacts.CONTACT_ID};
    String where = RawContacts._ID + "=?";
    String[] whereParams = new String[]{String.valueOf(rawId)};
    Cursor cursor = null;

    try {
        cursor = contactHelper.query(contactUri, projection, where, whereParams, null);
        if (cursor.moveToFirst()) {
            rawContactId = cursor.getLong(cursor.getColumnIndex(RawContacts.CONTACT_ID));
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if(cursor != null){
            cursor.close();
        }
    }
    return rawContactId;
}


728x90
블로그 이미지

Link2Me

,

안드로이드 연락처(Contacts) 정보를 수정(update)하는 메소드 중에서 휴대폰번호를 수정하는 코드를 테스트해보고 적어둔다.


ContactId 구하는 방법은 http://link2me.tistory.com/1313 에 있다.

사용법(Usage) : ContactHelper.updateContact(getContentResolver(), 17906, "010-1111-0000");

간단하게 수동으로 직접 적어서 테스트했다.


// CONTACT_ID 를 알고 있을 경우 휴대폰번호를 수정(update)하는 메소드
public static void updateContact(ContentResolver contactHelper, long contactId, String newNumber) {
    ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
    String wherePHone = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='"
            + Phone.CONTENT_ITEM_TYPE + "' AND " + Phone.TYPE + "=?";

    String[] phoneArgs = new String[] { String.valueOf(contactId), String.valueOf(Phone.TYPE_MOBILE) };
    ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
            .withSelection(wherePHone, phoneArgs)
            .withValue(Phone.NUMBER, newNumber).build());
    try {
        contactHelper.applyBatch(ContactsContract.AUTHORITY, ops);
    } catch (RemoteException e) {
        e.printStackTrace();
    } catch (OperationApplicationException e) {
        e.printStackTrace();
    }
}



728x90
블로그 이미지

Link2Me

,

안드로이드 연락처(Contacts)에서 ContactId 를 구하는 방법 테스트한 것을 적어둔다.


 Contacts._ID = PhoneLookup._ID = Phone.CONTACT_ID = RawContacts.CONTACT_ID

import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract;

Uri contactUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
// 검색할 칼럼 정하기, null 이면 모든 필드
String[] projection = {Phone.CONTACT_ID, Phone.DISPLAY_NAME, Phone.NUMBER, Phone.TYPE};
String where = Phone.DISPLAY_NAME + " like \'%" + display_name + "%\' AND " + Phone.TYPE + "=2";
String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
Cursor cursor = cursor = contactHelper.query(contactUri, projection, where, null, sortOrder);
long rawContactId = cursor.getLong(cursor.getColumnIndex(Phone.CONTACT_ID));

Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
// 검색할 칼럼 정하기, null 이면 모든 필드
String[] projection = {PhoneLookup._ID, PhoneLookup.DISPLAY_NAME, PhoneLookup.NUMBER};
Cursor cursor = contactHelper.query(contactUri, projection, null, null, null);
long rawContactId = cursor.getLong(cursor.getColumnIndex(PhoneLookup._ID));

Uri contactUri = ContactsContract.RawContacts.CONTENT_URI;
String[] projection = {RawContacts.CONTACT_ID};
String where = RawContacts._ID + "=?";
String[] whereParams = new String[]{String.valueOf(_ID)};
Cursor cursor = cursor = contactHelper.query(contactUri, projection, where, whereParams, null);
long rawContactId = cursor.getLong(cursor.getColumnIndex(RawContacts.CONTACT_ID));

ContentResolver cr = getContentResolver();
Uri contactUri = Contacts.CONTENT_URI;
String[] projection = new String[] {
        Contacts._ID,
        Contacts.DISPLAY_NAME,
        Contacts.STARRED,
        Contacts.TIMES_CONTACTED,
        Contacts.CONTACT_PRESENCE,
        Contacts.PHOTO_ID,
        Contacts.LOOKUP_KEY,
        Contacts.HAS_PHONE_NUMBER,
};
String where = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + Contacts.HAS_PHONE_NUMBER + " == 1))";
String sortOrder = Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";;
Cursor cursor = cr.query(contactUri, projection, where, null, sortOrder);
if (cursor.getCount() > 0) {
    while (cursor.moveToNext()) {
        String contactId = cursor.getString(cursor.getColumnIndex(Contacts._ID));
        String name = cursor.getString(cursor.getColumnIndex(Contacts.DISPLAY_NAME));
        System.out.println("contactId : " + contactId + " name : " + name);
        String mobileNO = null;
        String officeNO = null;
        if (Integer.parseInt(cursor.getString(cursor.getColumnIndex(Contacts.HAS_PHONE_NUMBER))) > 0) {
            Uri phonetUri = Phone.CONTENT_URI;
            Cursor pCur = cr.query(phonetUri, null, Phone.CONTACT_ID + " = ?", new String[]{contactId}, null);
            while (pCur.moveToNext()) {
                int phoneType = pCur.getInt(pCur.getColumnIndex(Phone.TYPE));
                String phoneNumber = pCur.getString(pCur.getColumnIndex(Phone.NUMBER));
                switch (phoneType) {
                    case Phone.TYPE_MOBILE:
                        mobileNO = phoneNumber;
                        break;
                    case Phone.TYPE_HOME:
                        break;
                    case Phone.TYPE_WORK:
                        officeNO = phoneNumber;
                        break;
                    case Phone.TYPE_OTHER:
                        break;
                    default:
                        break;
                }
            }
            pCur.close();
        }
    }
}

Contacts._ID 를 기준으로 구할 경우에는 휴대폰 번호가 바로 나오지 않기 때문에 또한번 Cursor를 사용하기 때문에 속도가 매우 늦다. 2,000개 정도 되는 연락처를 가져오는데 30초 정도 소요된다.


 ContactsContract.RawContacts 의 _ID 로 RawContacts.CONTACT_ID 구하는 코드

public static long getContactIDFrom_ID(ContentResolver contactHelper, long _ID) {
    long rawContactId = -1;
    Uri contactUri = ContactsContract.RawContacts.CONTENT_URI;
    String[] projection = {RawContacts.CONTACT_ID};
    String where = RawContacts._ID + "=?";
    String[] whereParams = new String[]{String.valueOf(_ID)};
    Cursor cursor = null;

    try {
        cursor = contactHelper.query(contactUri, projection, where, whereParams, null);
        if (cursor.moveToFirst()) {
            rawContactId = cursor.getLong(cursor.getColumnIndex(RawContacts.CONTACT_ID));
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        cursor.close();
    }
    return rawContactId;
}
 



구한 ID 기준으로 연락처 삭제

// 구한 CONTACT_ID 기준으로 연락처 삭제
public static void deleteContactFromContactId(ContentResolver contactHelper, long ContactId) {
    Uri contactUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
    String[] projection = null;
    String where = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?";
    String[] whereParams = new String[]{String.valueOf(ContactId)};
    String sortOrder = null;

    Cursor cursor = contactHelper.query(contactUri, projection, where, whereParams, sortOrder);
    if (cursor.moveToFirst()) {
        try {
            do {
                String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
                Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
                contactHelper.delete(uri, null, null);
            } while (cursor.moveToNext());
        } catch (Exception e) {
            e.getStackTrace();
        }
    }
}



728x90
블로그 이미지

Link2Me

,

연락처(Contacts)를 읽어오는 코드를 구현 테스트 중이다.

아래 코드를 테스트하면서 교보문고에 가서 책을 보니까 많은 시간이 걸리는 코드가 책에도 있더라.

읽어오는 연락처 데이터 개수가 적으면 아래 코드로도 빠른 응답 결과를 보여준다.

읽어올 데이터가 많다면 속도 문제 해결이 안되므로 해결을 위한 강구를 해야 한다.

해법은 데이터를 각각 읽어와서 메모리상에서 Join 하면 2천개 데이터를 가져오는데 1.5초 소요된다.


앱이 ContentProvider를 통해서 데이터에 접근할 때에는 ContentResolver를 통해서 접근하게 된다.
이 객체는 ContentProvider를 상속받아 특정 함수들을 보유하고 객체이다.
ContentResolver는 기존적인 CRUD(Create Retreive Update Delete) 함수들을 보유하고 있다.


Contacts 테이블에 있는 정보만 읽어오는 로직으로 구현시에는 2,000개의 데이터를 읽어오는 시간이 0.5초도 걸리지 않는다.

 public static Cursor LoadContactsCursor(ContentResolver contactHelper) {
    Uri contactUri = ContactsContract.Contacts.CONTENT_URI;
    String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " ASC";
    Cursor cursor = null;
    try {
        cursor = contactHelper.query(contactUri, null, null, null, sortOrder);
    } catch (Exception e){
        e.printStackTrace();
    }
    return cursor;
}

private ArrayList<String> contactRawContactID;
private ArrayList<String> contactNames;

contactRawContactID = new ArrayList<String>();
contactNames = new ArrayList<String>();

final SimpleDateFormat FORMATTER = new SimpleDateFormat("mm:ss:SSS");
long startTime = System.currentTimeMillis();
cursor = ContactHelper.LoadContactsCursor(getContentResolver());
System.out.println("연락처 개수 = " + cursor.getCount());
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
    contactRawContactID.add(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)));
    contactNames.add(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
    cursor.moveToNext();
}
cursor.close();
System.out.println("걸린시간 : " + FORMATTER.format(new Date(System.currentTimeMillis() - startTime)));



전화번호를 추가로 읽는 로직

 전화번호를 추가로 읽는 로직은 38초 소요된다.
 전화번호는 휴대폰번호, 사무실번호 2번 반복함에 따라 contactId 는 동일하지만 ArrayList 에 저장할 때 데이터가 따로 저장되므로 로직 구현을 고민해야 할 거 같다.

ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (cur.getCount() > 0) {
    int nCount=0; int mCount = 0;
    while (cur.moveToNext()) {
        nCount++;
        String contactId = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
        String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
        if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
            Uri contactUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
            Cursor pCur = cr.query(contactUri, null, Phone.CONTACT_ID + " = ?", new String[]{contactId}, null);
            while (pCur.moveToNext()) {
                mCount++;
                int phoneType = pCur.getInt(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
                String phoneNumber = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                switch (phoneType) {
                    case Phone.TYPE_MOBILE:
                        Log.e("nNo:"+nCount+" " + "mNo:"+mCount+" " +name + "(mobile number)", phoneNumber);
                        break;
                    case Phone.TYPE_HOME:
                        Log.e("nNo:"+nCount+" " + "mNo:"+mCount+" " +name + "(home number)", phoneNumber);
                        break;
                    case Phone.TYPE_WORK:
                        Log.e("nNo:"+nCount+" " + "mNo:"+mCount+" " +name + "(work number)", phoneNumber);
                        break;
                    case Phone.TYPE_OTHER:
                        Log.e("nNo:"+nCount+" " + "mNo:"+mCount+" " +name + "(other number)", phoneNumber);
                        break;
                    default:
                        break;
                }
            }
            pCur.close();
        }
    }
}



728x90
블로그 이미지

Link2Me

,

안드로이드 연락처 정보를 Update 하거나 Delete 할 경우에 성명 + 휴대폰번호 기준으로 조건에 충족하는 Contact_ID 를 구하는 메소드를 구현했다.

동일한 성명이 여러개 존재하거나, 휴대폰번호가 동일한 것이 2개 이상 존재할 수도 있다.

자료 결과 반환 조건은 성명 + 전화번호는 unique 하다는 가정하에 테스트를 진행했다.


Phone.TYPE = 2 (휴대폰번호, Phone.TYPE_MOBILE) 

Phone.TYPE = 3 (사무실번호, Phone.TYPE_WORK)


// 표시 이름과 휴대폰번호를 기준으로 ContactId 구하기
public static long getContactIDFromNameAndNumber(ContentResolver contactHelper, String display_name, String number) {
    long rawContactId = -1;

    Uri contactUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
    String[] projection = {Phone.CONTACT_ID, Phone.NUMBER};
    String where = Phone.DISPLAY_NAME + " = '" + display_name + "' AND " + Phone.NUMBER + " =? AND " + Phone.TYPE + " =2";
    String[] whereParams = new String[]{number};
    String sortOrder = Phone.DISPLAY_NAME + " ASC";
    Cursor cursor = null;
    try {
        cursor = contactHelper.query(contactUri, null, where, whereParams, sortOrder);
        if (cursor.moveToFirst()) {
            do {
                rawContactId = cursor.getLong(cursor.getColumnIndex(Phone.CONTACT_ID));
            } while (cursor.moveToNext());
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
    return rawContactId;
}


위 코드는 문제점이 휴대폰번호를 010-1111-0000 과 01011110000 을 다르게 인식하여 결과가 다르게 나온다.


그래서 코드를 다시 수정 테스트를 했다.

아래 코드는 휴대폰번호 010-1111-0000 과 01011110000 을 동일하게 인식하고 같은 rawContactId 를 반환한다.

// 표시 이름과 휴대폰번호를 기준으로 ContactId 구하기
public static long getContactIdFromNameAndNumber(ContentResolver contactHelper, String display_name, String number) {
    long rawContactId = -1;

    Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
    String[] projection = {PhoneLookup._ID, PhoneLookup.TYPE, PhoneLookup.DISPLAY_NAME};
    Cursor cursor = null;
    try {
        cursor = contactHelper.query(contactUri, projection, null, null, null);
        if (cursor.moveToFirst()) {
            do {
                String PhoneName = cursor.getString(cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME));
                if(display_name.equals(PhoneName)){
                    rawContactId = cursor.getLong(cursor.getColumnIndex(PhoneLookup._ID));
                }
            } while (cursor.moveToNext());
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
    return rawContactId;
}


728x90
블로그 이미지

Link2Me

,

CONTACT_ID 를 구했다는 가정하에 연락처를 삭제하는 메소드이다.

메소드는 2개 모두 잘 동작함을 확인하고 적어둔다.

// 구한 ID 기준으로 연락처 삭제
public static void deleteContactFromRawContactID(ContentResolver contactHelper, long CONTACT_ID) {
    String where = RawContacts.CONTACT_ID + " = " + String.valueOf(CONTACT_ID);
    contactHelper.delete(RawContacts.CONTENT_URI, where, null);
} 

 // 구한 ID 기준으로 연락처 삭제
public static void deleteContactFromContactId(ContentResolver contactHelper, long ContactId) {
    Uri contactUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
    String[] projection = null;
    String where = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?";
    String[] whereParams =new String[] { String.valueOf(ContactId) };
    String sortOrder = null;

    Cursor cursor = contactHelper.query(contactUri, projection, where, whereParams, sortOrder);
    if(cursor.moveToFirst()){
        try {
            do {
                String lookupKey = cursor .getString(cursor .getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
                Uri uri = Uri.withAppendedPath( ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
                contactHelper.delete(uri, null, null);
            } while (cursor.moveToNext());
        } catch (Exception e){
            e.getStackTrace();
        }
    }
}


전화번호로 CONTACT_ID 를 구하는 메소드

// 전화번호에서 구한 PhoneLookup._ID 가 RawContacts.ContactID 와 동일함
public static long getContactIDFromNumber(ContentResolver contactHelper, String number) {
    long rawContactId = -1;
    Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
    String[] projection = {PhoneLookup._ID};
    Cursor cursor = null;

    try {
        cursor = contactHelper.query(contactUri, projection, null, null, null);
        if (cursor.moveToFirst()) {
            System.out.println("PhoneLookup._ID from number : " + cursor.getLong(cursor.getColumnIndex(PhoneLookup._ID)));
            rawContactId = cursor.getLong(cursor.getColumnIndex(PhoneLookup._ID));
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if(cursor != null) {
            cursor.close();
        }
    }
    return rawContactId;
}



728x90
블로그 이미지

Link2Me

,

안드로이드 연락처 앱에 있는 연락처를  선택한 것만 삭제하는 메소드(bulkDelete) 와 모든 연락처를 삭제하는 메소드다.


public class ContactHelper {

    // 연락처 총개수 파악
    public static int getContactsTotalCount(ContentResolver contactHelper) {
        Cursor cursor = contactHelper.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
        return cursor.getCount();
    }

    public static void bulkDelete(ContentResolver contactHelper,long[] ids){
        if (ids.length == 0) { // 삭제할 데이터가 없으면
            return;
        }
        StringBuilder where=new StringBuilder();
        where.append(RawContacts.CONTACT_ID);
        where.append(" IN (");
        where.append(Long.toString(ids[0]));
        for (int i=1; i < ids.length; i++) {
            where.append(',');
            where.append(Long.toString(ids[i]));
        }
        where.append(')');
        try {
            contactHelper.delete(RawContacts.CONTENT_URI,where.toString(),null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 모든 연락처 삭제
    public static void deleteAllContact(ContentResolver contactHelper) {
        contactHelper.delete(RawContacts.CONTENT_URI, null, null);
    }
}


사용법

long[] ids = new long[]{16258,15265,15441,15542,16278};
ContactHelper.bulkDelete(getContentResolver(), ids);


위와 같이 수동으로 해당 CONTACT_ID를 직접 적어주고 테스트를 했다.

하지만 앱으로 구현한다면, CustomListView 에서 체크박스를 선택한 것만 삭제되도록 구현하면 될 것이다.

체크한 것만 ArrayList 에 담고 ArrayList 를 배열로 변환한 다음에

ContactHelper.bulkDelete(getContentResolver(), ids);

를 실행하면 될 것이다.

다만 IN 안에 들어가는 인수의 개수를 어느 범위까지 허용하는지 여부는 테스트를 안해봐서 장담할 수가 없다.


성명(display_name) 과 전화번호, CONTACT_ID 를 구할 수 있는 Cursor 메소드

    // Display Name 이 포함된 모든 Cursor 반환
    public static Cursor getContactCursorFromDisplayNameLIKE(ContentResolver contactHelper, String display_name) {

        // 검색할 칼럼 정하기, null 이면 모든 필드
        String[] projection = {Phone.CONTACT_ID,Phone._ID, Phone.DISPLAY_NAME, Phone.NUMBER};
        // Cursor를 얻기 위한 쿼리 조건
        String where = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " like \'%" + display_name + "%\'";
        String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
        Cursor cursor = null;

        try {
            if (display_name != null && !display_name.equals("")) {
                cursor = contactHelper.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, where, null,
                        sortOrder);
            } else {
                cursor = contactHelper.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, null, null,
                        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
            }
            cursor.moveToFirst();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return cursor;
    }

 public class MainActivity extends AppCompatActivity {
    private ArrayList<String> contactRawContactID;
    private ArrayList<String> contactDataID;
    private ArrayList<String> contactNames;
    private ArrayList<String> contactNumbers;
    ArrayAdapter<String> adapter;
    ListView listView;
    private Cursor cursor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listView = (ListView) findViewById(R.id.list);
        TextView tv_getCount = (TextView) findViewById(R.id.tv_getContactCount);
        tv_getCount.setText("총 " + String.valueOf(ContactHelper.getContactsTotalCount(getContentResolver())) + " 개");

        contactRawContactID = new ArrayList<String>();
        contactDataID = new ArrayList<String>();
        contactNames = new ArrayList<String>();
        contactNumbers = new ArrayList<String>();

        cursor = ContactHelper.getContactCursorFromDisplayNameLIKE(getContentResolver(), "");
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            contactRawContactID.add(cursor.getString(0));
            contactDataID.add(cursor.getString(1));
            contactNames.add(cursor.getString(2));
            contactNumbers.add(cursor.getString(3));
            cursor.moveToNext();
        }

        adapter = new MyAdapter(this, android.R.layout.simple_list_item_1, R.id.tvNameMain, contactNames);
        listView.setAdapter(adapter);

    }

    private class MyAdapter extends ArrayAdapter<String> {

        public MyAdapter(Context context, int resource, int textViewResourceId, ArrayList<String> conNames) {
            super(context, resource, textViewResourceId, conNames);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View row = setList(position, parent);
            return row;
        }

        private View setList(final int position, ViewGroup parent) {
            LayoutInflater inf = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            View row = inf.inflate(R.layout.liststyle, parent, false);

            TextView tvRawContactID = (TextView) row.findViewById(R.id.tvRawContactID);
            TextView tvDataID = (TextView) row.findViewById(R.id.tvDataID);
            TextView tvName = (TextView) row.findViewById(R.id.tvNameMain);
            TextView tvNumber = (TextView) row.findViewById(R.id.tvNumberMain);

            tvRawContactID.setText("RawContact_ID : " + contactRawContactID.get(position));
            tvDataID.setText("Data_ID : " + contactDataID.get(position));
            tvName.setText(contactNames.get(position));
            tvNumber.setText("No: " + contactNumbers.get(position));

            return row;
        }
    }
}


728x90
블로그 이미지

Link2Me

,

성명 + 전화번호 기준으로 일치되는 데이터를 삭제하는 메소드 구현을 적어둔다.

좀 더 나은 방법을 구현하면 업데이트해서 수정할 생각이다.


수정 구현 사항

// 성명 + 휴대폰번호 기준으로 연락처 삭제 (동명이인 고려)
public static void deleteContactFromNameAndNumber(ContentResolver contactHelper, String display_name, String number) {
    // 로직 개념 : 이름 검색으로 전화번호를 구한 다음에, 전화번호 일치여부 확인후 삭제 순서로 로직 구현
    number = number.replaceAll("[^0-9]", ""); // 숫자만 추출
    Uri contactUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
    String[] projection = {Phone.CONTACT_ID, Phone.NUMBER};
    String where = Phone.DISPLAY_NAME + " = '" + display_name + "' AND " + Phone.TYPE + "=2";
    String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
    Cursor cursor = null;
    try {
        if (display_name != null && !display_name.equals("") && number != null && !number.equals("")) {
            cursor = contactHelper.query(contactUri, projection, where, null, sortOrder);
            if (cursor.moveToFirst()) {
                do {
                    String phoneNO = cursor.getString(cursor.getColumnIndex(Phone.NUMBER));
                    phoneNO = phoneNO.replaceAll("[^0-9]", ""); // 숫자만 추출
                    if (number.equals(phoneNO)) {
                        // 이름으로 찾은 전화번호와 입력된 전화번호가 서로 같으면 해당 연락처 삭제 처리
                        long rawContactId = cursor.getLong(cursor.getColumnIndex(Phone.CONTACT_ID));
                        contactHelper.delete(RawContacts.CONTENT_URI,RawContacts.CONTACT_ID + "=" + rawContactId,null);
                    }
                } while (cursor.moveToNext());
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if(cursor != null) {
            cursor.close();
        }
    }
}



기존 구현 사항

public class ContactHelper {
    public ContactHelper() {
    }

    // 전화번호에서 ContactID 획득
    private static long getContactIDFromNumber(ContentResolver contactHelper, String number) {
        long rawContactID = -1;
        number = number.replaceAll("[^0-9]", ""); // 숫자만 추출
        Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));

        String[] projection = { PhoneLookup._ID };
        Cursor cursor = null;

        try {
            cursor = contactHelper.query(contactUri, projection, null, null, null);
            if (cursor.moveToFirst()) {
                rawContactID = cursor.getLong(cursor.getColumnIndex(PhoneLookup._ID));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            cursor.close();
        }
        return rawContactID;
    }

    // 전화번호 기준으로 연락처 삭제
    public static void deleteContactFromNumber(ContentResolver contactHelper, String number) {

        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        String[] WhereArgs = new String[] { String.valueOf(getContactIDFromNumber(contactHelper, number)) };

        ops.add(ContentProviderOperation.newDelete(RawContacts.CONTENT_URI)
                .withSelection(RawContacts.CONTACT_ID + "=?", WhereArgs).build());
        try {
            contactHelper.applyBatch(ContactsContract.AUTHORITY, ops);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (OperationApplicationException e) {
            e.printStackTrace();
        }
    }

    // 성명 + 전화번호 기준으로 연락처 삭제 (동명이인 고려)
    public static void deleteContactFromNameAndNumber(ContentResolver contactHelper, String display_name, String number) {
        // 로직 개념 : 이름 검색 --> 전화번호 --> ContactID 를 구하는 순서로 로직 구현
        number = number.replaceAll("[^0-9]", ""); // 숫자만 추출
        Uri contactUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        String[] projection = { ContactsContract.CommonDataKinds.Phone.NUMBER };
        String where = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " = '" + display_name + "'";
        String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
        Cursor cursor = null;
        try {
            if (display_name != null && !display_name.equals("") && number != null && !number.equals("")) {
                cursor = contactHelper.query(contactUri, projection, where, null, sortOrder);
                if (cursor.moveToFirst()) {
                    do {
                        String phoneNO = cursor.getString(cursor.getColumnIndex(Phone.NUMBER));
                        phoneNO = phoneNO.replaceAll("[^0-9]", ""); // 숫자만 추출
                        if (number.equals(phoneNO)) {
                            // 이름으로 찾은 전화번호와 입력된 전화번호가 서로 같으면 해당 연락처 삭제 처리
                            deleteContactFromNumber(contactHelper, phoneNO);
                        }
                    } while (cursor.moveToNext());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}



728x90
블로그 이미지

Link2Me

,

성명으로 검색한 연락처(Contacts)를 모두 삭제하는 메소드 구현사항을 적어둔다.

좀 더 효율적인 방법을 찾기 위해서 지속 수정 테스트로 내용 변경이 발생하다보니 기존 구현 메소드도 필요할 때가 있을거 같아서 적어둔다.


삭제 기본지식 이해

연락처를 읽거나 쓰기(수정/삭제) 위해서는 아래와 같은 퍼미션이 필요하다.
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>


연락처 삭제 메소드 중의 하나
static public void deleteContact(Context context, long rawContactId) {
  context.getContentResolver().delete(RawContacts.CONTENT_URI, RawContacts.CONTACT_ID + " = " + rawContactId, null);
}


RawContacts 를 삭제하면 종속된 data 는 자동으로 삭제가 된다.
Contacts 를 지우면 종속된 RawContacts 를 자동으로 삭제한다.
ContactsProvider 를 이용해서 RawContacts 를 삭제하면 데이터베이스에서 바로 지워지지 않는다.
RawContacts 테이블의 deleted 필드를 1로 세팅한다.
그리고 SyncAdapter 에 의해 실제 삭제가 이루어진다. 


성명(display_name)으로 검색한 동일한 이름을 포함하는 모든 데이터는 삭제를 한다.


수정 구현 사항

// 성명 포함 연락처 삭제 (구현 완료)
public static void deleteContactFromNameLIKE(ContentResolver contactHelper, String display_name) {
    System.out.println("Contact Name Search : " + display_name);
    Uri contactUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
    String[] projection = {Phone.CONTACT_ID, Phone.NUMBER}; // 검색
    String where = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " like \'%" + display_name + "%\'";
    String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
    Cursor cursor = null;
    try {
        if (display_name != null && !display_name.equals("")) {
            cursor = contactHelper.query(contactUri, projection, where, null, sortOrder);
            if (cursor.moveToFirst()) {
                int count = 0;
                do {
                    long rawContactId = cursor.getLong(cursor.getColumnIndex(Phone.CONTACT_ID));
                    contactHelper.delete(RawContacts.CONTENT_URI,RawContacts.CONTACT_ID + "=" + rawContactId,null);
                    count++;
                } while (cursor.moveToNext());
                System.out.println("Delete Contact Number Count = " + count);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if(cursor != null) {
            cursor.close();
        }
    }
}



기존 구현 사항

public class ContactHelper {
    public ContactHelper() {
    }

    // 성명 포함 연락처 삭제
    public static void deleteContactFromNameLIKE(ContentResolver contactHelper, Context context, String display_name) {
        System.out.println("Contact Name Search : " + display_name);
        Uri contactUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        String[] projection = { ContactsContract.CommonDataKinds.Phone.NUMBER };
        String where = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " like \'%" + display_name + "%\'";
        String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
        Cursor cursor = null;
        try {
            if (display_name != null && !display_name.equals("")) {
                cursor = contactHelper.query(contactUri, projection, where, null, sortOrder);
                if (cursor.moveToFirst()) {
                    int count = 0;
                    do {
                        String phoneNO = cursor.getString(cursor.getColumnIndex(Phone.NUMBER));
                        deleteContactFromNumber(contactHelper, phoneNO);
                        count++;
                    } while (cursor.moveToNext());
                    System.out.println("Delete Contact Number Count = " + count);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void deleteContactFromNumber(ContentResolver contactHelper, String number) {

        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        String[] WhereArgs = new String[] { String.valueOf(getContactIDFromNumber(contactHelper, number)) };

        ops.add(ContentProviderOperation.newDelete(RawContacts.CONTENT_URI)
                .withSelection(RawContacts.CONTACT_ID + "=?", WhereArgs).build());
        try {
            contactHelper.applyBatch(ContactsContract.AUTHORITY, ops);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (OperationApplicationException e) {
            e.printStackTrace();
        }
    }

    // 전화번호에서 ContactID 획득
    private static long getContactIDFromNumber(ContentResolver contactHelper, String number) {
        long rawContactID = -1;
        number = number.replaceAll("[^0-9]", ""); // 숫자만 추출
        Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));

        String[] projection = { PhoneLookup._ID };
        Cursor cursor = null;

        try {
            cursor = contactHelper.query(contactUri, projection, null, null, null);
            if (cursor.moveToFirst()) {
                System.out.println("ContactID from number : " + cursor.getLong(cursor.getColumnIndex(PhoneLookup._ID)));
                rawContactID = cursor.getLong(cursor.getColumnIndex(PhoneLookup._ID));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
                cursor.close();
        }

        return rawContactID;
    }
}


사용법

btn_delte.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // 전화번호 삭제
                ContactHelper.deleteContactFromNameLIKE(getContentResolver(), MainActivity.this, "홍길동");
            }
        });

        // 현재 Activity 갱신처리
        finish();
        startActivity(getIntent());

    }
});



728x90
블로그 이미지

Link2Me

,