Reputation: 810
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 :
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 :
EDIT :
Second problem is solved. However, I am still not able to display the strings. Shows null in logcat.
Upvotes: 0
Views: 115
Reputation: 5741
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.
Upvotes: 2