Way to get ParseObjects to custom Search suggestions in Android - android

I want to ask, if is there some way to get ParseObjects to Search suggestions-box in Android. I've succesully created recent-query suggestions and it worked well. But right now do I need to put there one string collection from Parse.com while the user is typing -show results, which contain the query which is being typed. I am kind of desperated because I've been searching for it for a week and no result.
Do you have any idea, how to accomplish that?
My in normal ParseQuery in SearchActivity:
ParseQuery<Animal> squery = ParseQuery.getQuery(Animal.class);
squery.whereMatches("animal", query, "i");
squery.findInBackground(new FindCallback<Animal>() {
#Override
public void done(List<Animal> animals, ParseException error) {
if(animals != null){
nAdapter.clear();
for (int i = 0; i < animals.size(); i++) {
mProgressBar = (ProgressBar) findViewById(R.id.search_loading_animals);
mProgressBar.setVisibility(View.INVISIBLE);
nAdapter.add(animals.get(i));
}
}
}
});
SuggestionAdapter to which do i need to implement the ParseQuery:
public class SuggestionProvider extends ContentProvider {
private static final String TAG = "SuggestionProvider";
private static final int SEARCH_SUGGESTIONS = 1;
private static final UriMatcher sURLMatcher = new UriMatcher(
UriMatcher.NO_MATCH);
static {
sURLMatcher.addURI("*", SearchManager.SUGGEST_URI_PATH_QUERY,
SEARCH_SUGGESTIONS);
sURLMatcher.addURI("*", SearchManager.SUGGEST_URI_PATH_QUERY + "/*",
SEARCH_SUGGESTIONS);
}
private static final String[] COLUMNS = new String[] {
"_id",
SearchManager.SUGGEST_COLUMN_TEXT_1,
SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
SearchManager.SUGGEST_COLUMN_QUERY
};
public SuggestionProvider() {
}
#Override
public boolean onCreate() {
return true;
}
#Override
public Cursor query(Uri url, String[] projectionIn, String selection,
String[] selectionArgs, String sort) {
int match = sURLMatcher.match(url);
switch (match) {
case SEARCH_SUGGESTIONS:
String query = url.getLastPathSegment();
MatrixCursor cursor = new MatrixCursor(COLUMNS);
String[] suffixes = { "", "a", " foo", "XXXXXXXXXXXXXXXXX" };
for (String suffix : suffixes) {
Toast.makeText(getContext(), "", Toast.LENGTH_SHORT).show();
addRow(cursor, query + suffix);
}
return cursor;
default:
throw new IllegalArgumentException("Unknown URL: " + url);
}
}
private void addRow(MatrixCursor cursor, String string) {
long id = cursor.getCount();
cursor.newRow().add(id).add(string).add(Intent.ACTION_SEARCH).add(string);
}
#Override
public String getType(Uri url) {
int match = sURLMatcher.match(url);
switch (match) {
case SEARCH_SUGGESTIONS:
return SearchManager.SUGGEST_MIME_TYPE;
default:
throw new IllegalArgumentException("Unknown URL: " + url);
}
}
#Override
public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
throw new UnsupportedOperationException("update not supported");
}
#Override
public Uri insert(Uri url, ContentValues initialValues) {
throw new UnsupportedOperationException("insert not supported");
}
#Override
public int delete(Uri url, String where, String[] whereArgs) {
throw new UnsupportedOperationException("delete not supported");
}
}

Related

contentProvider and search by name and not ID Android

it's the first time I'm using the content provider.
so I have this:
public class ContactsContentProvider extends ContentProvider {
private ContactsDatabaseHelper dbHelper;
private static final UriMatcher uriMatcher =
new UriMatcher(UriMatcher.NO_MATCH);
private static final int ONE_CONTACT = 1;
private static final int CONTACTS = 2;
private static final int CONTACT = 3;
static {
uriMatcher.addURI(ContactsDatabaseDescription.AUTHORITY,
Contact.TABLE_NAME + "/#", ONE_CONTACT);
uriMatcher.addURI(ContactsDatabaseDescription.AUTHORITY,
Contact.TABLE_NAME, CONTACTS);
uriMatcher.addURI(ContactsDatabaseDescription.AUTHORITY,
Contact.TABLE_NAME + "/*" , CONTACT);
}
#Override
public boolean onCreate() {
dbHelper = new ContactsDatabaseHelper(getContext());
return true;
}
#Override
public String getType(Uri uri) {
return null;
}
#Override
public Cursor query(Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(Contact.TABLE_NAME);
switch (uriMatcher.match(uri)) {
case ONE_CONTACT:
queryBuilder.appendWhere(
Contact._ID + "=" + uri.getLastPathSegment());
break;
case CONTACTS:
break;
default:
throw new UnsupportedOperationException(
getContext().getString(R.string.invalid_query_uri) + uri);
}
Cursor cursor = queryBuilder.query(dbHelper.getReadableDatabase(),
projection, selection, selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
// insert a new contact in the database
#Override
public Uri insert(Uri uri, ContentValues values) {
Uri newContactUri = null;
switch (uriMatcher.match(uri)) {
case CONTACTS:
// insert the new contact--success yields new contact's row id
long rowId = dbHelper.getWritableDatabase().insert(
Contact.TABLE_NAME, null, values);
if (rowId > 0) {
newContactUri = Contact.buildContactUri(rowId);
getContext().getContentResolver().notifyChange(uri, null);
}
else
throw new SQLException(
getContext().getString(R.string.insert_failed) + uri);
break;
default:
throw new UnsupportedOperationException(
getContext().getString(R.string.invalid_insert_uri) + uri);
}
return newContactUri;
}
#Override
public int update(Uri uri, ContentValues values,
String selection, String[] selectionArgs) {
int numberOfRowsUpdated; // 1 if update successful; 0 otherwise
switch (uriMatcher.match(uri)) {
case ONE_CONTACT:
String id = uri.getLastPathSegment();
numberOfRowsUpdated = dbHelper.getWritableDatabase().update(
Contact.TABLE_NAME, values, Contact._ID + "=" + id,
selectionArgs);
break;
default:
throw new UnsupportedOperationException(
getContext().getString(R.string.invalid_update_uri) + uri);
}
if (numberOfRowsUpdated != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return numberOfRowsUpdated;
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int numberOfRowsDeleted;
switch (uriMatcher.match(uri)) {
case ONE_CONTACT:
String id = uri.getLastPathSegment();
numberOfRowsDeleted = dbHelper.getWritableDatabase().delete(
Contact.TABLE_NAME, Contact._ID + "=" + id, selectionArgs);
break;
default:
throw new UnsupportedOperationException(
getContext().getString(R.string.invalid_delete_uri) + uri);
}
if (numberOfRowsDeleted != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return numberOfRowsDeleted;
}
}
My database is
public class ContactsDatabaseDescription {
public static final String AUTHORITY =
"com.example.afran.bdcontacts.data";
private static final Uri BASE_CONTENT_URI =
Uri.parse("content://" + AUTHORITY);
public static final class Contact implements BaseColumns {
public static final String TABLE_NAME = "contacts"; // table's name
public static final Uri CONTENT_URI =
BASE_CONTENT_URI.buildUpon().appendPath(TABLE_NAME).build();
public static final String COLUMN_FIRST_NAME = "firstName";
public static final String COLUMN_LAST_NAME = "lastName";
public static final String COLUMN_EMAIL = "email";
public static final String COLUMN_TYPE = "type";
public static Uri buildContactUri(long id) {
return ContentUris.withAppendedId(CONTENT_URI, id);
}
}
}
and on this fragment I read one last name (search) and I want to find the contact and I do not know how
public class DetailFragment extends Fragment
implements LoaderManager.LoaderCallbacks<Cursor> {
public interface DetailFragmentListener {
void onContactDeleted();
void onEditContact(Uri contactUri);
}
private static final int CONTACT_LOADER = 0;
private DetailFragmentListener listener;
private Uri contactUri;
private TextView prenomTextView;
private TextView nomTextView;
private TextView emailTextView;
private TextView typeTextView;
#Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (DetailFragmentListener) context;
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
setHasOptionsMenu(true);
Bundle arguments = getArguments();
if (arguments != null)
contactUri = arguments.getParcelable(MainActivity.CONTACT_URI);
View view =
inflater.inflate(R.layout.fragment_detail, container, false);
prenomTextView = (TextView) view.findViewById(R.id.firstNameTextView);
nomTextView = (TextView) view.findViewById(R.id.lastNameTextView);
emailTextView = (TextView) view.findViewById(R.id.emailTextView);
typeTextView = (TextView) view.findViewById(R.id.typeTextView);
getLoaderManager().initLoader(CONTACT_LOADER, null, this);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_main, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_edit:
listener.onEditContact(contactUri);
return true;
case R.id.action_delete:
deleteContact();
return true;
case R.id.action_search:
searchContact();
return true;
}
return super.onOptionsItemSelected(item);
}
private void searchContact() {
final EditText input = new EditText(getContext());
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.menuitem_recherche);
builder.setMessage(R.string.label_lastName);
builder.setView(input);
builder.setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int whichButton) {
String value = input.getText().toString();
return;
}
});
builder.setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
return;
}
});
builder.create().show();
}
private void deleteContact() {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.confirm_title);
builder.setMessage(R.string.confirm_message);
builder.setPositiveButton(R.string.button_delete, new DialogInterface.OnClickListener() {
#Override
public void onClick(
DialogInterface dialog, int button) {
getActivity().getContentResolver().delete(
contactUri, null, null);
listener.onContactDeleted();
}
}
);
builder.setNegativeButton(R.string.button_cancel, null);
builder.create().show();
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
CursorLoader cursorLoader;
switch (id) {
case CONTACT_LOADER:
cursorLoader = new CursorLoader(getActivity(),
contactUri,
null,
null,
null,
null);
break;
default:
cursorLoader = null;
break;
}
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (data != null && data.moveToFirst()) {
int firstIndex = data.getColumnIndex(ContactsDatabaseDescription.Contact.COLUMN_FIRST_NAME);
int lastIndex = data.getColumnIndex(ContactsDatabaseDescription.Contact.COLUMN_LAST_NAME);
int emailIndex = data.getColumnIndex(ContactsDatabaseDescription.Contact.COLUMN_EMAIL);
int typeIndex = data.getColumnIndex(ContactsDatabaseDescription.Contact.COLUMN_TYPE);
prenomTextView.setText(data.getString(firstIndex));
nomTextView.setText(data.getString(lastIndex));
emailTextView.setText(data.getString(emailIndex));
typeTextView.setText(data.getString(typeIndex));
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) { }
}
It is simple to search for a match of any column in your table. You simply need the contentUri, and where and whereArgs parameters for the query. Ensure your Uri points to the whole table. Assuming you want to match columns called "first_name" and "surname" with Strings called firstName and surname.
String where = "first_name =? and surname =?";
String[] whereArgs = {firstName, surname};
You can use parentheses and "and" and "or" to construct more complex queries. With numerical fields you can use > and < etc. You must ensure whereArgs has as many elements as where has "?"

Recyclerview not refreshing

I am working on a project where user adds data at runtime.The problem is whenever user inserts the fist element it is adding to the database and displaying in recyclerview.But when user adds more data the recyclerview keeps displaying firstelement over and over again.
If the user adds Apple it is adding to database and recyclerview is displaying Apple.Now if the user adds orange it is adding to database but the recyclerview is displaying Apple two times.
I am using Cursorloader to load data,Contentprovider to add data,and CustomCursoradapter(https://gist.github.com/skyfishjy/443b7448f59be978bc59) to set the data to recyclerview
addDetails() method execute when user adds data
public class AddLog extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>{
TextView TotalAmount,Date;
EditText name,mobile,city,detailname,detailamount;
RecyclerView adddetailtolist;
DetailsAdapter adapter;
Intent returnback;
double totamount;
long logid;
String Debt = "Debt";
String Paid = "Paid";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_log);
Toolbar toolbar = (Toolbar)findViewById(R.id.addlogtoolbar);
setSupportActionBar(toolbar);
toolbar.setTitle("Add Log");
returnback = new Intent(this,MainActivity.class);
Intent intent = getIntent();
logid = intent.getExtras().getLong("ID");
TotalAmount = (TextView)findViewById(R.id.totalAmount);
Date = (TextView)findViewById(R.id.addlogDate);
name = (EditText)findViewById(R.id.AddName);
mobile = (EditText)findViewById(R.id.AddPhone);
city = (EditText)findViewById(R.id.Addcity);
detailname = (EditText)findViewById(R.id.Detailname);
detailamount = (EditText)findViewById(R.id.Detailamount);
adddetailtolist = (RecyclerView)findViewById(R.id.addloglist);
Date.setText(getDate());
getSupportLoaderManager().initLoader(1,null,this);
adapter = new DetailsAdapter(this,null);
adddetailtolist.setAdapter(adapter);
adddetailtolist.setLayoutManager(new LinearLayoutManager(this));
}
private String getDate()
{
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE,dd-MMM-yyyy");
String date = simpleDateFormat.format(calendar.getTime());
return date;
}
public void addDetails(View view)
{
String Name = detailname.getText().toString();
String Amount = detailamount.getText().toString();
String date = Date.getText().toString();
ContentValues contentValues = new ContentValues();
contentValues.put(DataProvider.Dname,Name);
contentValues.put(DataProvider.DCategory,Debt);
contentValues.put(DataProvider.Damount,Amount);
contentValues.put(DataProvider.Ddate,date);
contentValues.put(DataProvider.Per_In,logid);
Uri uri = getContentResolver().insert(DataProvider.ContentUri_Details,contentValues);
Toast.makeText(AddLog.this, uri.toString()+"Value Inserted", Toast.LENGTH_SHORT).show();
NumberFormat currency = changeamount();
TotalAmount.setText(currency.format(getAmount()));
}
private double getAmount()
{
ContentProviderClient client = getContentResolver().acquireContentProviderClient(DataProvider.ContentUri_Details);
SQLiteDatabase db = ((DataProvider)client.getLocalContentProvider()).sqLiteDatabase;
String query = "SELECT SUM(DAmount) FROM Details WHERE Per_In = "+logid;
Cursor cursor = db.rawQuery(query, null);
cursor.moveToFirst();
double amount = cursor.getDouble(0);
cursor.close();
client.release();
return amount;
}
public NumberFormat changeamount()
{
Locale locale = new Locale("en","IN");
NumberFormat currencyformat = NumberFormat.getCurrencyInstance(locale);
return currencyformat;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuinflate = getMenuInflater();
menuinflate.inflate(R.menu.addlogmenu,menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.done:
saveData();
}
return super.onOptionsItemSelected(item);
}
private void saveData()
{
String name1 = name.getText().toString();
String phone = mobile.getText().toString();
String address = city.getText().toString();
if (TextUtils.isEmpty(name1)||TextUtils.isEmpty(phone)||TextUtils.isEmpty(address))
{
if (TextUtils.isEmpty(name1))
{
name.setError("Feild can not be Empty");
}
else if (TextUtils.isEmpty(phone))
{
mobile.setError("Feild can not be Empty");
}
else if (TextUtils.isEmpty(address))
{
city.setError("Feild can not be Empty");
}
}
else
{
ContentValues values = new ContentValues();
values.put(DataProvider.Pname,name1);
values.put(DataProvider.Pphone,phone);
values.put(DataProvider.Paddress,address);
values.put(DataProvider.PCategory,"Debt");
values.put(DataProvider.Pamount,totamount);
String where = DataProvider.PID+"=?";
String[] whereargs = {String.valueOf(logid)};
int a = getContentResolver().update(DataProvider.ContentUri_Person,values,where,whereargs);
Toast.makeText(AddLog.this, String.valueOf(1)+"Value updated", Toast.LENGTH_SHORT).show();
startActivity(returnback);
finish();
}
}
#Override
public Loader<Cursor> onCreateLoader(final int id, Bundle args)
{
String[] Projection = new String[]{DataProvider.DID,DataProvider.Dname,DataProvider.DCategory,DataProvider.Damount,DataProvider.Ddate};
String selection = DataProvider.Per_In+"=?";
String[] selectionargs = new String[]{String.valueOf(logid)};
return new CursorLoader(this,DataProvider.ContentUri_Details,Projection,selection,selectionargs,null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data)
{
adapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader)
{
adapter.swapCursor(null);
}
}
Content Provider class:
public class DataProvider extends ContentProvider
{
static final String ProviderName = "com.example.mrudu.accounts.provider";
static final String URLPerson = "content://"+ProviderName+"/Person_Detail";
static final String URLDetails = "content://"+ProviderName+"/Details";
static final Uri ContentUri_Person = Uri.parse(URLPerson);
static final Uri ContentUri_Details = Uri.parse(URLDetails);
//Tables
private static String PTableName = "Person_Detail";
private static String DTableName = "Details";
public static long insertId = 0;
//Person_Detail Coloumns
public static String PID = "_id";
public static String Pname = "PName";
public static String Pphone = "PMobile";
public static String Paddress = "PCity";
public static String PCategory = "PCategory";
public static String Pamount = "PAmount";
//Details coloumn
public static String DID = "_id";
public static String Dname = "DName";
public static String Damount = "DAmount";
public static String Ddate = "DDate";
public static String DCategory = "DCategory";
public static String Per_In = "Per_In";
private static final int Person = 1;
private static final int Person_ID = 2;
private static final int Details = 3;
private static final int Details_Id = 4;
static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static
{
uriMatcher.addURI(ProviderName,PTableName,Person);
uriMatcher.addURI(ProviderName,PTableName+"/#",Person_ID);
uriMatcher.addURI(ProviderName,DTableName,Details);
uriMatcher.addURI(ProviderName,DTableName+"/#",Details_Id);
}
public static SQLiteDatabase sqLiteDatabase;
private static String Databasename = "Accounts";
private static int DatabaseVersion = 1;
private class DatabaseHelper extends SQLiteOpenHelper
{
public DatabaseHelper(Context context)
{
super(context, Databasename, null, DatabaseVersion);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase)
{
String Create_Person = " Create Table "+PTableName+"("+PID+" INTEGER PRIMARYKEY ,"+Pname+" TEXT ,"+Pphone+" TEXT ,"+Paddress+" TEXT ,"+PCategory+" TEXT ,"+Pamount+" REAL"+")";
String Create_Details = " Create Table "+DTableName+"("+DID+" INTEGER PRIMARYKEY ,"+Dname+" TEXT ,"+DCategory+" TEXT ,"+Damount+" REAl ,"+Ddate+" TEXT ,"+Per_In+" INTEGER )";
sqLiteDatabase.execSQL(Create_Person);
sqLiteDatabase.execSQL(Create_Details);
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1)
{
sqLiteDatabase.execSQL("Drop TABLE if exists"+PTableName);
sqLiteDatabase.execSQL("Drop TABLE if exists"+DTableName);
onCreate(sqLiteDatabase);
}
}
#Override
public boolean onCreate()
{
Context context = getContext();
DatabaseHelper databaseHelper = new DatabaseHelper(context);
sqLiteDatabase = databaseHelper.getWritableDatabase();
return (sqLiteDatabase==null)?false:true;
}
#Override
public Uri insert(Uri uri, ContentValues values)
{
switch (uriMatcher.match(uri))
{
case Person:
long rowId = sqLiteDatabase.insert(PTableName,null,values);
insertId = rowId;
if (rowId>0)
{
Uri _uri = ContentUris.withAppendedId(ContentUri_Person,rowId);
getContext().getContentResolver().notifyChange(_uri,null);
return _uri;
}
break;
case Details:
long rowId1 = sqLiteDatabase.insert(DTableName,null,values);
if (rowId1>0)
{
Uri _uri = ContentUris.withAppendedId(ContentUri_Details,rowId1);
getContext().getContentResolver().notifyChange(_uri,null);
return _uri;
}
break;
}
return null;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder)
{
SQLiteQueryBuilder sqLiteQueryBuilder = new SQLiteQueryBuilder();
switch (uriMatcher.match(uri))
{
case Person_ID:
sqLiteQueryBuilder.setTables(PTableName);
sqLiteQueryBuilder.appendWhere(PID+ "="+ uri.getPathSegments().get(1));
break;
case Person:
sqLiteQueryBuilder.setTables(PTableName);
break;
case Details_Id:
sqLiteQueryBuilder.setTables(DTableName);
sqLiteQueryBuilder.appendWhere(Per_In +"="+ uri.getPathSegments().get(1));
break;
case Details:
sqLiteQueryBuilder.setTables(DTableName);
break;
default:
throw new UnsupportedOperationException("Not yet implemented");
}
Cursor cursor = sqLiteQueryBuilder.query(sqLiteDatabase,projection,selection,selectionArgs,null,null,sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(),uri);
return cursor;
}
#Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs)
{
int count = 0;
switch (uriMatcher.match(uri))
{
case Person:
count = sqLiteDatabase.update(PTableName,values,selection,selectionArgs);
break;
case Person_ID:
count = sqLiteDatabase.update(PTableName,values,PID+" = "+uri.getPathSegments().get(1)+(!TextUtils.isEmpty(selection)?" AND (" + selection + ')':""),selectionArgs);
break;
case Details:
count = sqLiteDatabase.update(DTableName,values,selection,selectionArgs);
break;
case Details_Id:
count = sqLiteDatabase.update(DTableName,values,Per_In+" = "+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 int delete(Uri uri, String selection, String[] selectionArgs) {
// Implement this to handle requests to delete one or more rows.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public String getType(Uri uri) {
// TODO: Implement this to handle requests for the MIME type of the data
// at the given URI.
throw new UnsupportedOperationException("Not yet implemented");
}
}
Detils class:
public class Details
{
String name,date;
double amount;
public Details(String name, double amount, String date) {
this.name = name;
this.amount = amount;
this.date = date;
}
public Details() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public static Details from(Cursor cursor)
{
cursor.moveToFirst();
do {
Details details = new Details(cursor.getString(1),cursor.getDouble(3),cursor.getString(4));
return details;
}while (cursor.moveToNext());
}
}
Adapter class :
public class DetailsAdapter extends CursorRecyclerViewAdapter<DetailsAdapter.View_Holder>
{
public DetailsAdapter(Context context, Cursor cursor) {
super(context, cursor);
}
public static class View_Holder extends RecyclerView.ViewHolder
{
TextView mName,mAmount,mDate;
public View_Holder(View itemView)
{
super(itemView);
mName = (TextView)itemView.findViewById(R.id.DetailName);
mAmount = (TextView)itemView.findViewById(R.id.DetailAmount);
mDate = (TextView)itemView.findViewById(R.id.DetailDate);
}
}
#Override
public DetailsAdapter.View_Holder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.addloglistlayout,parent,false);
View_Holder viewHolder = new View_Holder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(DetailsAdapter.View_Holder viewHolder, Cursor cursor)
{
Details details = Details.from(cursor);
viewHolder.mName.setText(details.getName());
viewHolder.mAmount.setText(String.valueOf(details.getAmount()));
viewHolder.mDate.setText(details.getDate());
}
}
Cursor Recyclerview Adapter class:
public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
private Context mContext;
private Cursor mCursor;
private boolean mDataValid;
private int mRowIdColumn;
private DataSetObserver mDataSetObserver;
public CursorRecyclerViewAdapter(Context context, Cursor cursor) {
mContext = context;
mCursor = cursor;
mDataValid = cursor != null;
mRowIdColumn = mDataValid ? mCursor.getColumnIndex("_id") : -1;
mDataSetObserver = new NotifyingDataSetObserver();
if (mCursor != null) {
mCursor.registerDataSetObserver(mDataSetObserver);
}
}
public Cursor getCursor() {
return mCursor;
}
#Override
public int getItemCount() {
if (mDataValid && mCursor != null) {
return mCursor.getCount();
}
return 0;
}
#Override
public long getItemId(int position) {
if (mDataValid && mCursor != null && mCursor.moveToPosition(position)) {
return mCursor.getLong(mRowIdColumn);
}
return 0;
}
#Override
public void setHasStableIds(boolean hasStableIds) {
super.setHasStableIds(true);
}
public abstract void onBindViewHolder(VH viewHolder, Cursor cursor);
#Override
public void onBindViewHolder(VH viewHolder, int position) {
if (!mDataValid) {
throw new IllegalStateException("this should only be called when the cursor is valid");
}
if (!mCursor.moveToPosition(position)) {
throw new IllegalStateException("couldn't move cursor to position " + position);
}
onBindViewHolder(viewHolder, mCursor);
}
/**
* Change the underlying cursor to a new cursor. If there is an existing cursor it will be
* closed.
*/
public void changeCursor(Cursor cursor) {
Cursor old = swapCursor(cursor);
if (old != null) {
old.close();
}
}
/**
* Swap in a new Cursor, returning the old Cursor. Unlike
* {#link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em>
* closed.
*/
public Cursor swapCursor(Cursor newCursor) {
if (newCursor == mCursor) {
return null;
}
final Cursor oldCursor = mCursor;
if (oldCursor != null && mDataSetObserver != null) {
oldCursor.unregisterDataSetObserver(mDataSetObserver);
}
mCursor = newCursor;
if (mCursor != null) {
if (mDataSetObserver != null) {
mCursor.registerDataSetObserver(mDataSetObserver);
}
mRowIdColumn = newCursor.getColumnIndexOrThrow("_id");
mDataValid = true;
notifyDataSetChanged();
} else {
mRowIdColumn = -1;
mDataValid = false;
notifyDataSetChanged();
//There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
}
return oldCursor;
}
private class NotifyingDataSetObserver extends DataSetObserver {
#Override
public void onChanged() {
super.onChanged();
mDataValid = true;
notifyDataSetChanged();
}
#Override
public void onInvalidated() {
super.onInvalidated();
mDataValid = false;
notifyDataSetChanged();
//There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
}
}
}
Thank you
Probably from method in Details causing issue due to cursor.moveToFirst(); and do-while loop. change it as:
public static Details from(Cursor cursor)
{
Details details = new Details(cursor.getString(1),
cursor.getDouble(3),
cursor.getString(4));
return details;
}
I have checked your adapter and all, so you are already moving your cursor to particular position from Adapter, so you don't need to set it moveToFist, so just remove the line cursor.moveToFirst() from Details Class and check result.

Android DBFlow and CursorLoader

Anyone knows how to use cursorLoader with DBFlow ? I seen this issue but this is not added to DBFlow.
Thanks.
You can find official docs here or you can implement it the way i have
DBFlow ver used 3
//I have edited my answer & provided easier way for content provider part below
add this to manifest inside application
<provider
android:authorities="com.hashx19.pristinekashmir.mycontentprovider"
android:exported="false"
android:name=".MyContentProvider"/>
Create java file named MyContentProvider & copy below code in it
& replace AUTHORITY ,ENDPOINT, AppDatabase(Your database name) ,TableClassName as per you project.
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.CursorIndexOutOfBoundsException;
import android.net.Uri;
import com.hashx19.pristinekashmir.MySQLiteHelper;
import com.raizlabs.android.dbflow.annotation.ConflictAction;
import com.raizlabs.android.dbflow.config.FlowManager;
import com.raizlabs.android.dbflow.structure.ModelAdapter;
import java.util.Arrays;
import java.util.HashSet;
/**
* Created by Filu on 8/25/2016.
*/
public class MyContentProvider extends ContentProvider {
public static final String AUTHORITY = "com.hashx19.pristinekashmir.mycontentprovider";
private static final String ENDPOOINT = "feeds";
// #ContentUri(path = ENDPOOINT, type = ContentUri.ContentType.VND_MULTIPLE + ENDPOOINT)
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
+ "/" + ENDPOOINT);
private static final int feeds_CONTENT_URI = 0;
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
static {
MATCHER.addURI(AUTHORITY, ENDPOOINT, feeds_CONTENT_URI);
}
;
#Override
public final String getType(Uri uri) {
String type = null;
switch(MATCHER.match(uri)) {
case feeds_CONTENT_URI: {
type = "vnd.android.cursor.dir/" +ENDPOINT;
break;
}
default: {
throw new IllegalArgumentException("Unknown URI" + uri);
}
}
return type;
}
#Override
public boolean onCreate() {
return false;
}
#Override
public final Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
android.database.Cursor cursor = null;
switch(MATCHER.match(uri)) {
case feeds_CONTENT_URI: {
cursor = FlowManager.getDatabase("AppDatabase").getWritableDatabase().query("TableClassName", projection, selection, selectionArgs, null, null, sortOrder);
break;
}
}
if (cursor != null) {
cursor.setNotificationUri(getContext().getContentResolver(), uri);
}
return cursor;
}
#Override
public final Uri insert(Uri uri, ContentValues values) {
switch(MATCHER.match(uri)) {
case feeds_CONTENT_URI: {
ModelAdapter adapter = FlowManager.getModelAdapter(FlowManager.getTableClassForName("AppDatabase", "TableClassName"));
final long id = FlowManager.getDatabase("AppDatabase").getWritableDatabase().insertWithOnConflict("TableClassName", null, values, ConflictAction.getSQLiteDatabaseAlgorithmInt(adapter.getInsertOnConflictAction()));
getContext().getContentResolver().notifyChange(uri, null);
return ContentUris.withAppendedId(uri, id);
}
default: {
throw new IllegalStateException("Unknown Uri" + uri);
}
}
}
#Override
public final int delete(Uri uri, String selection, String[] selectionArgs) {
switch(MATCHER.match(uri)) {
case feeds_CONTENT_URI: {
long count = FlowManager.getDatabase("AppDatabase").getWritableDatabase().delete("TableClassName", selection, selectionArgs);
if (count > 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return (int) count;
}
default: {
throw new IllegalArgumentException("Unknown URI" + uri);
}
}
}
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
switch(MATCHER.match(uri)) {
case feeds_CONTENT_URI: {
ModelAdapter adapter = FlowManager.getModelAdapter(FlowManager.getTableClassForName("AppDatabase", "TableClassName"));
long count = FlowManager.getDatabase("AppDatabase").getWritableDatabase().updateWithOnConflict("TableClassName", values, selection, selectionArgs, ConflictAction.getSQLiteDatabaseAlgorithmInt(adapter.getUpdateOnConflictAction()));
if (count > 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return (int) count;
}
default: {
throw new IllegalStateException("Unknown Uri" + uri);
}
}
}
}
then when overriding Loader methods do something like this
getLoaderManager().initLoader(1, null, this);
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String selection, sortOrder;
String[] selectionArgs, projection;
selection = ...;
selectionArgs = ...;
sortOrder = ...;
projection= new String[]{"id","date", "link","title","content","excerpt","author",};
CursorLoader cursorLoader = new CursorLoader(getContext(),MyContentProvider.CONTENT_URI, projection,null,null,null);
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
TableClass post = new TableClass();
while (!cursor.isAfterLast()) {
try{
post.setId(cursor.getInt(cursor.getColumnIndex("id")));
}catch (NullPointerException e){
e.printStackTrace();
}catch (CursorIndexOutOfBoundsException c){
c.printStackTrace();
}
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
editted
Figured out easier way to implement content provider .
add this to your manifest / or modify this way if you already have added Provider code .
modify your AppDatabase Class as
#ContentProvider(authority = AppDatabase.AUTHORITY,
database = AppDatabase.class,
baseContentUri = AppDatabase.BASE_CONTENT_URI)
#Database(name = AppDatabase.NAME, version = AppDatabase.VERSION)
public class AppDatabase {
public static final String NAME = "AppDatabase"; // we will add the .db extension
public static final int VERSION = 2;
public static final String AUTHORITY = "com.hashx19.pristinekashmir.dbflowcontentprovider";
public static final String BASE_CONTENT_URI = "content://"; }
modify each table you want to use as provider as
#TableEndpoint(name = PostData.ENDPOINT, contentProvider = AppDatabase.class)
#Table(database = AppDatabase.class ,allFields = true ,name = PostData.ENDPOINT)
public class PostData extends BaseModel {
public static final String ENDPOINT = "PostData";
#ContentUri(path = ENDPOINT, type = ContentUri.ContentType.VND_MULTIPLE + ENDPOINT)
public static final Uri CONTENT_URI = Uri.parse(AppDatabase.BASE_CONTENT_URI + AppDatabase.AUTHORITY
+ "/" + ENDPOINT);
#PrimaryKey
public int id;
public String image;
}
For using Content provider as in Cursor Loader use TableName.CONTENT_URI as in this case
CursorLoader cursorLoader = new CursorLoader(getContext(),PostData.CONTENT_URI,projection,null,null,null);

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!

How to add a new table column?

This is my project for Android. I've tried to create a new table column: KEY_EXAMPLE. But it doesn't work. I'll put my code below and I would like to fix this. Can someone help me, please? It's very important. I'm a newbie. The KEY_EXAMPLE doesn't work. This is my code and what I'm trying to do this workout.
DictionaryDatabase.Java
public class DictionaryDatabase {
private static final String TAG = "DictionaryDatabase";
public static final String KEY_WORD = SearchManager.SUGGEST_COLUMN_TEXT_1;
public static final String KEY_DEFINITION = SearchManager.SUGGEST_COLUMN_TEXT_2;
public static final String KEY_EXAMPLE = SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA;
private static final String DATABASE_NAME = "dictionary";
private static final String FTS_VIRTUAL_TABLE = "FTSdictionary";
private static final int DATABASE_VERSION = 3;
private final DictionaryOpenHelper mDatabaseOpenHelper;
private static final HashMap<String,String> mColumnMap = buildColumnMap();
public DictionaryDatabase(Context context) {
mDatabaseOpenHelper = new DictionaryOpenHelper(context);
}
private static HashMap<String,String> buildColumnMap() {
HashMap<String,String> map = new HashMap<String,String>();
map.put(KEY_WORD, KEY_WORD);
map.put(KEY_DEFINITION, KEY_DEFINITION);
map.put(KEY_EXAMPLE, KEY_EXAMPLE);
map.put(BaseColumns._ID, "rowid AS " +
BaseColumns._ID);
map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " +
SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
map.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, "rowid AS " +
SearchManager.SUGGEST_COLUMN_SHORTCUT_ID);
return map;
}
public Cursor getWord(String rowId, String[] columns) {
String selection = "rowid = ?";
String[] selectionArgs = new String[] {rowId};
return query(selection, selectionArgs, columns);
}
public Cursor getWordMatches(String query, String[] columns) {
String selection = KEY_WORD + " MATCH ?";
String[] selectionArgs = new String[] {query+"*"};
return query(selection, selectionArgs, columns);
}
private Cursor query(String selection, String[] selectionArgs, String[] columns) {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(FTS_VIRTUAL_TABLE);
builder.setProjectionMap(mColumnMap);
Cursor cursor = builder.query(mDatabaseOpenHelper.getReadableDatabase(),
columns, selection, selectionArgs, null, null, null);
if (cursor == null) {
return null;
} else if (!cursor.moveToFirst()) {
cursor.close();
return null;
}
return cursor;
}
private static class DictionaryOpenHelper extends SQLiteOpenHelper {
private final Context mHelperContext;
private SQLiteDatabase mDatabase;
private static final String FTS_TABLE_CREATE =
"CREATE VIRTUAL TABLE " + FTS_VIRTUAL_TABLE +
" USING fts3 (" +
KEY_WORD + ", " +
KEY_DEFINITION +
KEY_EXAMPLE + ");";
DictionaryOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mHelperContext = context;
}
#Override
public void onCreate(SQLiteDatabase db) {
mDatabase = db;
mDatabase.execSQL(FTS_TABLE_CREATE);
loadDictionary();
}
private void loadDictionary() {
new Thread(new Runnable() {
public void run() {
try {
loadWords();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}).start();
}
private void loadWords() throws IOException {
Log.d(TAG, "Loading words...");
final Resources resources = mHelperContext.getResources();
InputStream inputStream = resources.openRawResource(R.raw.definitions);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
String line;
while ((line = reader.readLine()) != null) {
String[] strings = TextUtils.split(line, "-");
if (strings.length < 2) continue;
long id = addWord(strings[0].trim(), strings[1].trim(), strings[2].trim());
if (id < 0) {
Log.e(TAG, "unable to add word: " + strings[0].trim());
}
}
} finally {
reader.close();
}
Log.d(TAG, "DONE loading words.");
}
public long addWord(String word, String definition, String example) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_WORD, word);
initialValues.put(KEY_DEFINITION, definition);
initialValues.put(KEY_EXAMPLE, example);
return mDatabase.insert(FTS_VIRTUAL_TABLE, null, initialValues);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS " + FTS_VIRTUAL_TABLE);
onCreate(db);
}
}
}
DictionaryProvider.Java
public class DictionaryProvider extends ContentProvider {
String TAG = "DictionaryProvider";
public static String AUTHORITY = "com.pesquisa.dicionario.searchabledict.DictionaryProvider";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/dictionary");
public static final String WORDS_MIME_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE +
"/vnd.pesquisa.dicionario.searchabledict";
public static final String DEFINITION_MIME_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE +
"/vnd.pesquisa.dicionario.searchabledict";
private DictionaryDatabase mDictionary;
private static final int SEARCH_WORDS = 0;
private static final int GET_WORD = 1;
private static final int SEARCH_SUGGEST = 2;
private static final int REFRESH_SHORTCUT = 3;
private static final UriMatcher sURIMatcher = buildUriMatcher();
private static UriMatcher buildUriMatcher() {
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
matcher.addURI(AUTHORITY, "dictionary", SEARCH_WORDS);
matcher.addURI(AUTHORITY, "dictionary/#", GET_WORD);
matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT, REFRESH_SHORTCUT);
matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", REFRESH_SHORTCUT);
return matcher;
}
#Override
public boolean onCreate() {
mDictionary = new DictionaryDatabase(getContext());
return true;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
switch (sURIMatcher.match(uri)) {
case SEARCH_SUGGEST:
if (selectionArgs == null) {
throw new IllegalArgumentException(
"selectionArgs must be provided for the Uri: " + uri);
}
return getSuggestions(selectionArgs[0]);
case SEARCH_WORDS:
if (selectionArgs == null) {
throw new IllegalArgumentException(
"selectionArgs must be provided for the Uri: " + uri);
}
return search(selectionArgs[0]);
case GET_WORD:
return getWord(uri);
case REFRESH_SHORTCUT:
return refreshShortcut(uri);
default:
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
}
private Cursor getSuggestions(String query) {
query = query.toLowerCase();
String[] columns = new String[] {
BaseColumns._ID,
DictionaryDatabase.KEY_WORD,
SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID};
return mDictionary.getWordMatches(query, columns);
}
private Cursor search(String query) {
query = query.toLowerCase();
String[] columns = new String[] {
BaseColumns._ID,
DictionaryDatabase.KEY_WORD,
DictionaryDatabase.KEY_DEFINITION,
DictionaryDatabase.KEY_EXAMPLE};
return mDictionary.getWordMatches(query, columns);
}
private Cursor getWord(Uri uri) {
String rowId = uri.getLastPathSegment();
String[] columns = new String[] {
DictionaryDatabase.KEY_WORD,
DictionaryDatabase.KEY_DEFINITION,
DictionaryDatabase.KEY_EXAMPLE};
return mDictionary.getWord(rowId, columns);
}
private Cursor refreshShortcut(Uri uri) {
String rowId = uri.getLastPathSegment();
String[] columns = new String[] {
BaseColumns._ID,
DictionaryDatabase.KEY_WORD,
DictionaryDatabase.KEY_DEFINITION,
DictionaryDatabase.KEY_EXAMPLE,
SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID};
return mDictionary.getWord(rowId, columns);
}
#Override
public String getType(Uri uri) {
switch (sURIMatcher.match(uri)) {
case SEARCH_WORDS:
return WORDS_MIME_TYPE;
case GET_WORD:
return DEFINITION_MIME_TYPE;
case SEARCH_SUGGEST:
return SearchManager.SUGGEST_MIME_TYPE;
case REFRESH_SHORTCUT:
return SearchManager.SHORTCUT_MIME_TYPE;
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
}
#Override
public Uri insert(Uri uri, ContentValues values) {
throw new UnsupportedOperationException();
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
throw new UnsupportedOperationException();
}
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
throw new UnsupportedOperationException();
}
}
SenseDictionary.Java (the Main Activity)
public class SenseDictionary extends Activity {
private TextView mTextView;
private ListView mListView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
mTextView = (TextView) findViewById(R.id.text);
mListView = (ListView) findViewById(R.id.list);
handleIntent(getIntent());
}
#Override
protected void onNewIntent(Intent intent) {
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Intent wordIntent = new Intent(this, WordActivity.class);
wordIntent.setData(intent.getData());
startActivity(wordIntent);
} else if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
showResults(query);
}
}
private void showResults(String query) {
Cursor cursor = managedQuery(DictionaryProvider.CONTENT_URI, null, null,
new String[] {query}, null);
if (cursor == null) {
mTextView.setText(getString(R.string.no_results, new Object[] {query}));
} else {
int count = cursor.getCount();
String countString = getResources().getQuantityString(R.plurals.search_results,
count, new Object[] {count, query});
mTextView.setText(countString);
String[] from = new String[] { DictionaryDatabase.KEY_WORD,
DictionaryDatabase.KEY_DEFINITION,
DictionaryDatabase.KEY_EXAMPLE};
int[] to = new int[] { R.id.word,
R.id.definition,
R.id.example};
SimpleCursorAdapter words = new SimpleCursorAdapter(this,
R.layout.result, cursor, from, to);
mListView.setAdapter(words);
mListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent wordIntent = new Intent(getApplicationContext(), WordActivity.class);
Uri data = Uri.withAppendedPath(DictionaryProvider.CONTENT_URI,
String.valueOf(id));
wordIntent.setData(data);
startActivity(wordIntent);
}
});
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setIconifiedByDefault(false);
}
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.search:
onSearchRequested();
return true;
default:
return false;
}
}
}
WordActivity
public class WordActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.word);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
}
Uri uri = getIntent().getData();
Cursor cursor = managedQuery(uri, null, null, null, null);
if (cursor == null) {
finish();
} else {
cursor.moveToFirst();
TextView word = (TextView) findViewById(R.id.word);
TextView definition = (TextView) findViewById(R.id.definition);
TextView example = (TextView) findViewById(R.id.example);
int wIndex = cursor.getColumnIndexOrThrow(DictionaryDatabase.KEY_WORD);
int dIndex = cursor.getColumnIndexOrThrow(DictionaryDatabase.KEY_DEFINITION);
int eIndex = cursor.getColumnIndexOrThrow(DictionaryDatabase.KEY_EXAMPLE);
word.setText(cursor.getString(wIndex));
definition.setText(cursor.getString(dIndex));
example.setText(cursor.getString(eIndex));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setIconifiedByDefault(false);
}
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.search:
onSearchRequested();
return true;
case android.R.id.home:
Intent intent = new Intent(this, SenseDictionary.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
default:
return false;
}
}
}
I would like to help you, but there are some issues.
First: You only posted the question an hour ago. In general, the stackoverflow community is not eagerly waiting for the next question to come in. You'll have to be patient.
Second: You've only posted your program. There may be someone out there who's willing to go through it step by step to figure out the problem, and I wish him or her luck, but I'd hesitate to do it. stackoverflow isn't my full-time job, so I can't spend 15-20 minutes just figuring out what (if anything) your program does.
It's not a simple program. You have a database, a content provider, and two activities.
Third: Your program doesn't have a single comment. Makes it even harder to debug.
Fourth: You said "I've tried to create a new table column: KEY_EXAMPLE. But it doesn't work." What happens? Why do you think it's not working? What do you expect it to do?
stackoverflow "works" when you have a specific question or problem that has you stumped. It works the worst when you ask, in essence, "fix my program for me".
Having said all this, I'll venture an off-the-wall guess: Did you run this app before and create a previous version of the database? If so, I don't see any place that you're deleting the previous version. You won't be able to create a new version, including the new column, until you delete the old version. You can do this in Settings > Apps > appname > Clear Data, or you can put it into the program itself.
Good luck!

Categories

Resources