Решил собрать все воедино и поделиться с теми, кто возможно будет набивать себе оскомину пытаясь найти решение данной проблемы. На оптимальность не претендую, так как сам учусь
Мониторинг входящих сообщений
Наверное реализация этой части самая простая и легкая. В манифесте приложения даем разрешение на обработку получения сообщения
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
И регистрируем Receiver, который будет срабатывать по событию входящего сообщения
<receiver android:name="MessageReceiver" android:enabled="true"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver>
Как видно из примера кода, при получении сообщения управление будет передаваться Receiver-у MessageReceiver.
Примерная реализация:
public class MessageReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); if (bundle != null) { Object[] pdus = (Object[]) bundle.get("pdus"); SmsMessage[] msgs = new SmsMessage[pdus.length]; ArrayList<String> numbers = new ArrayList<String>(); ArrayList<String> messages = new ArrayList<String>(); for (int i=0; i<msgs.length; i++){ //пробегаемся по всем полученным сообщениям msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]); numbers.add(msgs[i].getOriginatingAddress()); //получаем номер отправителя messages.add(msgs[i].getMessageBody().toString());//получаем текст сообщения } if (messages.size() > 0){ //делаем что-то с сообщениями } } } }
Мониторинг исходящих сообщений
К сожалению с исходящими сообщениями не так просто как со входящими. Telephony API не предоставляет отдельного события исходящего сообщения. Для меня это выглядит весьма странным в довольно отточенном продукте, которым является Android. Тем не менее решение все-таки есть.
В манифесте приложения даем разрешение на чтение сообщений
<uses-permission android:name="android.permission.READ_SMS"/>
А далее следует создать и зарегистрировать обработчик изменения базы сообщений. Вприцнипе тут можно объеденить обработку входящих и исходящих сообщений, но как-то со входящими сообщениями все намного проще. При обработке исходящих сообщений следует учесть тот факт, что обработчик может быть вызван несколько раз при отправке одного и того-же сообщения. Рекомендуется создать таблицу хешей всех сообщений проверять нету ли обрабатываемого сообщения в базе. В коде ниже показана примитивная проверка по идентификатору сообщения
private static final String CONTENT_SMS = "content://sms/"; private static long id = 0; //регистрируем обработчик изменений контента сообщений ContentResolver contentResolver = getBaseContext().getContentResolver(); contentResolver.registerContentObserver(Uri.parse(CONTENT_SMS),true, new OutgoingSmsObserver(new Handler())); private class OutgoingSmsObserver extends ContentObserver { @Override public void onChange(boolean selfChange) { super.onChange(selfChange); Uri uriSMSURI = Uri.parse(CONTENT_SMS); Cursor cur = getContentResolver().query(uriSMSURI, null, null,null, null); cur.moveToNext(); String protocol = cur.getString(cur.getColumnIndex("protocol")); if(protocol == null){ long messageId = cur.getLong(cur.getColumnIndex("_id")); //проверяем не обрабатывали ли мы это сообщение только-что if (messageId != id){ id = messageId; int threadId = cur.getInt(cur.getColumnIndex("thread_id")); Cursor c = getContentResolver().query(Uri.parse("content://sms/outbox/" + threadId), null, null, null, null); c.moveToNext(); //получаем адрес получателя String address = cur.getString(cur.getColumnIndex("address")); //получаем текст сообщения String body= cur.getString(cur.getColumnIndex("body")); //делаем что-то с сообщением } } } }
Мониторинг звонков
Android предоставляет возможность мониторить состояние телефона посредством действия android.intent.action.PHONE_STATE, но у меня снова таки возникла проблема получения номера абонента при исходящем звонке, поэтому мне пришлось регистрировать ресивер для двух действий.
В манифесте приложения даем разрешение на чтение состояния телефона и обработки исходящих звонков.
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
И регистрируем Receiver, который будет срабатывать по событию входящего сообщения
<receiver android:name="CallReceiver"> <intent-filter> <action android:name="android.intent.action.PHONE_STATE"/> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> </intent-filter> </receiver>
Примерная реализация:
String phoneNumber = ""; public class CallReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) { //получаем исходящий номер phoneNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER"); } else if (intent.getAction().equals("android.intent.action.PHONE_STATE")){ String phone_state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); if (phone_state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { //телефон звонит, получаем входящий номер phoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); } else if (phone_state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){ //телефон находится в режиме звонка (набор номера / разговор) } else if (phone_state.equals(TelephonyManager.EXTRA_STATE_IDLE)){ //телефон находиться в ждущем режиме. Это событие наступает по окончанию разговора, когда мы уже знаем номер и факт звонка } } } }
Резюмируя проблемы, которые я описал в самом начале, снова таки скажу, что меня не покидало ощущение некоторой недоделанности Android API. Входящее сообщение весьма легко перехватывается, что не скажешь о исходящем. Тоже самое касается и звонков. Конечно можно использовать одно решение и для сообщений, но если для входящих так просто, то почему нету такой простоты для исходящих?
ссылка на оригинал статьи http://habrahabr.ru/post/162181/
Добавить комментарий