I'm trying to organize favourites in my app. I have a database with three columns:
_id | name | description | star
1 London some desc.
2 Berlin some desc.
3 Paris some desc. yes
I want to display favourites in listview. The refreshCursor() returns list of names with "star" column value "yes":
private static final String COLUMN_STAR = "star";
private void refreshCursor() {
stopManagingCursor(cursor);
Intent intent = getIntent();
String TABLE_NAME = intent.getStringExtra("tableName");
cursor = database.query(TABLE_NAME, null, COLUMN_STAR + " = ?",
new String[] { "yes" }, null, null, null);
startManagingCursor(cursor);
}
It's ok.
Then after I click on Paris I send extra string with clicked position:
lvData.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String entryID = new Integer(position).toString();
Intent intent = new Intent();
intent.setClass(FavouritesActivity.this, ViewFavsActivity.class);
Bundle b = new Bundle();
b.putString("elementId", entryID);
intent.putExtras(b);
startActivity(intent);
}
});
But I get position (of endtryID) 0 and ViewFavsActivity displays decription of London.
How to get actual position of Cursor and send it to ViewFavsActivity?
Help, please.
Part of FavouritesActivity (onCreate): // method refreshCursor is above
refreshCursor();
String[] from = new String[] { COLUMN_NAME };
int[] to = new int[] { R.id.tvText };
scAdapter = new SimpleCursorAdapter(this, R.layout.list_item, cursor,
from, to);
lvData = (ListView) findViewById(R.id.list);
lvData.setAdapter(scAdapter);
lvData.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String entryID = String.valueOf(id);
Intent intent = new Intent();
intent.setClass(FavouritesActivity.this, ViewFavsActivity.class);
Bundle b = new Bundle();
b.putString("elementId", entryID);
intent.putExtras(b);
startActivity(intent);
Part of ViewFavsActivity:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// opening DB
refreshCursor();
bundle = getIntent().getExtras();
TextView titleText = (TextView) findViewById(R.id.titleText);
setTitle = database.query(TABLE_NAME, new String[] { COLUMN_DESC },
null, null, null, null, null);
int entryID = Integer.parseInt(bundle.getString("elementId"));
setTitle.moveToPosition(entryID);
titleText.setText(setTitle.getString(setTitle
.getColumnIndex(COLUMN_DESC)));
}
private void refreshCursor() {
stopManagingCursor(cursor);
Intent intent = getIntent();
cursor = database.query(TABLE_NAME, new String[] { COLUMN_ID, COLUMN_STAR, COLUMN_DESC },
"_id = ? AND star = ?",
new String[] { intent.getStringExtra("elementId"), "yes" },
null, null, null);
}
Added:
FavouritesActivity on pastebin
ViewFavsActivity on pastebin
Project
The real problem is that you are using two different Cursor's. You get position == 0 from:
cursor = database.query(TABLE_NAME, null, COLUMN_STAR + " = ?",
new String[] { "yes" }, null, null, null);
But then ask for position 0 in:
setTitle = database.query(TABLE_NAME, new String[] { COLUMN_DESC },
null, null, null, null, null);
So the odds are good that you will get a different result.
Also Bundle can hold any primitive data type and a few more complex ones. So you don't need to convert a number into a String and then back to its original data type...
A safer approach is to use the row's id, so use this in your OnItemClickListener:
b.putLong("elementId", id);
And in ViewFavsActivity:
long entryID = bundle.getLong("elementId");
setTitle = database.query(TABLE_NAME, new String[] { COLUMN_DESC },
"_id = " + entryID, null, null, null, null);
(Note: when in doubt always use ? and query()'s selectionArgs parameter to prevent SQL injection attacks, but you are working with a long that you retrieved as an index, so you're safe in this context.)
the problem here is that your Cursor only result one object. I belive is londe, is it correct ? If yes. Always the position result in the list view is added a element more one. Ex:
If the list view have only one object:
lvData.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//Here will be showed the 0 position, not 3 like you whant.
String entryID = new Integer(position).toString();
}
});
the solution:
You need to cast a view in the method to your Object placed in the Adapter. Ex:
lvData.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//Here will be showed the 0 position, not 3 like you whant.
MyObject object = (MyObject)view; //This object is placed in the Adapter.
object.getId(); //This method is inserted in my object or you can Override the method toString() to return the id of your query.
//Now you can send your ID to another Activity.
//Put your code here.
}
});
It´s this. I hope that I help you with my solution. Any question please put your question here.
--
thiago L. Silva
Related
I'm trying to create a contact application so far so good,(I'm new to Android Developing) but I struggle with this part of the code where I have an AlertDialog, that I want from the elements that displays (infos of the contact, selected), to take me to my Activity, (ActivitySMS.class to be exact), but although it seems to be fine, running the app, and selecting the number from the AlertDialog that appears, it ends. Log doesn't show something worthy of exploring and understanding where lies the problem.
public class AgendaActivity extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_agenta);
ContentResolver resolver = getContentResolver();
Cursor mCursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
String[] contacts = {
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY,
ContactsContract.Contacts.LOOKUP_KEY,
ContactsContract.Contacts._ID,
};
int[] views = new int[]{
android.R.id.text1
};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_2,
mCursor,
contacts,
views,
0);
// Bind to our new adapter.
setListAdapter(adapter);
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
final Cursor phoneCursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=?",
new String[]{"" + id},
null);
assert phoneCursor != null;
final int nTelephones = phoneCursor.getCount();
final String[] telephones = new String[nTelephones];
int x = 0;
while (phoneCursor.moveToNext()) {
int col = phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
telephones[x++] = phoneCursor.getString(col);
}
//Cursor Close
phoneCursor.close();
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Telephone Selection");
builder.setItems(telephones, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int item) {
String currentNumber = "smsto: " + (telephones[item]);
Intent sentIntent = new Intent(AgendaActivity.this, ActivitySMS.class);
sentIntent.setData(Uri.parse(currentNumber));
startActivity(sentIntent);
}
});
AlertDialog alert = builder.create();
alert.show();
}
Is there a way to overcome this obstacle?
Replace the line sendIntent.setData(Uri.parse(currentNumber)); by
public static final String EXTRA_CURRENT_NUMBER = "EXTRA_CURRENT_NUMBER"; //just a string constant, it can be whatever you want
...
sendIntent.putExtra(EXTRA_CURRENT_NUMBER, currentNumber);
You can read that value later in your activity like this
//ActivitySMS.class
getIntent().getExtras().getString(MyDialogClass.EXTRA_CURRENT_NUMBER, "some default value...");
I want to open new activity which will display instructions from the position id of my listview.
This is my helper
public List<step_con> getSteps(){
List<step_con> steplist = new ArrayList<step_con>();
String query = "SELECT s1,s1_img,s2,s2_img,s3,s3_img,s4,s4_img,s5,s5_img,s6,s6_img, FROM step_software WHERE _id = "+ id;
Cursor cur = database.rawQuery(query, null);
if (cur.moveToFirst()) {
do {
step_con steps = new step_con();
steps.setS(cur.getString(0));
steps.setImage(cur.getBlob(1));
steps.setS2(cur.getString(2));
steps.setImage2(cur.getBlob(3));
steps.setS3(cur.getString(4));
steps.setImage3(cur.getBlob(5));
steps.setS4(cur.getString(6));
steps.setImage4(cur.getBlob(7));
steps.setS5(cur.getString(8));
steps.setImage5(cur.getBlob(9));
steps.setS6(cur.getString(10));
steps.setImage6(cur.getBlob(11));
} while (cur.moveToNext());
}
database.close();
return steplist;
}
The +id is the position of mylistview.
And this is my listitemclick
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent myIntent = new Intent(view.getContext(),DatabaseAccess.class);
int pos = position;
String pos1 = String.valueOf(pos);
}
I'm new to android without attending class, just learning by myself. Please help what should i do or include?
I'm trying get all contacts and select it.
I completed get all contacts in my phone. But when i try to select a few contacts and get their names or numbers, I faced nullpointer error.
public class ContactListFragment extends ListFragment implements LoaderCallbacks<Cursor> {
private CursorAdapter mAdapter;
final HashMap<String,String> hashMap = new HashMap<String,String>();
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
private Uri uriContact;
private String contactID;
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create adapter once
Context context = getActivity();
int layout = android.R.layout.simple_list_item_multiple_choice;
Cursor c = null; // there is no cursor yet
int flags = 0; // no auto-requery! Loader requeries.
mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// each time we are started use our listadapter
setListAdapter(mAdapter);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
// and tell loader manager to start loading
getLoaderManager().initLoader(0, null, this);
***getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor cursorID = getActivity().getContentResolver().query(uriContact,
new String[]{ContactsContract.Contacts._ID},
null, null, null);
contactID = cursorID.getString(cursorID.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
System.out.println(contactID);
}
});
}***
// columns requested from the database
private static final String[] PROJECTION = {
Contacts._ID, // _ID is always required
Contacts.DISPLAY_NAME_PRIMARY // that's what we want to display
};
// and name should be displayed in the text1 textview in item layout
private static final String[] FROM = { Contacts.DISPLAY_NAME_PRIMARY };
private static final int[] TO = { android.R.id.text1 };
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// load from the "Contacts table"
Uri contentUri = Contacts.CONTENT_URI;
// no sub-selection, no sort order, simply every row
// projection says we want just the _id and the name column
return new CursorLoader(getActivity(),
contentUri,
PROJECTION,
null,
null,
null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Once cursor is loaded, give it to adapter
mAdapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
// on reset take any old cursor away
mAdapter.swapCursor(null);
}
I think problem is my onItemClickListener.
How can i fix this?
Thanks from now :)
The main problem is that uriContact is null when you make the query.
The other problem is that you are only using ContactsContract.Contacts._ID as the projection, so the ID is the only thing returned.
I got it working by using null for the projection so that it returns all rows.
I also added functionality to find the currently selected contact, and display a Toast with their phone number.
This is not optimal code, since it just queries all rows and then iterates through them until it finds the currently selected contact, but it works:
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor cur = mAdapter.getCursor();
cur.moveToPosition(position);
String curName = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY));
System.out.println(curName);
uriContact = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
Cursor cursorID = getContentResolver().query(uriContact,
null,
null, null, null);
for (cursorID.moveToFirst(); !cursorID.isAfterLast(); cursorID.moveToNext() ) {
String testName = cursorID.getString(cursorID.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY));
if (testName != null && testName.equals(curName)) {
contactID = cursorID.getString(cursorID.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
}
if (contactID != null) {
System.out.println(contactID);
Toast.makeText(MainActivity.this, "contact Phone: " + contactID, Toast.LENGTH_LONG).show();
}
}
});
Edit: I got a more optimized version working, which uses the selection and selectionArgs in the query to return just the current contact info:
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor cur = mAdapter.getCursor();
cur.moveToPosition(position);
String curName = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY));
System.out.println(curName);
uriContact = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
Cursor cursorID = getContentResolver().query(uriContact,
null,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " = ?", new String[]{curName}, null);
if (cursorID.moveToFirst()) {
contactID = cursorID.getString(cursorID.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
if (contactID != null) {
System.out.println(contactID);
Toast.makeText(MainActivity.this, "contact Phone: " + contactID, Toast.LENGTH_LONG).show();
}
}
});
Right now, my app filters the data in a listview when somethings is entered into the editText, but it can only filter by one thing at a time. I want it to be able to filter by more than value. For example, if someone types in "chicken" it should filter the recipes by the word 'chicken'. But, if someone then types in "dinner", I want it to filter the recipes by both "chicken" and "dinner." Eventually, I want to make it so those values appear as checkboxes above the listview so they can be easily removed.
I can't figure out how to do this. I played around with loops at first but didn't really get anywhere.
public class SearchActivity extends NavDrawerActivity {
private DBHandler dbHelper;
private SimpleCursorAdapter dataAdapter;
ArrayList<String> filters = new ArrayList<String>();
//String[] filters;
FrameLayout frameLayout;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main_activity3);
frameLayout = (FrameLayout) findViewById(R.id.activity_frame);
// inflate the custom activity layout
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View activityView = layoutInflater.inflate(R.layout.activity_main_activity3, null, false);
// add the custom layout of this activity to frame layout.
frameLayout.addView(activityView);
dbHelper = new DBHandler(this, null, null, 1);
//dbHelper.open();
//Clean all data
dbHelper.deleteAllRecipes();
//Add some data
dbHelper.insertSomeRecipes();
//Generate ListView from SQLite Database
displayListView();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
private void displayListView() {
final Cursor cursor = dbHelper.fetchAllRecipes();
// The desired columns to be bound
String[] columns = new String[]{
//DBHandler.COLUMN_CODE,
DBHandler.COLUMN_NAME,
DBHandler.COLUMN_TYPE,
DBHandler.COLUMN_INGRED
};
// the XML defined views which the data will be bound to
int[] to = new int[]{
//R.id.code,
R.id.name,
R.id.type,
R.id.ingredient,
};
// create the adapter using the cursor pointing to the desired data
//as well as the layout information
dataAdapter = new SimpleCursorAdapter(
this, R.layout.recipeinfo,
cursor,
columns,
to,
0);
ListView listView = (ListView) findViewById(R.id.listView1);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
String recipeName = cursor.getString(cursor.getColumnIndexOrThrow("name"));
Intent n = new Intent(getApplicationContext(), RecipeActivity.class);
//n.putExtra("position", position);
n.putExtra("recipeName", recipeName);
startActivity(n);
}
});
//final GridView gridView = (GridView)findViewById(R.id.gridView);
final TextView tv = (TextView)findViewById(R.id.textView14);
final EditText myFilter = (EditText) findViewById(R.id.myFilter);
myFilter.setImeActionLabel("Filter",1);
myFilter.setPrivateImeOptions("actionUnspecified");
myFilter.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
if (id == 1 || id == EditorInfo.IME_NULL) {
String filter = textView.getText().toString();
dataAdapter.getFilter().filter(filter);
filters.add(filter);
tv.append(filter);
myFilter.setText("");
}
return false;
}
});
dataAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return dbHelper.fetchRecipesByName(constraint.toString());
}
});
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Then you start a new Activity via Intent
Intent intent = new Intent();
intent.setClass(this, RecipeActivity.class);
intent.putExtra("position", position);
// Or / And
intent.putExtra("id", id);
startActivity(intent);
}
}
fetchRecipesByName in DBHandler
public Cursor fetchRecipesByName(String inputText) throws SQLException {
SQLiteDatabase mDb = this.getWritableDatabase();
Log.w(TAG, inputText);
Cursor mCursor = null;
if (inputText == null || inputText.length () == 0) {
mCursor = mDb.query(SQLITE_TABLE, new String[] {COLUMN_ROWID,
COLUMN_NAME, COLUMN_TYPE, COLUMN_INGRED, COLUMN_IMGPATH},
null, null, null, null, null);
}
else {
mCursor = mDb.query(true, SQLITE_TABLE, new String[] {COLUMN_ROWID,
COLUMN_NAME, COLUMN_TYPE, COLUMN_INGRED, COLUMN_IMGPATH},
COLUMN_NAME + " like '%" + inputText + "%'" + " or " +
COLUMN_TYPE + " like '%" + inputText + "%'" + " or " +
COLUMN_INGRED + " like '%" + inputText + "%'",
null, null, null, null, null);
}
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
What is the implementation of dbHelper.fetchReccipesByName()? I think, as of now, it queries the table only by one thing. You should change its logic and implement your complex need in this method (obviously, it should be an SQL query execution).
As a best practice, you should call listView.setFilterText() instead of dataAdapter.getFilter().filter(), because this method is supposed to run in secondary thread for the reason that DB queries are time consuming. If you call listView.setFilterText(), the framework will take care of threading and calls filter.filter() in secondary thread.
And finally, since you are searching by more than one keyword, but setFilterText() accepts only one CharSequence param, you should encode somehow many keywords into single String (say comma separated). And while querying you could decode the constraint to get the keywords.
I have ListView which have items from a database.
My adapter is this:
Cursor cur = myDb.getCategories();
// Closing the cursor
// DEPRECATED!!
startManagingCursor(cur);
// Set up mapping from cursor to view fields
String[] fromFieldNames = new String[] { DBAdapter.KEY_ITEM_CAT };
int[] toViewIDs = new int[] { R.id.tvItemCat };
// Create adapter to map columns of DB to elements on UI
myCursorAdapter = new SimpleCursorAdapter(this, // Context
R.layout.category_layout, // Raw layout template
cur, // Cursor (set of DB records)
fromFieldNames, // DB column names
toViewIDs // views ID to putt in list view
);
// Set the adapter for list view
LVCat.setAdapter(myCursorAdapter);
getCategories():
Cursor c = db.rawQuery("SELECT DISTINCT " + KEY_ITEM_CAT + " as " + KEY_ITEM_ID
+ ", " + KEY_ITEM_CAT + " FROM " + ITEMS_TABLE_NAME, null);
if (c != null) {
c.moveToFirst();
}
return c;
I want when i click on some item I should get item name.
I've search and i found this code:
public void onCatClick(){
LVCat.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
// TODO Auto-generated method stub
String category = LVCat.getItemAtPosition(position).toString();
// String category = parent.getItemAtPosition(position).toString(); --> This also I've tried, but the same result
System.out.println("Cat: " + category);
}
});
}
For other people this works. But I don't get the item name i get something like this:
System.out(23858): Cat: android.database.sqlite.SQLiteCursor#4197f3a0
So how can I get the selected item name?
Use parent.getItemAtPosition(position).toString() in your onItemClickListener to get item.
or use it
TextView tv = (TextView) v.findViewById(R.id.tvItemCat);
String value = tv.getText().toString();