Aymane
Aymane

Reputation: 11

Android Studio Cursor Error code when trying to retrieve call log

I was working on a simple phone app that shows the Call log and contacts also offers the possibility to call someone " It's Simply A Phone Caller ". The problem is when I was trying to retrieve the call log list using the cursor I got an error (Redline) that says the value must be >= 0.

Here is my fragment code

public class CallLogFragment extends Fragment {

    private RecyclerView recyclerView;
    private ArrayList<ModelCalls> arrayList;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.call_log_fragment, container, false);

        recyclerView = view.findViewById(R.id.call_log_rv);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
        RecyclerView.LayoutManager layoutManager = linearLayoutManager;
        recyclerView.setLayoutManager(layoutManager);
        CallLogAdapter adapter = new CallLogAdapter(getContext(), getCallLog());
        recyclerView.setAdapter(adapter);
        return view;
    }

    private ArrayList<ModelCalls> getCallLog() {
        Cursor cursor = getContext().getContentResolver().query(
                CallLog.Calls.CONTENT_URI,
                null,
                null,
                null,
                CallLog.Calls.DATE + " ASC"
        );

        String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
        String duration = cursor.getString(cursor.getColumnIndex(CallLog.Calls.DURATION));
        String date = cursor.getString(cursor.getColumnIndex(CallLog.Calls.DATE));
        String name = cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));

        cursor.moveToFirst();
        while (cursor.moveToNext()) {
            ModelCalls modelCalls = new ModelCalls(date, number, duration, name);
            arrayList.add(modelCalls);
        }
        return arrayList;
    }
}

And This is MainActivity Code :

public class MainActivity extends AppCompatActivity {

    private String[] PERMISSIONS;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        PERMISSIONS = new String[]{
                Manifest.permission.READ_CONTACTS,
                Manifest.permission.READ_CALL_LOG,
                Manifest.permission.WRITE_CALL_LOG
        };
        if (!EasyPermissions.hasPermissions(this, PERMISSIONS)){

            EasyPermissions.requestPermissions(this,
                    "Please allow Phone to access all the permissions",
                    123,
                    PERMISSIONS);
        }


        MaterialToolbar toolbar = findViewById(R.id.toolbar);
        BottomNavigationView navigationView = findViewById(R.id.bottom_nav_view);
        setSupportActionBar(toolbar);

        getSupportActionBar().setTitle("Phone");
        getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
                new CallLogFragment()).commit();


        navigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                int id = item.getItemId();
                Fragment selectedFragment = null;
                switch (id){
                    case R.id.nav_phone:
                        selectedFragment = new CallLogFragment();
                        getSupportActionBar().setTitle("Phone");
                        break;
                    case R.id.nav_contacts:
                        selectedFragment = new ContactsFragment();
                        getSupportActionBar().setTitle("Contacts");
                        break;
                    case R.id.nav_favorites:
                        selectedFragment = new FavoritesFragment();
                        getSupportActionBar().setTitle("Favorites");
                        break;
                }

                getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
                        selectedFragment).commit();
                return true;
            }
        });
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }
}

and I added those permissions to the manifest file:

<uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.READ_CALL_LOG"/>
    <uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
    <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>

And Here is my error when running the app :

2021-09-20 16:13:32.725 10584-10584/? E/AndroidRuntime: FATAL EXCEPTION: main Process: com.highui.myphone, PID: 10584 android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1285 at android.database.AbstractCursor.checkPosition(AbstractCursor.java:515) at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:138) at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:52) at android.database.CursorWrapper.getString(CursorWrapper.java:141) at com.highui.myphone.CallLogFragment.getCallLog(CallLogFragment.java:50) at com.highui.myphone.CallLogFragment.onCreateView(CallLogFragment.java:36) at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2963) at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:518) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189) at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100) at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002) at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3138) at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:3072) at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:251) at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:502) at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246) at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1440) at android.app.Activity.performStart(Activity.java:8109) at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3806) at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:235) at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:215) at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:187) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:105) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:213) at android.app.ActivityThread.main(ActivityThread.java:8178) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)

Upvotes: 0

Views: 419

Answers (1)

Pratik Fagadiya
Pratik Fagadiya

Reputation: 1472

you are trying to get information from outside the loop and also there is no specific projection for cursor.

Add projection in cursor and fetch information from cursor inside while loop.

like below code

private ArrayList<ModelCalls> getCallLog() {
    String[] projection = new String[]{
            CallLog.Calls.CACHED_NAME,
            CallLog.Calls.NUMBER,
            CallLog.Calls.DURATION,
            CallLog.Calls.DATE
    };

    Cursor cursor = getContext().getContentResolver().query(
            CallLog.Calls.CONTENT_URI,
            projection,
            null,
            null,
            CallLog.Calls.DATE + " ASC"
    );

    cursor.moveToFirst();
    while (cursor.moveToNext()) {

        String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
        String duration = cursor.getString(cursor.getColumnIndex(CallLog.Calls.DURATION));
        String date = cursor.getString(cursor.getColumnIndex(CallLog.Calls.DATE));
        String name = cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));

        ModelCalls modelCalls = new ModelCalls(date, number, duration, name);
        arrayList.add(modelCalls);
    }
    cursor.close();

    return arrayList;
}

Upvotes: 1

Related Questions