Android Froyo:我的 call_log 生活

发布于 2024-10-15 08:08:17 字数 2223 浏览 3 评论 0原文

我对 Froyo 中的 call_log 功能感到困惑。正如许多人所知,Froyo 不仅会记录通话,还会记录每条传出和传入的短信。您可以在选项中选择显示所有垃圾,或仅显示特定类型(去电、来电、发送消息、收到消息等),但由于这是单选按钮,因此您不能仅指定正在进行的呼叫和来电。非常著名且令人烦恼的 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=)

不要查找语法错误,它是故意创建的,旨在强制提供程序通过调用 query(CallLog. Calls.CONTENT_URI,列,“_ID=”,null,null ))(_ID=) 是查询中提供的内容,其余的 (logtype=100 OR logtype=500) 显然是由调用日志提供程序本身添加的。

所以我有两个问题:

  1. 在 Android 代码中哪里可以找到提供程序如何添加 logtype 过滤器?我正在研究 CallLog.javaCallLogProvider。 java 并找不到它。
  2. 如何在 Froyo 中读取通话记录中的所有记录?我无法绕过通话记录提供程序并使用我自己的 SQL 助手来执行此操作,除非我不会 root 手机,但这是不可能的。还有其他方法吗?

I'm stuck with the call_log functionality in Froyo. As many of you know, Froyo logs in call log not only calls but also each outgoing and incomming SMS message. You can chose in options to show all that crap, or only specific types (outgoing calls, incoming calls, sent messages, received messages etc), but since this is radio button, you cannot specify for example only ongoing and incoming calls. Very known and annoing Froyo functionality.

So I started to write some simple tool to read the call log by myself. Here is the code snippet:

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;
    }
}

Surprise, surprise, the call_log provider skips the sms records from the call log. So with the code above I see only call records (incoming or outgoing), all other records are skipped. The little more digging into it revealed that the CallLog provider adds internally filtering to the call log database:

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=)

Do not look for the syntax error, it was created on purpose to force provider to dump the SQL query by calling query(CallLog.Calls.CONTENT_URI, columns, "_ID=", null, null )). The (_ID=) is what is provided in the query, the rest of (logtype=100 OR logtype=500) is apparently added by the call log provider itself.

So I have two questions:

  1. Where I can find in the Android code how the provider is adding the logtype filter? I was looking into CallLog.java and CallLogProvider.java and cannot find it.
  2. How can I read all records from the call log in Froyo? I cannot bypass the call log provider and use my own SQL helper for this until I will not root the phone, which is not an option. Is there any other way to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

疧_╮線 2024-10-22 08:08:17

我不确定到底出了什么问题,但读取通话记录以获取传入或传出呼叫非常简单。下面的示例对查询添加了限制,以便它仅返回特定日期之后拨出呼叫的数据。 where 字符串使用问号来指示应在何处替换 wargs 数组中的值以形成 sql 查询。

关于额外的 WHERE 子句出现的位置。几乎可以肯定是在调用日志提供程序的实现中。提供程序通常有一个 switch 语句,该语句使用您用来打开提供程序的 uri,然后根据 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;
}

I'm not certain just what is going wrong but reading the call log to get just incoming or outgoing calls is simple enough. The sample below adds restrictions to the query so that it only returns data for outgoing calls made after a certain date. The where string uses question marks to indicate where the values from the wargs array should be substituted in to form the sql query.

About where the extra WHERE clause occurs. Almost certainly in the calllog provider implementation. The providers commonly have a switch statement that uses the uri that you use to open the provider and then adds restrictions based on the uri. The calllog one seems to be in 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文