전화착발신이력

<uses-permission android:name=”android.permission.GET_ACCOUNTS” /> <uses-permission android:name=”android.permission.READ_CONTACTS” /> <uses-permission android:name=”android.permission.WRITE_CONTACTS” />

리스트 가져오기

모든 통화이력을 가져올 때는 아래와 같습니다.
		Uri UriCalls = Uri.parse("content://call_log/calls"); // 대소문자에 주의.
		Cursor c = getContentResolver().query(UriCalls, null, null, null, null);
		Log.d("JO", "CALL SIZE = " + c.getCount());
		if (c.getCount() > 0) {
			if (c.moveToFirst()) {
				do {
					String id = c.getString(c.getColumnIndex(CallLog.Calls._ID));
					String num = c.getString(c.getColumnIndex(CallLog.Calls.NUMBER));
					int type = Integer.parseInt(c.getString(c.getColumnIndex(CallLog.Calls.TYPE)));
					switch (type) {
					case 1:
						Log.d("JO", id + ", " + num + ": INCOMING");
						break;
					case 2:
						Log.d("JO", id + ", " + num + ": OUTGOING");
						break;
					case 3:
						Log.d("JO", id + ", " + num + ": MISSED");
						break;
					}
				} while (c.moveToNext());
			}
		}
		c.close();

통화(발신) 내역 추가하기

		ContentValues values = new ContentValues(5);
		values.put(CallLog.Calls.NUMBER, "08012345678");
		values.put(CallLog.Calls.TYPE, 2); // 1:수신, 2:발신, 3:부재중전화
		values.put(CallLog.Calls.DATE, System.currentTimeMillis()); // 시간
		values.put(CallLog.Calls.DURATION, 60L); // 통화시간
		values.put(CallLog.Calls.NEW, 1);
		Uri result = resolver.insert(Uri.parse("content://call_log/calls"), values);

마지막 통화(발신) 가져오기

		Cursor c = null;
		try {
			c = resolver.query(Uri.parse("content://call_log/calls"), new String[] { CallLog.Calls.NUMBER }, CallLog.Calls.TYPE + " = 2", null, "date DESC LIMIT 1");
			if (c == null || !c.moveToFirst()) {
				// 데이터 없음
				Log.d("JO", "No last call.");
			} else {
				// 마지막 발신통화
				String lastCall = c.getString(0);
				Log.d("JO", "last call is " + lastCall);
			}
		} finally {
			if (c != null) {
				c.close();
			}
		}

통화이력 삭제하기

최신 500개만 남기고 나머지는 삭제할때는 아래와 같습니다.
		Uri UriCalls = Uri.parse("content://call_log/calls");
		final ContentResolver resolver = getContentResolver();
		resolver.delete(UriCalls, "_id IN " + "(SELECT _id FROM calls ORDER BY date DESC LIMIT -1 OFFSET 500)", null);
2번째 인수가 SQLITE의 WHERE구문이므로 이부분을 설정하여 삭제가능합니다. 혹시 BroadcastReceiver내에서 통화종료시에 마지막 통화기록을 삭제하려면 아래와 같습니다. 전제조건으로 먼저 Telephone.CALLING_NUMBER 이라는 static 변수에 발신번호를 저장해둡니다.
	if ( Telephone.CALLING_NUMBER != null ) {
		final ContentResolver resolver = context.getContentResolver();
		Log.d("JO", "통화를 종료하였습니다. " + Telephone.CALLING_NUMBER);
		int deleted = resolver.delete(Uri.parse("content://call_log/calls"), "_id IN " + "(SELECT _id FROM calls WHERE number = '"+Telephone.CALLING_NUMBER+"' ORDER BY date DESC LIMIT 1)", null);
		Log.d("JO", "Deleted " + deleted + " record.");
	}
	// clear
	Telephone.CALLING_NUMBER=null;
단, 이렇게 하면 현재 통화종료한 데이터가 삭제되는게 아니라 1개 앞에것이 삭제됩니다. 달리말하면 BroadcastReceiver에서 IDLE상태가 되면서 동시에 통화로그 DB에도 저장이 되는데 타이밍상 삭제처리가 먼저 되고나서 통화로그에 이번 통화 기록이 됩니다. 따라서 아래처럼 약간의 딜레이를 주고 삭제해야 할것 같네요.
	(new Handler()).postDelayed(new Runnable() {
		@Override
		public void run() {
			if ( Telephone.CALLING_NUMBER != null ) {
				final ContentResolver resolver = context.getContentResolver();
				Log.d("JO", "통화를 종료하였습니다. " + Telephone.CALLING_NUMBER);
				int deleted = resolver.delete(Uri.parse("content://call_log/calls"), "_id IN " + "(SELECT _id FROM calls WHERE number = '"+Telephone.CALLING_NUMBER+"' ORDER BY date DESC LIMIT 1)", null);
				Log.d("JO", "Deleted " + deleted + " record.");
			}
			// clear
			Telephone.CALLING_NUMBER=null;
		}
	}, 1000); // 넉넉하게 1초 정도로 설정했습니다.

통화상태 체크하기

먼저 통화상태를 수신하기 위한 Receiver를 만듭니다.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
public class IncomingCallTracker extends BroadcastReceiver {
	// 통화화면으로 넘어가면서 Activity 가 onDestory 되므로, Receiver도 초기화됩니다.
	// 그래서 static 으로 선언해둡니다.
	static int currentState = -1;
	@Override
	public void onReceive(Context context, Intent intent) {
		final Bundle extras = intent.getExtras();
		if (intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
			final String state = extras.getString(TelephonyManager.EXTRA_STATE);
			final String incomingNumber = extras.getString(TelephonyManager.EXTRA_INCOMING_NUMBER); // 발신자 전화번호
			if ("IDLE".equals(state)) {
				// 통화종료
				if ( currentState == TelephonyManager.CALL_STATE_OFFHOOK ) {
					// 발신통화가 종료되었습니다.
				} else if ( currentState == TelephonyManager.CALL_STATE_RINGING ) {
					// 착신전화가 종료되었습니다.
				}
				currentState = TelephonyManager.CALL_STATE_IDLE;
			}
			if ("OFFHOOK".equals(state)) {
				// 발신
				currentState = TelephonyManager.CALL_STATE_OFFHOOK;
			}
			if ("RINGING".equals(state)) {
				// 착신(벨소리)
				currentState = TelephonyManager.CALL_STATE_RINGING;
			}
		}
	}
}
AndroidManifest.xml에는 아래와 같이 등록해둡니다.
        <receiver android:name=".IncomingCallTracker" >
            <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE" />
            </intent-filter>
        </receiver>
또는 AndroidManifest.xml 에 등록하지 않고 아래처럼 할 수 있습니다. 먼저 Activity에서 BroadcastReceiver 를 생성합니다.
	BroadcastReceiver receiver = new BroadcastReceiver() {
		// 통화화면으로 넘어가면서 Activity 가 onDestory 되므로, Receiver도 초기화됩니다.
		// 그래서 static 으로 선언해둡니다.
		static int currentState = -1;
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			Log.i("JO", "BROADCAST RECEIVED: ["+action+"]");
			if (action.equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
				Log.i("JO", "NEW CALL!");
			} else if (action.equals("android.intent.action.PHONE_STATE")) {
				final Bundle extras = intent.getExtras();
				if (intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
					final String state = extras.getString(TelephonyManager.EXTRA_STATE);
					Log.i("JO", "STATE => " + state);
					if ("IDLE".equals(state)) {
						if ( currentState == TelephonyManager.CALL_STATE_OFFHOOK ) {
							// 발신통화종료
						}
						currentState = TelephonyManager.CALL_STATE_IDLE;
					}
					if ("OFFHOOK".equals(state)) {
						currentState = TelephonyManager.CALL_STATE_OFFHOOK;
					}
					if ("RINGING".equals(state)) {
						currentState = TelephonyManager.CALL_STATE_RINGING;
					}
				}
			}
		}
	};
그 다음은 onCreate 에서 Receiver를 등록하고, onDestroy 에서 해제하면 됩니다. onCreate에서 등록할때는 아래처럼 필터를 등록합니다.
		IntentFilter filter = new IntentFilter();
		filter.addAction("android.intent.action.PHONE_STATE");
		filter.addAction("android.intent.action.NEW_OUTGOING_CALL");
		registerReceiver(receiver, filter);
해제시에는 아래처럼 합니다.
	@Override
	protected void onDestroy() {
		super.onDestroy();
		unregisterReceiver(receiver);
	}

참고사이트

http://mobisoftinfotech.com/call-log-deletion-in-android/ http://malsandroid.blogspot.jp/2010/06/accessing-call-logs.html http://ronanbrowne.wordpress.com/2011/02/06/content-providers-and-finding-call-logs/ http://alvinalexander.com/java/jwarehouse/android/core/java/android/provider/CallLog.java.shtml http://stackoverflow.com/questions/2477889/intent-to-be-fired-when-a-call-ends http://developer.android.com/reference/android/telephony/PhoneStateListener.html]]>

Related Posts