Search This Blog

11 June 2010

Accessing call logs

Start with a basic project:

F:\work> mvn archetype:generate -DarchetypeCatalog=http://kallisti.eoti.org:8081/content/repositories/snapshots/archetype-catalog.xml
2: http://kallisti.eoti.org:8081/content/repositories/snapshots/archetype-catalog.xml -> galatea-archetype (null)
groupId: org.eoti.android.calls
artifactId: CallLogs
version: 1.0-SNAPSHOT
package: org.eoti.android.calls


F:\work> cd CallLogs
F:\work\CallLogs> mvn clean install

Add the READ_CONTACTS permission to your AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_CONTACTS" />

Add this to the end of your onCreate() in CallLogsActivity:
        Uri allCalls = Uri.parse("content://call_log/calls");
        Cursor c = managedQuery(allCalls, null, null, null, null);
        for(String colName : c.getColumnNames())
            Log.v(TAG, "Column Name: " + colName);

        if (c.moveToFirst())
        {
           do{
               String id = c.getString(c.getColumnIndex(CallLog.Calls._ID));
               String num = c.getString(c.getColumnIndex(CallLog.Calls.NUMBER));
               int type = Integer.parseInt(c.getString(c.getColumnIndex(CallLog.Calls.TYPE)));

                switch (type)
                {
                    case 1: Log.v(TAG, id + ", " +num + ": INCOMING") ; break;
                    case 2: Log.v(TAG, id + ", " +num + ": OUTGOING") ;break;
                    case 3: Log.v(TAG, id + ", " +num + ": MISSED") ; break;
                }
           } while (c.moveToNext());
        }

Redeploy (mvn clean install).  If you watch the logs (adb logcat) while running the app on the emulator, you will see the column names listed -- but not any call logs... How do we fix that?
V/CallLogs(  870): Column Name: numbertype
V/CallLogs(  870): Column Name: new
V/CallLogs(  870): Column Name: duration
V/CallLogs(  870): Column Name: _id
V/CallLogs(  870): Column Name: numberlabel
V/CallLogs(  870): Column Name: name
V/CallLogs(  870): Column Name: number
V/CallLogs(  870): Column Name: type
V/CallLogs(  870): Column Name: date



The easy answer is that you can dial a number on the emulator (even though it won't connect) and then re-run your CallLogs app to see the number you just dialed listed as an OUTGOING call.

What about incoming and missed?  Create another AVD and launch a secondary emulator.  In the titlebar and taskbar icon name, you can see some number associated with each emulator instance (like: 5554).  From one emulator, you can "dial" the number of the other. So, for instance, in emulator 5556 open the dialer and dial 5554.  Dial from one to the other; answer some not others; Dial the other direction, etc.

Run your app again.  In my case, the emulator seemed to not log MISSED calls. 


At some point, you are bound to wonder what those nulls are in the managed query....  from the API:
public final Cursor managedQuery(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

A few brief examples of what you can do (per this tutorial):

uri: Who to get data from?
    Uri allCalls = Uri.parse("content://call_log/calls");

projection: What columns to return?
    String[] projection = new String[]{Calls._ID, Calls.NUMBER, Calls.TYPE};
   
selection: SQL WHERE clause
    String selection = "Calls.NUMBER LIKE '65%'"; //---retrieve numbers beginning with 65---
    String[] selectionArgs = null;
   
selectionArgs: (to populate the selection clause)

sortOrder: SQL ORDER BY clause
    String sortOrder = "Calls.TYPE DESC"; //---sort result by call TYPE descending---
   
So, for example,
Cursor c = managedQuery(
    Uri.parse("content://call_log/calls"),
    new String[]{Calls._ID, Calls.NUMBER, Calls.TYPE},
    "Calls.NUMBER LIKE '65%'",
    null,
    "Calls.TYPE DESC"
);
would return the _id, number, type columns from numbers that started with 65 in descending order....

19 comments:

  1. Call logs keep an extensive record of all your calls and transactions, as well as details such as name of caller, time, date, length of the call and result of transaction.

    ReplyDelete
  2. Hi Malachi,

    In phone log, we also see sent and received SMSes. Do you know how to retrieve that list and is it possible to clear them?

    Thanks,
    Abhijeet

    ReplyDelete
  3. Unfortunately, I have not tried SMS. Please post back if you find the solution.

    ReplyDelete
  4. hi Malachi ,
    I am new for android Apps.might be my questions seems funny to you but you will definatly trust me for upgraded version for call logs my queries are
    1. From where i can download the package
    org.eoti.android.calls

    2.I am getting a red line below this Uri
    Do i miss something please suggest

    With Regards
    Vikas

    ReplyDelete
  5. Hi Vicky,

    The package name 'org.eoti.android.calls' was created in the step where the maven archetype prompts for groupId and package.

    I am not sure if I understand the question about the URI, but the maven archetype has moved. See the Update at the bottom of this page for details.

    ReplyDelete
  6. Hi Malachi,
    I want to select number from call log. That number I want to display in edit text as my application required. I am able to open call log but I cant under stand how to select number from call log. Please Help me.. I am stuck on this..
    Thanks Mansi.

    ReplyDelete
  7. Hi Mansi,

    Loop though your cursor and grab the value from the CallLog.Calls.NUMBER field [see the 'num' example above].

    ReplyDelete
  8. Hi Malachi,
    Thanks for your answer. I got the all numbers from the Call log. Can I select that particular number from the call log directly? Is it possible..??

    Thanks Mansi

    ReplyDelete
  9. Hi Mansi,

    See the section above labeled "selection: SQL WHERE clause"

    ReplyDelete
  10. // To Read Inbox SMS's
    // use permission String
    uses-permission android:name="android.permission.READ_SMS"

    private Uri SmsInboxURI = Uri.parse("content://sms/inbox");
    Cursor myCursor = this.getContentResolver().query( SmsInboxURI, null,null, null,null );
    if(myCursor.getCount() == 0) // if Inbox is Empty
    return;

    myCursor.moveToFirst();
    do
    {
    android.util.Log.d( "SMS_LOG", "Senders Ph Number : " + myCursor.getString(2) );
    android.util.Log.d( "SMS_LOG", "SMS's TimeStamp : " + myCursor.getString(4) );
    android.util.Log.d( "SMS_LOG", "SMS Text : " + myCursor.getString(11) );

    }
    while (myCursor.moveToNext())
    myCursor.close();
    myCursor = null;

    ReplyDelete
  11. Hi Malachi,

    Can I get a month before call log in Android application? For example, suppose right now I have call log of this current month or week, if suppose I want to show a month before call log can we get that? And one more thing I want to know What is the limit of Call log?

    Thanks.

    ReplyDelete
  12. m@n: I have not tried it myself. According to this blog, it appears that Android keeps track of X call logs (not Y days). They say 500, but I am not sure that is consistent across all OEM/Carriers. I'd say they all probably have a max # of records though. So more calls means less likely to get what you want.

    ReplyDelete
  13. hi Malachi,
    can i get a full stretch of the code so tat i may gain additional knowledge abt call log access.
    I wll be so much thankful to u if u mail me the full code to my mail id which i furnish below.
    mailid: ragusizzles@gmail.com.
    Anticipating ur positive response!!!!

    Thanks
    With Regards,
    Raguram M

    ReplyDelete
  14. hi Malachi,
    can i get a full stretch of the code so tat i may gain additional knowledge abt call log access.
    I wll be so much thankful to u if u mail me the full code to my mail id which i furnish below.
    mailid: jasvintan@gmail.com.
    Anticipating ur positive response!!!!

    Thanks
    With Regards,
    Jasvin

    ReplyDelete
  15. hi malachi can u tell me how to display it.bcoz you are storing the data in string so simply displaying it through system.out.println will work we have to passsa data to the text boxes in xml

    ReplyDelete
  16. Hi Shashank,

    You need to get the view by id, then cast it to a TextBox/EditBox/etc, then call setText on it. You can see an example of that here.

    ReplyDelete
  17. Hi Malachi can you please tell me, why I cannot see the last outgoing call, but just one before last?

    Thanks,
    Karin

    ReplyDelete
  18. Hello,

    Its really nice tutorial and helped me a lot in going through the basics. But I am having one query here, the code is working very fine with single sim devices but its not working properly with dual sim devices. Can you give some guidance on how to get call log from dual sim devices?

    Keyur

    ReplyDelete
  19. Hi Keyur,

    I don't have access to a dual-sim device, but this site mentioned: field named "simid" shows which SIM card handled call.
    http://answer.techwikihow.com/1307000/sim-call-call-log-android.html

    ReplyDelete