Fill ListView from a cursor in Android - android

I've spent a lot of hours searching and reading similar posts, but none of them seem to truly reflect my problem and thus I haven't found anything that works for me.
I've got a database, on which I perform a query, the results of which are stored in a cursor. There's two things to that:
-the query is performed everytime a certain button is pressed (thus the query is inside the OnClickListener for that Button)
-the query returns two different columns with String values, which must be treated separately (one column stores the names which must be shown in the ListView, the other stores the paths to the image associated toa row)
My problem is, I try to create a String[] which I need to pass to the ArrayAdapter creator for the ListView, but trying to assign it a size of Cursor getCount() crashes my activity. I hope the code will be more of an explanation:
OnClickListener searchListener = new OnClickListener() {
public void onClick(View v) {
CardDatabaseOpenHelper helper = new
CardDatabaseOpenHelper(DeckEditorScreen1.this);
SQLiteDatabase db = helper.getReadableDatabase();
String columns[] = {"name","number","path"};
Cursor c = db.query("cards", columns, null, null, null, null, "number");
int count = c.getCount();
String[] resultNameStrings;
if (count != 0) resultNameStrings = new String[count];
else {resultNameStrings = new String[1]; resultNameStrings[1] = "No results";}
// This is the offending code
//Note that if I assign fixed values to resutNameStrings, the code works just
//fine
for (int i = 0; i < count; ++i) {
c.moveToNext();
int col = c.getColumnIndex("name");
String s = c.getString(col);
//Ideally here I would to something like:
//resultNameStrings[i] = s;
col = c.getColumnIndex("number");
int conv = c.getInt(col);
col = c.getColumnIndex("path");
String s2 = c.getString(col);
}
db.close();
ArrayAdapter<?> searchResultItemAdapter = new ArrayAdapter<String>
(DBScreen.this,
R.layout.search_result_item,
resultNameStrings);
ListView searchResultList = (ListView)
DBScreen.this.findViewById(R.id.search_result_list);
searchResultList.setAdapter(searchResultItemAdapter);
}
};
Button search_button = (Button) findViewById(R.id.search_button);
search_button.setOnClickListener(searchListener);

EDITED twice :)
do it in "Android Way" ...
first use CursorAdapter (fx.: SimpleCursorAdapter with overrided
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
Cursor cursor = managedQuery(MobileTraderProvider.CONTENT_URI,
null, null, new String[] { constraint.toString() }, null);
return cursor;
}
then
customAdapter.getFilter().filter(filterText)
// it will call runQueryOnBackgroundThread
second use ContentProvider(it will manage curosors for you ... it will even requery if data changed)
EDIT:
first really use my advice
second before
for (int i = 0; i < count; ++i) {
c.moveToNext();
//...
add c.moveToFirst();
thrid: use
if(c.moveToNext())
{
int col = c.getColumnIndex("name");
//..... rest goes here
}
SECOND EDIT:
MyProvider.java
public class MyProvider extends ContentProvider {
static final String LTAG = "MyAppName";
public static final Uri CONTENT_URI = Uri.parse("content://my.app.Content");
static final int CARDS = 1;
static final int CARD = 2;
public static final String CARDS_MIME_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/Cards";
public static final String CARD_MIME_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/Cards";
static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
static final HashMap<String, String> map = new HashMap<String, String>();
static {
//static "Constructor"
matcher.addURI(Constants.AUTHORITY, "Cards", LISTS);
matcher.addURI(Constants.AUTHORITY, "Cards/*", LIST);
map.put(BaseColumns._ID, "ROWID AS _id");
map.put(Tables.Cards.C_NAME, Tables.Cards.C_NAME);
map.put(Tables.Cards.C_NUMBER, Tables.Cards.C_NUMBER);
map.put(Tables.Cards.C_PATH, Tables.Cards.C_PATH);
}
private CardDatabaseOpenHelper mDB;
#Override
public boolean onCreate() {
try {
mDB = new CardDatabaseOpenHelper(getContext());
} catch (Exception e) {
Log.e(LTAG, e.getLocalizedMessage());
}
return true;
}
public int delete(Uri uri, String selection, String[] selectionArgs) {
String table = null;
switch (matcher.match(uri)) {
case CARD:
//overriding selection and selectionArgs
selection = "ROWID=?";
selectionArgs = new String[] { uri.getPathSegments().get(1) };
table = uri.getPathSegments().get(0);
break;
case CARDS:
//this version will delete all rows if you dont provide selection and selectionargs
table = uri.getPathSegments().get(0);
break;
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
int ret = mDB.getWritableDatabase().delete(table, selection, selectionArgs);
getContext().getContentResolver().notifyChange(Uri.withAppendedPath(CONTENT_URI, table), null);
return ret;
}
#Override
public String getType(Uri uri) {
switch (matcher.match(uri)) {
case CARDS:
return CARDS_MIME_TYPE;
case CARD:
return CARD_MIME_TYPE;
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
}
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
String table, rowid;
switch (matcher.match(uri)) {
case CARD:
//overriding selection and selectionArgs
selection = "ROWID=?";
selectionArgs = new String[] { uri.getPathSegments().get(1) };
table = uri.getPathSegments().get(0);
break;
case CARDS:
//this version will update all rows if you dont provide selection and selectionargs
table = uri.getPathSegments().get(0);
break;
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
int ret = mDB.getWritableDatabase().update(table, values, selection, selectionArgs);
getContext().getContentResolver().notifyChange(Uri.withAppendedPath(CONTENT_URI, table), null);
return ret;
}
public Uri insert(Uri uri, ContentValues values) {
String table = null;
switch (matcher.match(uri)) {
case CARDS:
table = uri.getPathSegments().get(0);
break;
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
mDB.getWritableDatabase().insert(table, null, values);
getContext().getContentResolver().notifyChange(Uri.withAppendedPath(CONTENT_URI, table), null);
return null;
}
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
switch (matcher.match(uri)) {
case CARDS:
builder.setTables(uri.getPathSegments().get(0));
break;
case CARD:
builder.setTables(uri.getPathSegments().get(0));
selection = "ROWID=?";
selectionArgs = new String[] { uri.getPathSegments().get(1) };
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
builder.setProjectionMap(map);
Cursor cursor = builder.query(mDB.getReadableDatabase(), projection, selection, selectionArgs, null, null, sortOrder);
if (cursor == null) {
return null;
}
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
}
CardCursorAdapter.java
class CardCursorAdapter extends SimpleCursorAdapter {
public MyCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
}
#Override
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
//search in cards.name
String selection = Tables.Cards.C_NAME + " LIKE ?";
String[] selectionArgs = new String[] {"%" + constraint.toString() + "%"};
Cursor cursor = managedQuery(Uri.withAppendedPath(MyProvider.CONTENT_URI, Tables.Cards.Name),
getCursor().getColumnNames(), selection, selectionArgs, null);
return cursor;
}
}
Tables.java
public static class Tables {
//table definition
public static interface Cards {
public static final String NAME = "cards";
public static final String C_NAME = "name";
public static final String C_NUMBER = "number";
public static final String C_PATH = "path";
}
//other tables go here
}
AndroidManifest.xml
</manifest>
</application>
<!-- ....... other stuff ....... -->
<provider android:name="MyProvider" android:authorities="my.app.Content" />
</application>
</manifest>
then in activity
onCreate(...){
listView.setAdapter(new CardCursorAdapter(this, R.layout.listrow,
managedQuery(Uri.withAppendedPath(MyProvider.CONTENT_URI, Tables.Cards.NAME),
new String[] { BaseColumns._ID, Tables.Cards.C_NAME, Tables.Cards.C_NUMBER, Tables.Cards.C_PATH },
null,null, number),
new String[] { Tables.Cards.C_NAME, Tables.Cards.C_NUMBER, Tables.Cards.C_PATH },
new int[] { R.id.tName, R.id.tNumber, R.id.tPath }));
}
OnClickListener searchListener = new OnClickListener() {
public void onClick(View v) {
DeckEditorScreen1.this.listView.getAdapter().getFilter().filter("text for search in name column of card table set me to empty for all rows");
}
}

Ok, I've done some testing and I think I know what was the problem. Java allows constructs like:
String[] whatever;
if (something) whatever = new String[avalue];
else whatever = new String[anothervalue];
The crash occurs if you don't assign a concrete value to each and every field whatever[i]. The rest of the code is now just fine, though I've added Selvin's correction
if (c.moveToNext) ...
c.moveToFirst() is not correctly used in my case, as the for iterates count times. If you perform a moveToFirst first, you're always missing the first element pointed by the cursor.

Related

SQL Database error

I have problem while deleting data from database. I have button which is toggle between two states. Adding data to database and removing data from database. Here's the code:
//Method for adding or removing movies in favorite movie database
public long toggleFav(MovieData movieData) {
ContentValues cv = new ContentValues();
boolean favorite = isFav(movieData.getTitle());
if(favorite) {
favDb.delete(FavoriteContract.FavoriteEntry.TABLE_NAME,
FavoriteContract.FavoriteEntry.COLUMN_ID, null);
mFavoriteImage.setImageResource(R.drawable.fav_ic_no);
movieData.setIsFav(false);
Toast.makeText(MovieDetails.this, getString(R.string.remove_fav),
Toast.LENGTH_SHORT).show();
} else {
cv.put(FavoriteContract.FavoriteEntry.COLUMN_ID, movieData.getMovieId());
cv.put(FavoriteContract.FavoriteEntry.COLUMN_POSTER, movieData.getPoster());
cv.put(FavoriteContract.FavoriteEntry.COLUMN_TITLE, movieData.getTitle());
cv.put(FavoriteContract.FavoriteEntry.COLUMN_RELEASE_DATE, movieData.getReleaseDate());
cv.put(FavoriteContract.FavoriteEntry.COLUMN_AVERAGE_VOTE, movieData.getRating());
cv.put(FavoriteContract.FavoriteEntry.COLUMN_SYNOPSIS, movieData.getSynopsis());
mFavoriteImage.setImageResource(R.drawable.fav_ic_selected);
Toast.makeText(MovieDetails.this, getString(R.string.add_fav),
Toast.LENGTH_SHORT).show();
}
return favDb.insert(FavoriteContract.FavoriteEntry.TABLE_NAME, null, cv);
}
On first click data is saved perfectly, but on second click data ''is removed'' but I get this strange error ...
04-05 14:57:18.540 11162-11162/com.example.android.popularmovies1 E/SQLiteLog: (1) near "null": syntax error
04-05 14:57:18.541 11162-11162/com.example.android.popularmovies1 E/SQLiteDatabase: Error inserting
android.database.sqlite.SQLiteException: near "null": syntax error (code 1): , while compiling: INSERT INTO fav_movies(null) VALUES (NULL)
Also, I have activity were I can see saved data, and if click button for saving it is listed on that activity. The problem is if I from database activity remove data from database, that data removes only when I leave that activity and then go back ...
Here's provider for database
public class FavoritesProvider extends ContentProvider {
public static final int FAVORITES = 100;
public static final int FAVORITES_WITH_ID = 101;
private FavoriteDbHelper mFavoriteDbHelper;
private static final UriMatcher sUriMatcher = buildUriMatcher();
public static UriMatcher buildUriMatcher() {
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(FavoriteContract.AUTHORITY, FavoriteContract.FAV_PATH, FAVORITES);
uriMatcher.addURI(FavoriteContract.AUTHORITY,
FavoriteContract.FAV_PATH + "/#", FAVORITES_WITH_ID);
return uriMatcher;
}
#Override
public boolean onCreate() {
Context context = getContext();
mFavoriteDbHelper = new FavoriteDbHelper(context);
return true;
}
#Nullable
#Override
public Cursor query(#NonNull Uri uri, #Nullable String[] projection, #Nullable String selection,
#Nullable String[] selectionArgs, #Nullable String sortOrder) {
final SQLiteDatabase db = mFavoriteDbHelper.getReadableDatabase();
int match = sUriMatcher.match(uri);
Cursor retCursor;
switch(match) {
case FAVORITES:
retCursor = db.query(FavoriteContract.FavoriteEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder);
break;
case FAVORITES_WITH_ID:
String id = uri.getPathSegments().get(1);
String mSelection = FavoriteContract.FavoriteEntry.COLUMN_ID;
String[] mSelectionArgs = new String[]{id};
retCursor = db.query(FavoriteContract.FavoriteEntry.TABLE_NAME,
projection,
mSelection,
mSelectionArgs,
null,
null,
sortOrder);
break;
default:
throw new UnsupportedOperationException("Uknown uri: " + uri);
}
retCursor.setNotificationUri(getContext().getContentResolver(), uri);
return retCursor;
}
#Nullable
#Override
public String getType(#NonNull Uri uri) {
int match = sUriMatcher.match(uri);
switch(match) {
case FAVORITES:
return "vnd.android.cursor.dir" + "/" + FavoriteContract.AUTHORITY + "/" +
FavoriteContract.FAV_PATH;
case FAVORITES_WITH_ID:
return "vnd.android.cursor.item" + "/" + FavoriteContract.AUTHORITY + "/" +
FavoriteContract.FAV_PATH;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
}
#Nullable
#Override
public Uri insert(#NonNull Uri uri, ContentValues values) {
final SQLiteDatabase db = mFavoriteDbHelper.getWritableDatabase();
int match = sUriMatcher.match(uri);
Uri retUri;
switch(match) {
case FAVORITES:
long id = db.insert(FavoriteContract.FavoriteEntry.TABLE_NAME,
null, values);
if(id > 0) {
retUri = ContentUris.withAppendedId(FavoriteContract
.FavoriteEntry.CONTENT_URI, id);
} else {
throw new android.database.SQLException("Failed to insert row into " + id);
}
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return retUri;
}
#Override
public int delete(#NonNull Uri uri, String selection,
String[] selectionArgs) {
final SQLiteDatabase db = mFavoriteDbHelper.getWritableDatabase();
int match = sUriMatcher.match(uri);
int favDeleted;
switch(match) {
case FAVORITES_WITH_ID:
String id = uri.getPathSegments().get(1);
favDeleted = db.delete(FavoriteContract.FavoriteEntry.TABLE_NAME,
FavoriteContract.FavoriteEntry.COLUMN_ID, new String[]{id});
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
if(favDeleted != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return favDeleted;
}
#Override
public int update(#NonNull Uri uri, #Nullable ContentValues values,
#Nullable String selection, #Nullable String[] selectionArgs) {
int match = sUriMatcher.match(uri);
int favUpdated;
switch(match) {
case FAVORITES_WITH_ID:
String id = uri.getPathSegments().get(1);
favUpdated = mFavoriteDbHelper.getWritableDatabase().update(
FavoriteContract.FavoriteEntry.TABLE_NAME, values,
FavoriteContract.FavoriteEntry.COLUMN_ID, new String[]{id});
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
if(favUpdated != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return favUpdated;
}
}
When the if statement is executed (favourite = true), nothing is added to your content values, and then in the last line you try insert into the database with no values, maybe just return -1 in the last bit of the if statement and move the final return statement into the else
maybe like this
public long toggleFav(MovieData movieData) {
boolean favorite = isFav(movieData.getTitle());
if(favorite) {
favDb.delete(FavoriteContract.FavoriteEntry.TABLE_NAME, FavoriteContract.FavoriteEntry.COLUMN_ID, null);
mFavoriteImage.setImageResource(R.drawable.fav_ic_no);
movieData.setIsFav(false);
Toast.makeText(MovieDetails.this, getString(R.string.remove_fav), Toast.LENGTH_SHORT).show();
return -1; // favourite deleted
} else {
ContentValues cv = new ContentValues();
cv.put(FavoriteContract.FavoriteEntry.COLUMN_ID, movieData.getMovieId());
cv.put(FavoriteContract.FavoriteEntry.COLUMN_POSTER, movieData.getPoster());
cv.put(FavoriteContract.FavoriteEntry.COLUMN_TITLE, movieData.getTitle());
cv.put(FavoriteContract.FavoriteEntry.COLUMN_RELEASE_DATE, movieData.getReleaseDate());
cv.put(FavoriteContract.FavoriteEntry.COLUMN_AVERAGE_VOTE, movieData.getRating());
cv.put(FavoriteContract.FavoriteEntry.COLUMN_SYNOPSIS, movieData.getSynopsis());
mFavoriteImage.setImageResource(R.drawable.fav_ic_selected);
Toast.makeText(MovieDetails.this, getString(R.string.add_fav), Toast.LENGTH_SHORT).show();
return favDb.insert(FavoriteContract.FavoriteEntry.TABLE_NAME, null, cv);
}
}

How to Dynamically Refresh ListFragment when Item is Deleted while Using SimpleCursorAdapter

So I am trying to refresh a list fragment when an item is deleted. The way I have it right now restarts the loader which causes a stutter in the UI when the loader is actually restarting.
I am restarting the loader in the listViewLongClick() method.
Here is my code for the adapter and list fragment:
public class EntriesListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {
private SimpleCursorAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_entries_list, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initButton();
fillData();
listViewLongClick()
}
private void listViewLongClick() { assignmentsListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, final View view, int i, long l) {
String entryId = ((TextView) view.findViewById(R.id.assignment_id)).getText().toString();
Uri uri = ElicitContract.Assignments.buildAssignmentIdUri(assignmentId);
mContentResolver.delete(uri, null, null);
getLoaderManager().restartLoader(0, null, AssignmentsListFragment.this);
fillData();
return true;
});
}
private void fillData() {
String[] from = new String[]{EntriesContract.EntriesColumns.ENTRIES_TITLE, EntriesContract.EntriesColumns.ENTRIES_DETAIL};
int[] to = new int[]{R.id.entries_title, R.id.entries_description};
getLoaderManager().initLoader(0, null, this);
adapter = new SimpleCursorAdapter(getActivity(), R.layout.custom_entries, null, from, to, 0);
setListAdapter(adapter);
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = {EntriesContract.EntriesColumns.ENTRIES_ID, EntriesContract.EntriesColumns.ENTRIES_TITLE, EntriesContract.EntriesColumns.ENTRIES_DETAIL};
CursorLoader cursorLoader = new CursorLoader(getActivity(), EntriesContract.ENTRIES_BASE_CONTENT_URI, projection, null, null, null);
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
adapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
adapter.swapCursor(null);
}
#Override
public void onResume() {
super.onResume();
fillData();
}
}
Here is my content provider code:
public class ElicitProvider extends ContentProvider {
private static final String TAG = ElicitProvider.class.getSimpleName();
private EntriesDatabase entriesDatabase; // Get a copy of the database.
private static final UriMatcher sUriMatcher = buildUriMatcher();
private static final int ENTRIES = 1;
private static final int ENTRIES_ID = 2;
private static UriMatcher buildUriMatcher() {
final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
final String authority = EntriesContract.CONTENT_AUTHORITY;
matcher.addURI(authority, "entries", ENTRIES);
matcher.addURI(authority, "entries/*", ENTRIES_ID);
return matcher;
}
#Override
public boolean onCreate() {
entriesDatabase = new EntriesDatabase(getContext()); // Creating a new instance of the Elicit Database.
return true;
}
#Override
public String getType(Uri uri) {
final int match = sUriMatcher.match(uri);
switch (match) {
case ENTRIES:
return EntriesContract.Entries.CONTENT_ENTRIES_TYPE;
case ENTRIES_ID:
return EntriesContract.Entries.CONTENT_ENTRIES_ITEM_TYPE;
default:
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
final SQLiteDatabase db = entriesDatabase.getReadableDatabase();
final int match = sUriMatcher.match(uri);
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(EntriesContract.ENTRIES_PATH);
switch (match) {
case ENTRIES:
break;
case ENTRIES_ID:
String id = EntriesContract.Entries.getEntryId(uri);
queryBuilder.appendWhere(BaseColumns._ID + "=" + id);
break;
default:
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
return cursor;
}
#Override
public Uri insert(Uri uri, ContentValues contentValues) {
final SQLiteDatabase db = entriesDatabase.getWritableDatabase();
final int match = sUriMatcher.match(uri);
long recordId;
switch (match) {
case ENTRIES:
recordId = db.insertOrThrox(EntriesDatabase.Tables.ENTRIES, null, contentValues);
return EntriesContract.Entxies.buildentryIdUri(String.valueOf(recordId));
default:
throw new IllegalArgumentEception("Unknown Uri: " + uri);
}
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
if (uri.equals(EntriesContract.BASE_CONTENT_URI)) {
deleteDatabase();x
return 0;
}
final SQLiteDatabase db = entriesDatabase.getWritableDatabase();
final int match = sUriMatcher.match(uri);
switch (match) {
case ENTRIES_ID:
String id = uri.getLastPathSegment();
String selectionCriteria = BaseColumns._ID + "=" + id + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : "");
return db.delete(EntriesDatabase.Tables.ENTRIES, selectionCriteria, selectionArgs);
default:
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
}
#Override
public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) {
final SQLiteDatabase db = entriesDatabase.getWritableDatabase();
final int match = sUriMatcher.match(uri);
String selectionCriteria = selection;
switch (match) {
case ENTRIES:
break;
case ENTRIES_ID:
String id = EntriesContract.Entries.getentryId(uri);
selectionCriteria = BaseColumns._ID + "=" + id + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : "");
break;
default:
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
int updateCount = db.update(EntriesDatabase.Tables.ENTRIES, contentValues, selectionCriteria, selectionArgs);
return updateCount;
}
// Delete the instance of the database and create a new one
public void deleteDatabase() {
entriesDatabase.close();
EntriesDatabase.deleteDatabase(getContext());
entriesDatabase = new EntriesDatabase(getContext());
}
}
I am also thinking that this is not the most efficient method of refreshing a list fragment.
I took a look at other similar issues and they said to use entriesListView.notifyDataSetChanged() but I don't know where to put it and how to use it because if I replace this line with getLoaderManager().restartLoader then it gives me a null pointer error.
To summarize, my question is how would I dynamically refresh a listFragment without restarting the loader which I think is less efficient and causes a stutter in the UI.
Thank you to everyone in advance for helping me out!

Table mismatch when selecting thumbnails from a specific Album in Android

I'm using the CursorJoiner to Join the Media.Image and Thumbnail table in order to select Thumbnails from a specific Album without resorting to actual SQL.
However, there seems to be a mismatch between the data in the Media.Image table and in the corresponding Thumbnails table. There are always less Thumbnails then there are actual images (but I know the thumbnails exists on disk).
I'm using the following code:
public ThumbnailSelector(Context context) {
mContext = context;
}
public List<LocalThumbnail<Integer>> getSqlThumbnailsFromBucket(String bucket) {
return null;
}
protected Cursor getImageMediaCursor(String bucket) {
String[] projection = { Media._ID, Media.BUCKET_DISPLAY_NAME };
String selection = String.format("(%s='%s')", Media.BUCKET_DISPLAY_NAME, bucket);
Cursor cursor = mContext.getContentResolver().query(Media.EXTERNAL_CONTENT_URI, projection,
selection, null, Media._ID + " ASC");
cursor.moveToFirst();
return cursor;
}
protected Cursor getImageThumbnailCursor() {
String[] projection = { Thumbnails.IMAGE_ID, Thumbnails.DATA };
String selection = String.format("%s=%d", Thumbnails.KIND, Thumbnails.MINI_KIND);
Cursor cursor = mContext.getContentResolver().query(Thumbnails.EXTERNAL_CONTENT_URI,
projection, selection, null, Thumbnails.IMAGE_ID + " ASC");
cursor.moveToFirst();
return cursor;
}
public List<LocalThumbnail<Integer>> getThumbnailsFromBucket(String bucket) {
List<LocalThumbnail<Integer>> thumbnails = new ArrayList<LocalThumbnail<Integer>>();
Cursor imageThumbnailCursor = getImageThumbnailCursor();
Cursor imageMediaCursor = getImageMediaCursor(bucket);
CursorJoiner joiner = new CursorJoiner(imageMediaCursor, new String[] { Media._ID },
imageThumbnailCursor, new String[] { Thumbnails.IMAGE_ID });
int idColumnIndex = imageThumbnailCursor.getColumnIndex(Thumbnails.IMAGE_ID);
int dataColumnIndex = imageThumbnailCursor.getColumnIndex(Thumbnails.DATA);
for (CursorJoiner.Result joinerResult : joiner) {
switch (joinerResult) {
case RIGHT: {
break;
}
case LEFT: {
break;
}
case BOTH:
thumbnails.add(new LocalThumbnail<Integer>(imageThumbnailCursor
.getInt(idColumnIndex), "file://"
+ imageThumbnailCursor.getString(dataColumnIndex)));
break;
}
}
imageThumbnailCursor.close();
imageMediaCursor.close();
return thumbnails;
}
Anyone know why this mismatch happens?

How can I read the favorites contacts inside service?

I am looking for a way to get the contacts in the favorites list inside service from phone number or from name it dose not matter. Can any one help me with this?
It's not important to use any code related to this code
I found in the developer.android.com something like this (IN_VISIBLE_GROUP).
How to use this variable in my case?
case (PICK_CONTACT):
if (resultCode == Activity.RESULT_OK) {
Uri contactData = data.getData();
Cursor c = managedQuery(contactData, null, null, null, null);
ContentResolver cr = getContentResolver();
if (c.moveToFirst()) {
String name = c.getString(c.getColumnIndexOrThrow(People.NAME));
String id =c.getString(c.getColumnIndexOrThrow(People._ID));
Cursor phones = cr.query(Phone.CONTENT_URI, null,
Phone.CONTACT_ID + " = " + id, null, null);
}
Lets assume that you are searching a contact by name..
If you want to get Favourite value of all the possible contacts , drop the selection parameter in the given code.
//First get the contact ID from a display name as:-
String displayName = "Albert Einstein";
Uri contacts = ContactsContract.Contacts.CONTENT_URI;
cur = cr.query(contacts, null, ContactsContract.Contacts.DISPLAY_NAME +"="+displayName,null, null);
int contactIdIndex = cur.getColumnIndex(ContactsContract.PhoneLookup._ID);
int contactId = cur.getInt(contactIdIndex);
//Make a query to get the Starred value:-
Cursor starred = cr.query(ContactsContract.Contacts.CONTENT_URI,
new String[] { ContactsContract.Contacts.STARRED },
ContactsContract.Contacts._ID + " = " + contactId,
null, null);
if (starred != null && starred.moveToFirst())
{
int fav = starred.getInt(0);
}
if (starred != null)
starred.close();
}
You can drop the step of getting Contact ID and then querying for Starred value and directly query based on Display name
Something like this?
final private static class DataQuery {
public static final int COLUMN_MIMETYPE = 1;
public static final int COLUMN_PHONE = 2;
public static final int COLUMN_RAWCONTACT_ID = 3;
public static final int COLUMN_PHONE_NUMBER = COLUMN_DATA1;
public static final String[] PROJECTION = new String[] { Data._ID, Data.MIMETYPE, Data.DATA1, Data.RAW_CONTACT_ID };
public static final String SELECTION_PHONE = Data.DATA1 + "=?";
}
long findContact(Context context, String number) {
long rawContactId = -1;
final Cursor cursor = context.getContentResolver().query(Data.CONTENT_URI, DataQuery.PROJECTION, DataQuery.SELECTION_PHONE, new String[] { number }, null);
try {
if (cursor.moveToFirst()) {
rawContactId = cursor.getLong(DataQuery.COLUMN_RAWCONTACT_ID);
}
} finally {
if (cursor != null)
cursor.close();
}
return rawContactId;
}
Ok let's try with this...
private static final Uri DATAGROUP_CONTENT_URI = ContactsContract.Data.CONTENT_URI.buildUpon().appendQueryParameter(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE).build();
public static void querytGroups(Context context) {
final ContentResolver resolver = context.getContentResolver();
long groupid=getGroupId(resolver, "Family");
final Cursor c = resolver.query(DATAGROUP_CONTENT_URI, DataQueryForContactsInGroup.PROJECTION, DataQueryForContactsInGroup.SELECTION, new String[] {ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE, String.valueOf(groupid)}, null);
try {
while (c.moveToNext()) {
final long rawContactId = c.getLong(DataQueryForContactsInGroup.RAW_CONTACT_ID);
//do something
}
}finally {
c.close();
}
}
private static long getGroupId(final ContentResolver resolver, String groupName) {
long groupid = -1;
Cursor cur = null;
try {
cur = resolver.query(Groups.CONTENT_URI, DataQueryForGroup.PROJECTION, DataQueryForGroup.SELECTION, new String[]{"%"+groupName+"%"}, null);
while (cur.moveToNext()) {
return groupid= cur.getLong(DataQueryForGroup.GROUP_ID);
}
}finally {
if (cur!=null) cur.close();
}
return groupid;
}
private interface DataQueryForGroup {
public final static String[] PROJECTION = new String[] {Groups._ID};
public static final String SELECTION = Groups.TITLE+" LIKE ?";
public final static int GROUP_ID = 0;
}
private interface DataQueryForContactsInGroup {
public final static String[] PROJECTION = new String[] { Data.RAW_CONTACT_ID };
public static final String SELECTION = "("+Data.MIMETYPE + "=?) and ("+ ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID+ "=?)";
public final static int RAW_CONTACT_ID = 0;
}
Please consider that if your google account is not English you need to look for the proper group's name

Android: Content resolver query returning 0 rows when it ought not to

Cursor cursor = resolver.query(
Data.CONTENT_URI,
DataQuery.PROJECTION,
DataQuery.SELECTION,
new String[] {String.valueOf(rawContactId)},
null);
With PROJECTION being:
public static final String[] PROJECTION = new String[] {
Data._ID,
Data.MIMETYPE,
Data.DATA1,
Data.DATA2,
Data.DATA3};
and SELECTION being:
public static final String SELECTION = Data.RAW_CONTACT_ID + "=?";
The rawcontactId does return values, I've made logs to check. To give it some context I'm working with Account sync. The goal here is for it to find the data columns for existing contacts and writing over them with any new data. I'm working from the following sample code provided by android: http://developer.android.com/resources/samples/SampleSyncAdapter/src/com/example/android/samplesync/platform/ContactManager.html
To summarize my problem, I have two contacts via this synced account which are added without any problems, but are not being able to be updated. Anyone have experience with this? Thanks.
EDIT: Here is my rawContact returning method
private static long lookupRawContact(ContentResolver resolver, String username) {
Log.e("Looking up Raw Contact", username);
long authorId = 0;
Cursor cursor = resolver.query(
Data.CONTENT_URI,
UserIdQuery.PROJECTION,
UserIdQuery.SELECTION,
new String[] {username},
null);
try {
if(cursor != null && cursor.moveToFirst()) {
authorId = cursor.getLong(UserIdQuery.COLUMN_ID);
}
} finally {
if(cursor != null) {
cursor.close();
}
}
return authorId;
}
The numbers I get back are like 3061. Here is the UserIdQuery class:
final private static class UserIdQuery {
private UserIdQuery() {
}
public final static String[] PROJECTION = new String[] {RawContacts._ID};
public final static int COLUMN_ID = 0;
public static final String SELECTION = RawContacts.ACCOUNT_TYPE + "='" +
"com.tagapp.android" + "' AND " + RawContacts.SOURCE_ID + "=?";
}
And here is my constructor for a ContactSyncOperations class being used to add a new contact. The source id here is a username, the same as I call in my SELECTION argument.
public ContactSyncOperations(Context context, String username,
String accountName, BatchOperationForSync batchOperation) {
this(context, batchOperation);
mBackReference = mBatchOperation.size();
mIsNewContact = true;
mValues.put(RawContacts.SOURCE_ID, username);
mValues.put(RawContacts.ACCOUNT_TYPE, "com.tagapp.android");
mValues.put(RawContacts.ACCOUNT_NAME, accountName);
mBuilder = newInsertCpo(RawContacts.CONTENT_URI, true).withValues(mValues);
mBatchOperation.add(mBuilder.build());
}
Thanks!
There was an error in the lookupRawContactId method, the rawcontactId long I was getting wasn't the right one. It should have looked like this:
private static long lookupRawContact(ContentResolver resolver, String username) {
Log.e("Looking up Raw Contact", username);
long authorId = 0;
Cursor cursor = resolver.query(
RawContacts.CONTENT_URI,
UserIdQuery.PROJECTION,
UserIdQuery.SELECTION,
new String[] {username},
null);
try {
if(cursor != null && cursor.moveToFirst()) {
authorId = cursor.getLong(UserIdQuery.COLUMN_ID);
}
} finally {
if(cursor != null) {
cursor.close();
}
}
return authorId;
}
There are a few issues that i could locate with the following query:
Cursor cursor = resolver.query(Data.CONTENT_URI,
UserIdQuery.PROJECTION,
UserIdQuery.SELECTION,
new String[] {username}, null);
If all the columns are pointing out at RawContacts table then you should use RawContacts.CONTENT_URI instead of Data.CONTENT_URI.
Here the value of RawContacts.SOURCE_ID is compared with username
public static final String SELECTION = RawContacts.ACCOUNT_TYPE + "='" +
"com.tagapp.android" + "' AND " + RawContacts.SOURCE_ID + "=?";
new String[] {username}

Categories

Resources