1

Froyo の call_log 機能に行き詰まっています。多くの人が知っているように、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 プロバイダーは通話ログから SMS レコードをスキップします。したがって、上記のコードでは、通話レコード (着信または発信) のみが表示され、他のすべてのレコードはスキップされます。もう少し掘り下げてみると、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)通話ログ プロバイダー自体によって明らかに追加されます。

だから私は2つの質問があります:

  1. プロバイダーが logtype フィルターを追加する方法を Android コードのどこで見つけることができますか? CallLog.javaCallLogProvider.javaを調べていましたが、見つかりません。
  2. Froyo の通話ログからすべてのレコードを読み取るにはどうすればよいですか? 電話をルート化しない限り、コールログプロバイダーをバイパスして独自の SQL ヘルパーを使用することはできません。これはオプションではありません。それを行う他の方法はありますか?
4

1 に答える 1

0

何が問題なのかはわかりませんが、通話ログを読んで着信または発信通話を取得するのは簡単です。次のサンプルでは、​​クエリに制限を追加して、特定の日付以降に行われた発信通話のデータのみを返すようにしています。where文字列では疑問符を使用して、SQL クエリを形成するために配列の値を代入する必要がある場所を示しますwargs

余分な WHERE 句が発生する場所について。コールログ プロバイダーの実装ではほぼ確実です。プロバイダーには通常、プロバイダーを開くために使用する uri を使用する switch ステートメントがあり、uri に基づいて制限を追加します。コールログは packages/providers/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;
}
于 2011-11-26T15:21:24.080 に答える