2 komentarze

Pobieranie informacji o rozmówcy po zakończonej rozmowie

Sierpień 22, 2011 Snippety Telefoniczne

Oto przykład komponentu BroadcastReceiver publikującego informacje o rozmówcy zaraz po zawieszeniu rozmowy. Informacje publikowane są przy każdym rozłączeniu telefonu (rozmowa przychodząca, wychodząca i nieodebrane połączenie).

public class CallReceiver extends BroadcastReceiver {
	private static final String TAG = "CallLogDebug";
	private Context context;
	private AsyncTask<Void, Void, Cursor> lastCallerDataTask = new AsyncTask<Void, Void, Cursor>(){
		@Override
		protected Cursor doInBackground(Void... params) {
			waitForCallLogUpdate();
			return fetchLastCallData();
		}

		@Override
		protected void onPostExecute(Cursor result) {
			showDataFromCursor(result);
		}
	};

	@Override
	public void onReceive(Context context, Intent intent) {
		this.context = context;
		String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
		if(TelephonyManager.EXTRA_STATE_IDLE.equals(state)) {
			getLastCallerData();
		}
	}

	private void getLastCallerData() {
		lastCallerDataTask.execute();
	}

	private void waitForCallLogUpdate() {
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	private Cursor fetchLastCallData() {
		Uri uri = CallLog.Calls.CONTENT_URI;
		String orderBy = String.format("%s desc limit 1",Calls.DATE);
		return context.getContentResolver().query(uri, null, null, null, orderBy);
	}

	private void showDataFromCursor(Cursor c) {
		if (c.moveToFirst()) {
			for (int i = 0; i < c.getColumnCount(); i++) {
				Log.d(TAG, c.getColumnName(i) + " : " + c.getString(i));
			}
		}
		c.close();
	}
}

Jednosekundowe opóźnienie  wynika z tego, że informacje o ostatnim połączeniu zapisywane są w logach dopiero po otrzymaniu intencji o zmianie stanu telefonu.

Działanie powyższego kodu opiera się o akcję zmiany stanu telefonu (Intencja o akcji TelephonyManager.ACTION_PHONE_STATE_CHANGED). Kiedy otrzymamy informację o przejściu telefonu do stanu IDLE (bezczynny – uruchamiany w momencie zakończenia lub zrzucenia połączenia) odczytujemy informację z logów telefonu.

W naszym przypadku dane zapisywane są do LogCata.

Dodatkowe wymagania

W pliku AndroidManifest.xml należy dodać nasz BroadcastReceiver wraz z właściwym filtrem intencji, który go wywoła:

<receiver android:name=".CallReceiver">
	<intent-filter>
		<action android:name="android.intent.action.PHONE_STATE" />
	</intent-filter>
</receiver>

Należy również dodać pozwolenie na odczytywanie stanu telefonu:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

Efekt działania

O znaczeniu każdego pola zawartego w zwróconym obiekcie Cursor można poczytać w dokumentacji (link).

Komentarze (2) Subskrybuj

 

  1. m.pietraszek pisze:

    W dokumentacji do BroadcastReceiver (http://developer.android.com/reference/android/content/BroadcastReceiver.html) można przeczytać, że uruchamianie zadań asynchronicznych w onReceiv() nie jest dobrym rozwiązaniem. Czy podejście opisane w artykule rzeczywiście gwarantuje wpis do logu?

  2. Przyznam, że przeoczyłem informację o której mówisz. Jednak w przypadku tego kodu źródłowego nie ma to zbyt wielkiego znaczenia.

    Zgodnie z dokumentacją obiekt BroadcastReceiver może zostać usunięty w związku z czym nie należy przeprowadzać żadnych operacji asynchronicznych, które następnie wpłyną na jego stan.
    W przypadku opisanym powyżej operacje nie mają żadnego wpływu na BroadcastReceiver, w związku z czym nie powinny wystąpić tu żadne problemy. Ewentualnie można przesunąć metodę showDataFromCursor(result); do wnętrza doInBackground(…) aby i ona była wykonana w osobnym wątku (a nie wątku receivera).

Prześlij komentarz

Zaloguj się lub skorzystaj z profilu:

[rpxlogin redirect="http://www.android4devs.pl" prompt="" style="large"]

Możesz również zostawić komentarz bez rejestracji, korzystając z poniższego formularza:

Musisz być zalogowany aby móc pisać komentarze.