-1

I am trying to make an app in which I can store and view my daily lectures, using sqlite. Everything was working fine before i started using the content provider. Whenever I try to query from the database it returns a null cursor.

Moreover, I cant even add a new lecture to the database. It seems like my ContentProvider class is not working properly. But I have absolutely no idea of whats wrong in it. I have added the source code below.

I have been stuck here for quite long. So any help is highly appreciated!

StudentProvider.java

package com.example.utkarsh_pc.tester_app.data;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log;


public class StudentProvider extends ContentProvider {

private  final String LOG_TAG = StudentProvider.class.getSimpleName();

/** URI matcher code for the content URI for the lectures table */
private static final int LECTURES = 100;

/** URI matcher code for the content URI for a single lecture in the lectures table */
private static final int LECTURES_ID = 101;

/**
 * UriMatcher object to match a content URI to a corresponding code.
 * The input passed into the constructor represents the code to return for the root URI.
 * It's common to use NO_MATCH as the input for this case.
 */
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

// Static initializer. This is run the first time anything is called from this class.
static {
    // The calls to addURI() go here, for all of the content URI patterns that the provider
    // should recognize. All paths added to the UriMatcher have a corresponding code to return
    // when a match is found.

    // The content URI of the form "content://com.example.utkarsh_pc.tester_app/lectures" will map to the
    // integer code {@link #LECTURES}. This URI is used to provide access to MULTIPLE rows
    // of the pets table.
    sUriMatcher.addURI(StudentContract.CONTENT_AUTHORITY, StudentContract.PATH_LECTURES, LECTURES);

    // The content URI of the form "content://com.example.utkarsh_pc.tester_app/lectures/#" will map to the
    // integer code {@link #LECTURES_ID}. This URI is used to provide access to ONE single row
    // of the lectures table.
    //
    // In this case, the "#" wildcard is used where "#" can be substituted for an integer.
    // For example, "content://com.example.utkarsh_pc.tester_app/lectures/3" matches, but
    // "content://com.example.utkarsh_pc.tester_app/lectures" (without a number at the end) doesn't match.
    sUriMatcher.addURI(StudentContract.CONTENT_AUTHORITY, StudentContract.PATH_LECTURES + "/#", LECTURES_ID);
}

/** Database helper object */
private StudentDbHelper mDbHelper;

@Override
public boolean onCreate() {
    mDbHelper = new StudentDbHelper(getContext());
    return true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                    String sortOrder) {
    // Get readable database
    SQLiteDatabase database = mDbHelper.getReadableDatabase();

    // This cursor will hold the result of the query
    Cursor cursor;

    // Figure out if the URI matcher can match the URI to a specific code
    switch (sUriMatcher.match(uri)) {
        case LECTURES:
            // For the LECTURES code, query the lectures table directly with the given
            // projection, selection, selection arguments, and sort order. The cursor
            // could contain multiple rows of the lectures table.
            cursor = database.query(StudentContract.LectureEntry.TABLE_NAME, projection, selection, selectionArgs,
                    null, null, sortOrder);
            break;
        case LECTURES_ID:
            // For the LECTURES_ID code, extract out the ID from the URI.
            // For an example URI such as "content://com.example.utkarsh_pc.tester_app/lectures/3",
            // the selection will be "_id=?" and the selection argument will be a
            // String array containing the actual ID of 3 in this case.
            //
            // For every "?" in the selection, we need to have an element in the selection
            // arguments that will fill in the "?". Since we have 1 question mark in the
            // selection, we have 1 String in the selection arguments' String array.
            selection = StudentContract.LectureEntry._ID + "=?";
            selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};

            // This will perform a query on the lectures table where the _id equals 3 to return a
            // Cursor containing that row of the table.
            cursor = database.query(StudentContract.LectureEntry.TABLE_NAME, projection, selection, selectionArgs,
                    null, null, sortOrder);
            break;
        default:
            throw new IllegalArgumentException("Cannot query unknown URI " + uri);
    }

        return cursor;

}

@Override
public Uri insert(Uri uri, ContentValues contentValues) {
    final int match = sUriMatcher.match(uri);
    switch (match) {
        case LECTURES:
            return insertLecture(uri, contentValues);
        default:
            throw new IllegalArgumentException("Insertion is not supported for " + uri);
    }
}

/**
 * Insert a lecture into the database with the given content values. Return the new content URI
 * for that specific row in the database.
 */
private Uri insertLecture(Uri uri, ContentValues values) {
    // Check that the name is not null
    String name = values.getAsString(StudentContract.LectureEntry.COLUMN_LECTURE_NAME);
    if (name == null) {
        throw new IllegalArgumentException("Lecture requires a name");
    }

    // Check that the day is valid
    Integer day = values.getAsInteger(StudentContract.LectureEntry.COLUMN_LECTURE_DAY);
    if (day == null || !StudentContract.LectureEntry.isValidDay(day)) {
        throw new IllegalArgumentException("Lecture requires valid day");
    }

    // No need to check the start_time or end_time, any time is valid (including null).

    // Get writeable database
    SQLiteDatabase database = mDbHelper.getWritableDatabase();

    // Insert the new lecture with the given values
    long id = database.insert(StudentContract.LectureEntry.TABLE_NAME, null, values);
    if (id == -1) {
        return null;
    }

    // Return the new URI with the ID (of the newly inserted row) appended at the end
    return ContentUris.withAppendedId(uri, id);
}

@Override
public int update(Uri uri, ContentValues contentValues, String selection,
                  String[] selectionArgs) {
    final int match = sUriMatcher.match(uri);
    switch (match) {
        case LECTURES:
            return updateLecture(uri, contentValues, selection, selectionArgs);
        case LECTURES_ID:
            // For the LECTURES_ID code, extract out the ID from the URI,
            // so we know which row to update. Selection will be "_id=?" and selection
            // arguments will be a String array containing the actual ID.
            selection = StudentContract.LectureEntry._ID + "=?";
            selectionArgs = new String[] { String.valueOf(ContentUris.parseId(uri)) };
            return updateLecture(uri, contentValues, selection, selectionArgs);
        default:
            throw new IllegalArgumentException("Update is not supported for " + uri);
    }
}

/**
 * Update lectures in the database with the given content values. Apply the changes to the rows
 * specified in the selection and selection arguments (which could be 0 or 1 or more lectures).
 * Return the number of rows that were successfully updated.
 */
private int updateLecture(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    // If the {@link LectureEntry#COLUMN_LECTURE_NAME} key is present,
    // check that the name value is not null.
    if (values.containsKey(StudentContract.LectureEntry.COLUMN_LECTURE_NAME)) {
        String name = values.getAsString(StudentContract.LectureEntry.COLUMN_LECTURE_NAME);
        if (name == null) {
            throw new IllegalArgumentException("Lecture requires a name");
        }
    }

    // If the {@link LectureEntry#COLUMN_LECTURE_DAY} key is present,
    // check that the day value is valid.
    if (values.containsKey(StudentContract.LectureEntry.COLUMN_LECTURE_DAY)) {
        Integer day = values.getAsInteger(StudentContract.LectureEntry.COLUMN_LECTURE_DAY);
        if (day == null || !StudentContract.LectureEntry.isValidDay(day)) {
            throw new IllegalArgumentException("Lecture requires valid day");
        }
    }

    // If the {@link LectureEntry#COLUMN_LECTURE_DAY} key is present,
    // check that the day value is valid.
    if (values.containsKey(StudentContract.LectureEntry.COLUMN_LECTURE_DAY)) {
        Integer day = values.getAsInteger(StudentContract.LectureEntry.COLUMN_LECTURE_DAY);

    }

    // No need to check the start_time and end_time, any value is valid (including null).

    // If there are no values to update, then don't try to update the database
    if (values.size() == 0) {
        return 0;
    }

    // Otherwise, get writeable database to update the data
    SQLiteDatabase database = mDbHelper.getWritableDatabase();

    // Returns the number of database rows affected by the update statement
    return database.update(StudentContract.LectureEntry.TABLE_NAME, values, selection, selectionArgs);
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    // Get writeable database
    SQLiteDatabase database = mDbHelper.getWritableDatabase();

    final int match = sUriMatcher.match(uri);
    switch (match) {
        case LECTURES:
            // Delete all rows that match the selection and selection args
            return database.delete(StudentContract.LectureEntry.TABLE_NAME, selection, selectionArgs);
        case LECTURES_ID:
            // Delete a single row given by the ID in the URI
            selection = StudentContract.LectureEntry._ID + "=?";
            selectionArgs = new String[] { String.valueOf(ContentUris.parseId(uri)) };
            return database.delete(StudentContract.LectureEntry.TABLE_NAME, selection, selectionArgs);
        default:
            throw new IllegalArgumentException("Deletion is not supported for " + uri);
    }
}

@Override
public String getType(Uri uri) {
    final int match = sUriMatcher.match(uri);
    switch (match) {
        case LECTURES:
            return StudentContract.LectureEntry.CONTENT_LIST_TYPE;
        case LECTURES_ID:
            return StudentContract.LectureEntry.CONTENT_ITEM_TYPE;
        default:
            throw new IllegalStateException("Unknown URI " + uri + " with match " + match);
    }
}
}

StudentDbHelper.java

package com.example.utkarsh_pc.tester_app.data;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;


public class StudentDbHelper extends SQLiteOpenHelper {

public static final String LOG_TAG = StudentDbHelper.class.getSimpleName();

private static final String DATABASE_NAME = "student.db";

private static final int DATABASE_VERSION = 1;

public StudentDbHelper(Context context){

    super(context, DATABASE_NAME, null, DATABASE_VERSION);

}

@Override
public void onCreate(SQLiteDatabase db){

    String SQL_CREATE_TABLE = "CREATE TABLE " + StudentContract.LectureEntry.TABLE_NAME + " ("
            + StudentContract.LectureEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
            + StudentContract.LectureEntry.COLUMN_LECTURE_NAME + " TEXT NOT NULL, "
            + StudentContract.LectureEntry.COLUMN_LECTURE_TEACHER + " TEXT, "
            + StudentContract.LectureEntry.COLUMN_LECTURE_STARTTIME + " TEXT, "
            + StudentContract.LectureEntry.COLUMN_LECTURE_ENDTIME + " TEXT, "
            + StudentContract.LectureEntry.COLUMN_LECTURE_DAY + " INTEGER NOT NULL);";

    db.execSQL(SQL_CREATE_TABLE);

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){}

}

StudentContract.java

package com.example.utkarsh_pc.tester_app.data;

import android.content.ContentResolver;
import android.net.Uri;
import android.provider.BaseColumns;

public final class StudentContract {

private StudentContract() {
}

public static final String CONTENT_AUTHORITY = "com.example.utkarsh_pc.tester_app";

public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);

public static final String PATH_LECTURES = "lectures";

public static final class LectureEntry implements BaseColumns {

    public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, PATH_LECTURES);

    public static final String CONTENT_LIST_TYPE =
            ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_LECTURES;

    public static final String CONTENT_ITEM_TYPE =
            ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_LECTURES;

    public static final String TABLE_NAME = "lectures";

    public static final String _ID = BaseColumns._ID;

    public static final String COLUMN_LECTURE_NAME = "name";

    public static final String COLUMN_LECTURE_TEACHER = "teacher";

    public static final String COLUMN_LECTURE_STARTTIME = "start_time";

    public static final String COLUMN_LECTURE_ENDTIME = "end_time";

    public static final String COLUMN_LECTURE_DAY = "day";

    /**
     * Possible values for the day of the lecture.
     */
    public static final int DAY_MONDAY = 0;
    public static final int DAY_TUESDAY = 1;
    public static final int DAY_WEDNESDAY = 2;
    public static final int DAY_THURSDAY = 3;
    public static final int DAY_FRIDAY = 4;
    public static final int DAY_SATURDAY = 5;
    public static final int DAY_SUNDAY = 6;


    /**
     * Returns whether or not the given day is {@link #DAY_MONDAY}, {@link #DAY_TUESDAY},
     * {@link #DAY_WEDNESDAY},{@link #DAY_THURSDAY},{@link #DAY_FRIDAY},{@link #DAY_SATURDAY}
     * or {@link #DAY_SUNDAY}.
     */
    public static boolean isValidDay(int day) {
        if (day == DAY_MONDAY || day == DAY_TUESDAY || day == DAY_WEDNESDAY || day == DAY_THURSDAY || day == DAY_FRIDAY || day == DAY_SATURDAY || day == DAY_SUNDAY) {
            return true;
        } else {
            return false;
        }

    }
}
}

MondayActivity.java

package com.example.utkarsh_pc.tester_app;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.example.utkarsh_pc.tester_app.data.StudentContract;
import com.example.utkarsh_pc.tester_app.data.StudentDbHelper;
import com.example.utkarsh_pc.tester_app.data.StudentProvider;

import java.util.Objects;

public class MondayActivity extends AppCompatActivity {

ListView listView_mon;
String[] sub_mon = new String[]{"Sub1", "Sub2", "Sub3"};
FloatingActionButton fab;

private final String TAG = MondayActivity.class.getSimpleName();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_monday);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar1);
    setSupportActionBar(toolbar);
    getSupportActionBar().setTitle("Monday");

    fab = (FloatingActionButton) findViewById(R.id.fab1);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(MondayActivity.this, AddSubject1Activity.class);
            startActivity(intent);
        }
    });
}

@Override
protected void onStart(){
    super.onStart();
    displayLectureInfo();
}

private void displayLectureInfo() {

    String[] projections = new String[]{StudentContract.LectureEntry._ID,
            StudentContract.LectureEntry.COLUMN_LECTURE_NAME,
            StudentContract.LectureEntry.COLUMN_LECTURE_STARTTIME,
            StudentContract.LectureEntry.COLUMN_LECTURE_ENDTIME,
            StudentContract.LectureEntry.COLUMN_LECTURE_TEACHER,
            StudentContract.LectureEntry.COLUMN_LECTURE_DAY};

    Cursor cursor;
    cursor = getContentResolver().query(
            StudentContract.LectureEntry.CONTENT_URI,   // The content URI of the words table
            projections,             // The columns to return for each row
            null,                   // Selection criteria
            null,                   // Selection criteria
            null);                  // The sort order for the returned rows

    TextView displayView = (TextView) findViewById(R.id.sample_view_1);


        try {
            displayView.setText("The lecture table contains " + cursor.getCount() + " lectures.\n\n");
            displayView.append(StudentContract.LectureEntry._ID + " - " +
                    StudentContract.LectureEntry.COLUMN_LECTURE_NAME + " - " +
                    StudentContract.LectureEntry.COLUMN_LECTURE_STARTTIME + " - " +
                    StudentContract.LectureEntry.COLUMN_LECTURE_ENDTIME + " - " +
                    StudentContract.LectureEntry.COLUMN_LECTURE_TEACHER + " - " +
                    StudentContract.LectureEntry.COLUMN_LECTURE_DAY + "\n");

            // Figure out the index of each column
            int idColumnIndex = cursor.getColumnIndex(StudentContract.LectureEntry._ID);
            int nameColumnIndex = cursor.getColumnIndex(StudentContract.LectureEntry.COLUMN_LECTURE_NAME);
            int starttimeColumnIndex = cursor.getColumnIndex(StudentContract.LectureEntry.COLUMN_LECTURE_STARTTIME);
            int endtimeColumnIndex = cursor.getColumnIndex(StudentContract.LectureEntry.COLUMN_LECTURE_ENDTIME);
            int teacherColumnIndex = cursor.getColumnIndex(StudentContract.LectureEntry.COLUMN_LECTURE_TEACHER);
            int dayColumnIndex = cursor.getColumnIndex(StudentContract.LectureEntry.COLUMN_LECTURE_DAY);

            // Iterate through all the returned rows in the cursor
            while (cursor.moveToNext() || cursor.isFirst()) {
                // Use that index to extract the String or Int value of the word
                // at the current row the cursor is on.
                int currentID = cursor.getInt(idColumnIndex);
                String currentName = cursor.getString(nameColumnIndex);
                String currentStartttime = cursor.getString(starttimeColumnIndex);
                String currentEndtime = cursor.getString(endtimeColumnIndex);
                String currentTeacher = cursor.getString(teacherColumnIndex);
                int currentDay = cursor.getInt(dayColumnIndex);
                // Display the values from each column of the current row in the cursor in the TextView
                displayView.append(("\n" + currentID + " - " +
                        currentName + " - " +
                        currentStartttime + " - " +
                        currentEndtime + " - " +
                        currentEndtime + " - " +
                        currentTeacher + " - " +
                        currentDay));
            }
        } finally {
            cursor.close();
        }
    }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.timetable_menu1, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.back:
            Intent intent = new Intent(MondayActivity.this, MainActivity.class);
            startActivity(intent);
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}
}
Donald Duck
  • 8,409
  • 22
  • 75
  • 99
  • 1
    Is it possible for you to narrow down where the problematic code is in your program? What section did you change to initiate this issue? Simply dumping your whole source code makes answering your question a considerable amount of effort and may impact you receiving a useful answer. – Will Barnwell Feb 06 '17 at 18:06
  • Actually I don't have any idea of where the error might be. But yes I can tell you that, in the displayLectureInfo() method in theMondayActivity, the cursor returned from the getContentResolver().query() method is null. So i cant retrieve the lectures stored in the database. – Utkarsh Rai Feb 06 '17 at 18:10

1 Answers1

0

Did you add your ContentProvider in Manifest?

<provider
        android:authorities="@string/content_authority"
        android:name=".package.ProviderClass"
        android:exported="false"
        android:syncable="true" />

android:exported is false if only your app has access to ContentProvider

hosseinAmini
  • 2,184
  • 2
  • 20
  • 46
  • Yes, you are right! Because of this stupid mistake, my code wasn't working for the past 2 days. I can't even thank you enough for this Sir. I am highly grateful! – Utkarsh Rai Feb 06 '17 at 18:20