2

I'm trying to refresh the call log once a button is pressed. I have both a Uri and Cursor defined

Cursor c;
Uri allCalls = Uri.parse("content://call_log/calls");

and then this function is called in onCreate

public void checkLogs() {
    c = getContentResolver().query(allCalls, null, null, null, sOrder);

    while (c.moveToNext()) {
        num = c.getString(c.getColumnIndex(CallLog.Calls.NUMBER)); // for
                                                                    // number
        if (num.startsWith("+1")) {
            num = num.substring(2);
        }
        name = c.getString(c.getColumnIndex(CallLog.Calls.CACHED_NAME)); // for
                                                                            // name
        type = Integer.parseInt(c.getString(c
                .getColumnIndex(CallLog.Calls.TYPE))); // for type

        if (type == 3 && arrlst.contains(num) == false && name == null) {
            arrlst.add(num);
            initialize(num);
        }

        else {
            arrlst.add(num);
            continue;
        }
    }

    c.close();
}

This works, but I tried making a refresh button that contains the following code

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case (R.id.menuRefresh):
                allCalls = Uri.parse("content://call_log/calls");
                checkLogs();
    }
    return false;
}

when I press the refresh the new calls do not appear, but when I close and open the application they appear. What am I doing wrong?

Error log when trying to use Loader

05-25 02:31:14.724: E/AndroidRuntime(18892): FATAL EXCEPTION: main
05-25 02:31:14.724: E/AndroidRuntime(18892): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.callfinder/com.example.callfinder.FindCalls}: java.lang.NullPointerException
05-25 02:31:14.724: E/AndroidRuntime(18892):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2306)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2356)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at android.app.ActivityThread.access$600(ActivityThread.java:150)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1244)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at android.os.Handler.dispatchMessage(Handler.java:99)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at android.os.Looper.loop(Looper.java:137)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at android.app.ActivityThread.main(ActivityThread.java:5195)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at java.lang.reflect.Method.invokeNative(Native Method)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at java.lang.reflect.Method.invoke(Method.java:511)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at dalvik.system.NativeStart.main(Native Method)
05-25 02:31:14.724: E/AndroidRuntime(18892): Caused by: java.lang.NullPointerException
05-25 02:31:14.724: E/AndroidRuntime(18892):    at com.example.callfinder.FindCalls.checkLogs(FindCalls.java:171)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at com.example.callfinder.FindCalls.onCreate(FindCalls.java:55)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at android.app.Activity.performCreate(Activity.java:5104)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
05-25 02:31:14.724: E/AndroidRuntime(18892):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2260)
05-25 02:31:14.724: E/AndroidRuntime(18892):    ... 11 more

Also the code that I tried to explain if it was confusing in the comment

public void initialize() {
    layout = (LinearLayout) findViewById(R.id.ll1);
    tvTitle = (TextView) findViewById(R.id.textView1);
    lp = new LayoutParams(LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
    sOrder = String.format(sDate + " %s", sSort);

    mAdapter = new SimpleCursorAdapter(this, R.layout.activity_find_calls,
            null, null, null, 0);
    getLoaderManager().initLoader(0, null, this);

}

@Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
    return new CursorLoader(this, allCalls,
            null, null, null, sOrder);
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    switch (loader.getId()) {
      case 1:
          mAdapter.swapCursor(cursor);
          break;
    }

}

@Override
public void onLoaderReset(Loader<Cursor> arg0) {
    mAdapter.swapCursor(null);

}

and

    public void checkLogs() {
    c = mAdapter.getCursor();
    //c = getContentResolver().query(allCalls, null, null, null, sOrder);

    while (c.moveToNext()) {
        num = c.getString(c.getColumnIndex(CallLog.Calls.NUMBER)); // for
                                                                    // number
        if (num.startsWith("+1")) {
            num = num.substring(2);
        }
        name = c.getString(c.getColumnIndex(CallLog.Calls.CACHED_NAME)); // for
                                                                            // name
        type = Integer.parseInt(c.getString(c
                .getColumnIndex(CallLog.Calls.TYPE))); // for type

        if (type == 3 && arrlst.contains(num) == false && name == null) {
            arrlst.add(num);
            makeButton(num);
        }

        else {
            arrlst.add(num);
            continue;
        }
    }


}
Dzinic
  • 2,361
  • 2
  • 15
  • 16

2 Answers2

3

Use a CursorLoader to query a cursor containing the call log records. The CursorLoader will automatically refresh when the call logs are modified so you will not have to worry about refreshing the display manually (if you did need to refresh manually though, you can do so calling the LoaderManager's restartLoader() method).

Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
  • Could you give me a quick example of how I may use the cursorloader in this case? I was reading about it but I can't seem to understand how it full works. – Dzinic May 24 '13 at 05:44
-1

I actually got it to work with the following code

case (R.id.menuRefresh):
        allCalls = Uri.parse("content://call_log/calls");
        layout.removeAllViews();
        arrlst.clear();
        checkLogs();
Dzinic
  • 2,361
  • 2
  • 15
  • 16
  • You should accept this answer if it is the solution you are satisfied with. `CursorLoader` is definitely the recommended solution though... and it will make your code WAY simpler. Check out my [**blog posts**](http://www.androiddesignpatterns.com/2012/07/loaders-and-loadermanager-background.html) on `Loader`s. – Alex Lockwood May 24 '13 at 15:44
  • How do I query when using a CursorLoader? I did the following `clC.setUri(allCalls);` `clC.setSortOrder(sOrder);` `c = clC.loadInBackground();` where c is a cursor and cLc is a CursorLoader, but the app crashed when it called checkLogs on launch. Sorry if the question is straight forward, but I'm unable to find many resources to teach me about these loaders, they're new to me. – Dzinic May 24 '13 at 22:50
  • 1
    No, that's not how it works. You don't query the `CursorLoader` by calling its methods directly... you tell the `LoaderManager` to initialize the `CursorLoader` and the `LoaderManager` calls the `CursorLoader`'s methods instead (i.e. when it detects that new data is available). You should check out the [**documentation**](http://developer.android.com/reference/android/app/LoaderManager.html) for the `LoaderManager`... there is also some sample code on my [**blog post**](http://www.androiddesignpatterns.com/2012/07/understanding-loadermanager.html) illustrating the basic concept of how it works – Alex Lockwood May 24 '13 at 22:57
  • So I followed the instructions in your blog, and implemented the LoadManager and set up the unimplemented methods. I made my onCreateLoader return `new CursorLoader(this, allCalls, null, null, null, sOrder);` and also made an mAdapter and added `getLoaderManager().initLoader(0, null, this);`. Instead of using `c = getContentResolver().query(allCalls, null, null, null, sOrder);` in my checkLogs method I used `c = mAdapter.getCursor();` and left the rest of the code the same other than removing the c.close() Am I doing something wrong with the cursor because it crashes. Added log above – Dzinic May 25 '13 at 06:30