pblead26 pblead26 - 4 months ago 9
Android Question

Android : Content Provider adds two rows at a time

I followed this tutorial on Content Providers, and it worked fine.
I tried something on my own and used Loaders to load the data. And I cant achieve the following :


  • Doesnt display the "body" text of the message, only the ID and timestamp. (Even though timestamp is string but contains numbers)

  • Biggest issue : 2 rows of the same values are added one at a time



So everytime I click the Send Message button, it adds two rows.
This is the logcat file.

07-17 02:57:18.307 11619-11619/poketpixels.reminder D/DB: 1, , 1468526093018
07-17 02:57:18.307 11619-11619/poketpixels.reminder D/DB: 2, , 1468526093018
07-17 02:57:18.307 11619-11619/poketpixels.reminder D/DB: 3, , 1468526292717
07-17 02:57:18.307 11619-11619/poketpixels.reminder D/DB: 4, , 1468526292717
07-17 02:57:18.307 11619-11619/poketpixels.reminder D/DB: 5, , 1468696845898
07-17 02:57:18.307 11619-11619/poketpixels.reminder D/DB: 6, , 1468696845898


Notice that there is no text display for BODY and the timestamps of two rows are equal. So naturally, created at the same time.

Following is the activity file :

public class ActivityChat extends AppCompatActivity
implements LoaderManager.LoaderCallbacks<Cursor> {

private static final int URL_LOADER = 0;
String URL = "content://something/messages";
Button sendMessage;

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

sendMessage = (Button)findViewById(R.id.btnSend);

getLoaderManager().initLoader(URL_LOADER, null, this);

sendMessage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SendMessage();
}
});

}



public Loader<Cursor> onCreateLoader(int id, Bundle args) {
CursorLoader loader = new CursorLoader(
this,
Uri.parse(URL),
null,
null,
null,
null);

return loader;
}



public void onLoadFinished(
Loader<Cursor> loader,
Cursor c) {

// LOADS ALL ROWS
if (c.moveToFirst()) {
do {
Log.d("DB",
c.getString(c.getColumnIndex(MessageProvider._ID)) +
", " + c.getString(c.getColumnIndex(MessageProvider.BODY)) +
", " + c.getString(c.getColumnIndex(MessageProvider.CREATED_AT)) + "\n"
);
} while (c.moveToNext());
}

}


@Override
public void onLoaderReset(Loader<Cursor> loader) {

}

public void SendMessage() {

// Add a new message record
ContentValues values = new ContentValues();

values.put(MessageProvider.BODY,
((EditText)findViewById(R.id.eTmessageBody)).getText().toString());

values.put(MessageProvider.CREATED_AT,
(System.currentTimeMillis()));

Log.d("DB", "SENT ALREADY");
Uri messages = Uri.parse(URL);

Cursor c = getContentResolver().query(messages, null, null, null, "created_at");

//loads only the last row
c.moveToLast();
Log.d("LAST ROW",c.getString(c.getColumnIndex(MessageProvider._ID)) +
", " + c.getString(c.getColumnIndex( MessageProvider.BODY)) +
", " + c.getString(c.getColumnIndex( MessageProvider.CREATED_AT)) );

}


}

MessageProvider.java

public class MessageProvider extends ContentProvider {

static final String PROVIDER_NAME = "something";
static final String URL = "content://" + PROVIDER_NAME + "/messages";
public static final Uri CONTENT_URI = Uri.parse(URL);

public static final String _ID = "_id";
public static final String BODY = "body";
public static final String CREATED_AT = "created_at";

private static HashMap<String, String> MESSAGES_PROJECTION_MAP;

static final int MESSAGES = 1;
static final int MESSAGE_ID = 2;

static final UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(PROVIDER_NAME, "messages", MESSAGES);
uriMatcher.addURI(PROVIDER_NAME, "messages/#", MESSAGE_ID);
}


/**
* Database specific constant declarations
*/
private SQLiteDatabase db;
static final String DATABASE_NAME = "test";
static final String MESSAGES_TABLE_NAME = "message";
static final int DATABASE_VERSION = 1;
static final String CREATE_DB_TABLE =
" CREATE TABLE " + MESSAGES_TABLE_NAME +
" (_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
" body TEXT NOT NULL, " +
" created_at TEXT NOT NULL);";

/**
* Helper class that actually creates and manages
* the provider's underlying data repository.
*/
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_DB_TABLE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + MESSAGES_TABLE_NAME);
onCreate(db);
}
}

@Override
public boolean onCreate() {
Context context = getContext();
DatabaseHelper dbHelper = new DatabaseHelper(context);

/**
* Create a write able database which will trigger its
* creation if it doesn't already exist.
*/
db = dbHelper.getWritableDatabase();
return (db == null) ? false : true;
}

@Override
public Uri insert(Uri uri, ContentValues values) {

final long objectId = db.insertOrThrow(MessageProvider.MESSAGES_TABLE_NAME, null, values);
final Uri newObjectUri = ContentUris.withAppendedId(CONTENT_URI, objectId);
getContext().getContentResolver().notifyChange(newObjectUri, null);

/**
* Add a new message record
*/
long rowID = db.insert(MESSAGES_TABLE_NAME, "", values);

/**
* If record is added successfully
*/

if (rowID > 0) {
Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
getContext().getContentResolver().notifyChange(_uri, null);
return _uri;
}
throw new SQLException("Failed to add a record into " + uri);
}

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(MESSAGES_TABLE_NAME);


switch (uriMatcher.match(uri)) {
case MESSAGES:
qb.setProjectionMap(MESSAGES_PROJECTION_MAP);
break;

case MESSAGE_ID:
qb.appendWhere(_ID + "=" + uri.getPathSegments().get(1));
break;

default:
throw new IllegalArgumentException("Unknown URI " + uri);
}

if (sortOrder == null || sortOrder == "") {
/**
* By default sort on time
*/
sortOrder = CREATED_AT;
}
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);

/**
* register to watch a content URI for changes
*/
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}


@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;


//public int delete(String table, String whereClause, String[] whereArgs) {

final long objectId = db.delete(MessageProvider.MESSAGES_TABLE_NAME, null, null);
final Uri newObjectUri = ContentUris.withAppendedId(CONTENT_URI, objectId);
getContext().getContentResolver().notifyChange(newObjectUri, null);


switch (uriMatcher.match(uri)) {
case MESSAGES:
count = db.delete(MESSAGES_TABLE_NAME, selection, selectionArgs);
break;

case MESSAGE_ID:
String id = uri.getPathSegments().get(1);
count = db.delete(MESSAGES_TABLE_NAME, _ID + " = " + id +
(!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
break;

default:
throw new IllegalArgumentException("Unknown URI " + uri);
}

getContext().getContentResolver().notifyChange(uri, null);
return count;
}

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int count = 0;


final long objectId = db.insertOrThrow(MessageProvider.MESSAGES_TABLE_NAME, null, values);
final Uri newObjectUri = ContentUris.withAppendedId(CONTENT_URI, objectId);
getContext().getContentResolver().notifyChange(newObjectUri, null);


switch (uriMatcher.match(uri)) {
case MESSAGES:
count = db.update(MESSAGES_TABLE_NAME, values, selection, selectionArgs);
break;

case MESSAGE_ID:
count = db.update(MESSAGES_TABLE_NAME, values, _ID + " = " + uri.getPathSegments().get(1) +
(!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
break;

default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}

@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
/**
* Get all message records
*/
case MESSAGES:
return "vnd.android.cursor.dir/vnd.poketpixels.reminder.messages";

/**
* Get a particular message
*/
case MESSAGE_ID:
return "vnd.android.cursor.item/vnd.poketpixels.reminder.messages";

default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
}


So the two problems are :


  • I want to display strings.

  • Two rows added to database at one point of time



EDIT :

Second problem is solved.
However, I am still not able to display the strings. Shows null in logcat.

Answer

You are inserting record two times in insert method.

one by using :     final long objectId = db.insertOrThrow(MessageProvider.MESSAGES_TABLE_NAME, null, values);


Another by :  long rowID = db.insert(MESSAGES_TABLE_NAME, "", values);

Remove one of the above line from insert method of class MessageProvider.

Comments