Android Froyo: моя жизнь с call_log - PullRequest
       24

Android Froyo: моя жизнь с call_log

1 голос
/ 03 февраля 2011

Я застрял с функциональностью call_log в Froyo. Как многие из вас знают, Froyo регистрирует в журнале вызовов не только звонки, но и каждое исходящее и входящее SMS-сообщение. В параметрах можно выбрать отображение всего этого дерьма или только определенных типов (исходящие вызовы, входящие вызовы, отправленные сообщения, полученные сообщения и т. Д.), Но поскольку это переключатель, вы не можете указать, например, только текущие и входящие вызовы. Очень известная и раздражающая функциональность Froyo.

Итак, я начал писать какой-то простой инструмент для чтения журнала вызовов самостоятельно. Вот фрагмент кода:

try {
    mCur = getApplicationContext().getContentResolver()
               .query(CallLog.Calls.CONTENT_URI, columns, null, null, null );
    mCur.moveToFirst();
    io = mCur.getColumnIndex(CallLog.Calls._ID);
    bo = mCur.getColumnIndex(CallLog.Calls.NUMBER);
    no = mCur.getColumnIndex(CallLog.Calls.CACHED_NAME);
    to = mCur.getColumnIndex(CallLog.Calls.TYPE);

    while (mCur.isAfterLast() == false) {
        i = mCur.getString(io);
        b = mCur.getString(bo);
        n = mCur.getString(no);
        t = mCur.getString(to);
        Log.i(TAG, "CallLog: ID="+i+" number="+b+" name="+n+" type="+t);

        mCur.moveToNext();
    }
} catch (Exception e) {
    Log.e(TAG, "updateCallLog", e);
} finally {
    if (mCur != null) {
        mCur.close();
        mCur = null;
    }
}

Сюрприз, сюрприз, провайдер call_log пропускает записи смс из журнала вызовов. Таким образом, с помощью кода выше я вижу только записи о вызовах (входящие или исходящие), все остальные записи пропускаются. Немного больше углубившись в это выяснилось, что поставщик CallLog добавляет внутреннюю фильтрацию в базу данных журнала вызовов:

02-03 09:26:42.348 E/CLCService(28244): android.database.sqlite.SQLiteException: 
near ")": syntax error: , while compiling: 
SELECT _id, name, number, type FROM logs WHERE (logtype=100 OR logtype=500) AND (_ID=)

Не ищите синтаксическую ошибку, она была создана специально для того, чтобы заставить провайдера сбросить SQL-запрос, вызвав query(CallLog.Calls.CONTENT_URI, columns, "_ID=", null, null )). (_ID=) - это то, что указано в запросе, остальная часть (logtype=100 OR logtype=500), по-видимому, добавляется самим поставщиком журнала вызовов.

Итак, у меня два вопроса:

  1. Где я могу найти в коде Android, как провайдер добавляет фильтр типа журнала? Я искал CallLog.java и CallLogProvider.java и не могу найти его.
  2. Как я могу прочитать все записи из журнала вызовов в Froyo? Я не могу обойти провайдера журнала вызовов и использовать свой собственный помощник SQL для этого, пока я не буду рутировать телефон, который не вариант. Есть ли другой способ сделать это?

1 Ответ

0 голосов
/ 26 ноября 2011

Я не уверен, что происходит не так, но чтение журнала вызовов для получения только входящих или исходящих вызовов достаточно просто. Пример ниже добавляет ограничения к запросу, так что он возвращает данные только для исходящих вызовов, сделанных после определенной даты. Строка where использует вопросительные знаки, чтобы указать, куда следует подставлять значения из массива wargs для формирования запроса sql.

О том, где происходит дополнительное предложение WHERE. Почти наверняка в реализации провайдера calllog. У провайдеров обычно есть оператор switch, который использует URI, который вы используете для открытия провайдера, а затем добавляет ограничения на основе URI. Кажется, что список вызовов находится в пакетах / поставщики / ContactsProvider.

public static int getMinutesUsedSince(Context context, Date date) {
    Uri uri = CallLog.Calls.CONTENT_URI;
    String columns[] = new String[] { CallLog.Calls.DURATION };
    String where = CallLog.Calls.TYPE + "=? AND " + CallLog.Calls.DATE + ">?";
    String wargs[] = new String[] {
            String.valueOf(CallLog.Calls.OUTGOING_TYPE),
            String.valueOf(date.getTime())
    };
    String sortOrder = "date DESC";
    Cursor c = context.getContentResolver().query(uri, columns, where, wargs, sortOrder);
    long sum = 0;
    int durationIndex = c.getColumnIndex(CallLog.Calls.DURATION);
    if (c.moveToFirst()) {
        do {
            /* for each individual call, round up to the nearest minute */
            long duration = c.getLong(durationIndex);
            long minutes = (long)Math.ceil(duration / 60.0);
            sum += minutes;
        } while (c.moveToNext());
    }
    c.close();
    return (int)sum;
}
...