I'm trying to add edit function to my database, read and write function working perfectly. First step i want, is to show record clicked from my listview in another layout (the same layout I use for add new record)
in show_activity I've this code
show_activity
///ON CREATE
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
datasource = new DBAdapter(this);
datasource.open();
Cursor cursor = datasource.Query(filter);
String[] columns = new String[] { "swimm_pos", "swimm_date","swimm_lap", "swimm_stroke", "swimm_time", "swimm_media", "swimm_efficiency", "swimm_note" };
int[] to = new int[] { R.id.swimm_pos, R.id.swimm_date, R.id.swimm_lap, R.id.swimm_stroke, R.id.swimm_time, R.id.swimm_medialap, R.id.swimm_efficiency, R.id.swimm_note};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
this,
R.layout.list_layout,
cursor,
columns,
to);
this.setListAdapter(adapter);
datasource.close();
'''''
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent("com.poolper.Edit_Activity");
Cursor cursor = (Cursor) adapter.getItem(position);
intent.putExtra("idContacto",cursor.getInt(cursor.getColumnIndex("_id")));
startActivity(intent);
}
this is extract from my Edit Activity
public class Edit_Activity extends Activity {
int idContacto;
DBAdapter datasource;
GetSet details;
EditText edtSwimm_pos;
.....
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_layout);
edtSwimm_pos = (EditText) findViewById(R.modificacontatto.edswimm_date);
......
LoadDetails();
...
private void LoadDetails(){
idContacto = getIntent().getIntExtra("idContacto", 0);
datasource = new DBAdapter(this);
datasource.open();
details = datasource.getContacto(idContacto);
datasource.close();
edtSwimm_pos.setText(contacto.getswimm_pos());
.....
and from my DBAdapter
public class DBAdapter {
private SQLiteDatabase database;
private DBHelper DBHelper;
private String[] allColumns = {
DBHelper.ID,
DBHelper.SWIMM_POS,
DBHelper.SWIMM_DATE,
DBHelper.SWIMM_LAP,
DBHelper.SWIMM_STROKE,
DBHelper.SWIMM_TIME,
DBHelper.SWIMM_MEDIA,
DBHelper.SWIMM_EFFICIENCY,
DBHelper.SWIMM_NOTE
};
....
private GetSet cursorToContacto(Cursor cursor) {
GetSet contacto = new GetSet(cursor.getLong(0),cursor.getString(1),cursor.getString(2), cursor.getString(3), cursor.getString(4), cursor.getString(5), cursor.getString(6), cursor.getString(7), cursor.getString(8));
return contacto;
}
public GetSet getContacto (int idContacto){
Cursor cursor = database.query(DBHelper.TABLE_NAME, allColumns, DBHelper.ID + " = " + idContacto, null,null, null, null);
cursor.moveToFirst();
return cursorToContacto(cursor);
}
and this GetSet class
public class GetSet {
private long _id;
private String swimm_pos;
private String swimm_media;
private String swimm_note;
private String swimm_date;
private String swimm_lap;
private String swimm_stroke;
private String swimm_time;
private String swimm_efficiency;
public GetSet(long id, String swimm_pos, String swimm_date, String swimm_lap,String swimm_stroke, String swimm_time, String swimm_media, String swimm_efficiency, String swimm_note){
this._id=id;
this.swimm_pos=swimm_pos;
this.swimm_date=swimm_date;
this.swimm_lap=swimm_lap;
this.swimm_stroke=swimm_stroke;
this.swimm_media=swimm_media;
this.swimm_time=swimm_time;
this.swimm_efficiency=swimm_efficiency;
this.swimm_note=swimm_note;
}
public long getId() {
return _id;
}
public void setId(long id) {
this._id = id;
}
public String getswimm_pos() {
return swimm_pos;
}
public void setswimm_pos(String swimm_pos) {
this.swimm_pos = swimm_pos;
}
But when i click on record debug show the NullPointException at this line
Cursor cursor = (Cursor) adapter.getItem(position)
Change your code as:
protected void onListItemClick(ListView l, View v, int position, long id) {
Cursor cursor = ((SimpleCursorAdapter)l.getAdapter()).getCursor();
cursor.moveToPosition(position);
Intent intent = new Intent(Current_Activity.this,Edit_Activity.class);
intent.putExtra("idContacto",cursor.getInt(cursor.getColumnIndex("_id")));
startActivity(intent);
}
Related
So just to describe the app im building, there are 3 buttons on the home screen, "Data Input", "Info Display" and "Exit". When user clicks "Data Input", they get to fill in some EditText boxes with info and also UPLOAD AN IMAGE from gallery. Once they click a "Save" button on the page, all data entered will be sent to a ListView widget in the "Info Display" screen. However my problem now is that I have managed to get the EditText values to the list view throught the use of Sqlite, but i currently have no clue on how to get the image which was uploaded from the gallery to the ListView widget
These are the working codes I have(only missing the image part)
TouristHelper
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class TouristHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "assignment.db";
private static final int SCHEMA_VERSION = 1;
public TouristHelper(Context context){
super(context, DATABASE_NAME, null, SCHEMA_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db){
//will be called once when the database 1s not created
db.execSQL("CREATE TABLE tourist_table ( _id INTEGER PRIMARY KEY AUTOINCREMENT," +
" Vactivity TEXT, Vdate TEXT, Vdescription TEXT);");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
//Will not be called until SCHEMA_VERSION increases
// Here we can upgrade the database e.g. add more tables
}
/*Read all records from restaurants_Table */
public Cursor getAll() {
return (getReadableDatabase().rawQuery(
"SELECT _id, Vactivity, Vdate, Vdescription " +
"FROM tourist_table ORDER BY Vactivity", null));
}
public Cursor getById(String id) {
String[] args = {id};
return (getReadableDatabase().rawQuery(
"SELECT _id, Vactivity, Vdate, Vdescription" +
" FROM tourist_table WHERE _ID = ?", args));
}
public void insert (String Vactivity, String Vdate,
String Vdescription) {
ContentValues cv = new ContentValues();
cv.put("Vactivity", Vactivity);
cv.put("Vdate", Vdate);
cv.put("Vdescription", Vdescription);
getWritableDatabase().insert("tourist_table", "Vactivity", cv);
}
public void update(String id, String Vactivity, String Vdate,
String Vdescription) {
ContentValues cv = new ContentValues();
String[] args = {id};
cv.put("Vactivity", Vactivity);
cv.put("Vdate", Vdate);
cv.put("Vdescription", Vdescription);
getWritableDatabase().update("tourist_table", cv, "_ID = ?", args);
}
public String getID(Cursor c) { return (c.getString(0)); }
public String getActivity(Cursor c){
return (c.getString(1));
}
public String getDate(Cursor c){
return (c.getString(2));
}
public String getDescription(Cursor c){
return (c.getString(3));
}
}
InfoDisplay
public class InfoDisplay extends AppCompatActivity {
private Cursor model = null;
private VietnamAdapter adapter = null;
private ListView list;
private TouristHelper helper = null;
private TextView empty = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.info_display);
empty = findViewById(R.id.empty);
helper = new TouristHelper(this);
list = findViewById(R.id.listview);
model = helper.getAll();
adapter = new VietnamAdapter(this, model, 0);
list.setOnItemClickListener(onListClick);
list.setAdapter(adapter);
}
#Override
protected void onResume() {
super.onResume();
if (model != null) {
model.close();
}
model = helper.getAll();
if (model.getCount() > 0) {
empty.setVisibility(View.INVISIBLE);
}
adapter.swapCursor(model);
}
#Override
protected void onDestroy() {
helper.close();
super.onDestroy();
}
private AdapterView.OnItemClickListener onListClick = new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
model.moveToPosition(position);
String recordID = helper.getID(model);
Intent intent;
intent = new Intent(InfoDisplay.this, DataIn.class);
intent.putExtra("ID", recordID);
startActivity(intent);
}
};
static class DataHolder {
private TextView VietACTI = null;
private TextView VietDATE = null;
private TextView VietDES = null;
DataHolder(View row) {
VietACTI = row.findViewById(R.id.VAct);
VietDATE = row.findViewById(R.id.VDate);
VietDES = row.findViewById(R.id.VDes);
}
void populateFrom(Cursor c, TouristHelper helper) {
VietACTI.setText(helper.getActivity(c));
VietDATE.setText(helper.getDate(c));
VietDES.setText(helper.getDescription(c));
}
}
class VietnamAdapter extends CursorAdapter {
VietnamAdapter(Context context, Cursor cursor, int flags) {
super(context, cursor, flags);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
DataHolder holder = (DataHolder) view.getTag();
holder.populateFrom(cursor, helper);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.row, parent, false);
DataHolder holder = new DataHolder(row);
row.setTag(holder);
return (row);
}
}
}
DataIn
public class DataIn extends AppCompatActivity {
private EditText Vactivity;
private EditText Vdate;
private EditText Vdescription;
private Button buttonSave;
private Button buttonImg;
ImageView imageView;
private Bitmap imageToStore;
private static int RESULT_LOAD_IMAGE = 1;
private TouristHelper helper = null;
private String touristID = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_data_input);
Vactivity = findViewById(R.id.activity);
Vdate = findViewById(R.id.date);
Vdescription = findViewById(R.id.description);
buttonSave = findViewById(R.id.button_save);
buttonSave.setOnClickListener(onSave);
buttonImg = findViewById(R.id.imginput);
buttonImg.setOnClickListener(onImg);
imageView = findViewById(R.id.imgView);
helper = new TouristHelper(this);
touristID = getIntent().getStringExtra("ID");
if (touristID != null) {
load();
}
/*list = findViewById(R.id.Data);
adapter = new DataAdapter();
list.setAdapter(adapter);*/
}
#Override
protected void onDestroy() {
super.onDestroy();
helper.close();
}
private void load() {
Cursor c = helper.getById(touristID);
c.moveToFirst();
Vactivity.setText(helper.getActivity(c));
Vdate.setText(helper.getDate(c));
Vdescription.setText(helper.getDescription(c));
}
View.OnClickListener onImg = new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(
/*Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, RESULT_LOAD_IMAGE*/);
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "pick an image"), RESULT_LOAD_IMAGE);
}
};
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && data != null) {
Uri selectedImage = data.getData();
/*String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();*/
// String picturePath contains the path of selected Image
imageView.setImageURI(selectedImage);
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
}
}
private View.OnClickListener onSave = new View.OnClickListener(){
#Override
public void onClick(View v){
//read data from restaurantName EditText
String nameStr = Vactivity.getText().toString();
String dateStr = Vdate.getText().toString();
String desStr = Vdescription.getText().toString();
if (touristID == null) {
helper.insert(nameStr, dateStr, desStr);
}
else {
helper.update(touristID, nameStr, dateStr, desStr);
}
// To clase current Activity class and exit
finish();
}
};
}
At this point you have two options:
Save the image in the private storage of your app and save on the DB the URI to this image so you can load it later.
Having the Bitmap with the image get the ByteArray of the image and save it directly to the DB.
I prefer the first option, but the second one could do the job too, hope it helps you.
Can anybody please have a look at my code and tell me where I am wrong? I don't get errors, unfortunately the row that is long pressed and new value is provided is not being updated unless I specify exact row number. I need to be able to update the row that is clicked. I tried everything and up to today I didn't manage to get any help. I am beginner in Android development.
Here is the code of MyDB:
public class MyDB {
private static final String TABLE_NAME = null;
private static final String KEY_ID = null;
private SQLiteDatabase db;
private final Context context;
private final MyDBhelper dbhelper;
// Initializes MyDBHelper instance
public MyDB(Context c){
context = c;
dbhelper = new MyDBhelper(context, Constants.DATABASE_NAME, null,
Constants.DATABASE_VERSION);
}
// Closes the database connection
public void close()
{
db.close();
}
// Initializes a SQLiteDatabase instance using MyDBhelper
public void open() throws SQLiteException
{
try {
db = dbhelper.getWritableDatabase();
} catch(SQLiteException ex) {
Log.v("Open database exception caught", ex.getMessage());
db = dbhelper.getReadableDatabase();
}
}
// updates a diary entry (existing row)
public boolean updateDiaryEntry(String title, long rowId)
{
ContentValues newValue = new ContentValues();
newValue.put(Constants.TITLE_NAME, title);
db.beginTransaction();
db.setTransactionSuccessful();
db.endTransaction();
return db.update(Constants.TABLE_NAME , newValue , Constants.KEY_ID + "= ?" ,
new String[]{ Double.valueOf(rowId).toString() })>0;
}
// Reads the diary entries from database, saves them in a Cursor class and returns it from the method
public Cursor getdiaries()
{
Cursor c = db.query(Constants.TABLE_NAME, null, null,
null, null, null, null);
return c;
}
}
Here is the code with the dialog, where I should update the row:
class EditListItemDialog extends Dialog implements View.OnClickListener {
MyDB dba;
private View editText;
private DiaryAdapter adapter;
private SQLiteDatabase db;
public EditListItemDialog(Context context) {
super(context);
dba = new MyDB(context);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_text_dialog);//here is your xml with EditText and 'Ok' and 'Cancel' buttons
View btnOk = findViewById(R.id.button_ok);
editText = findViewById(R.id.edit_text);
btnOk.setOnClickListener(this);
dba.open();
}
private List<String> fragment_monday;
private long rowId;
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Position is the number of the item clicked
//You can use your adapter to modify the item
long rowId = adapter.getItemId(position); //Will return the clicked item
saveItToDB(rowId);
}
public EditListItemDialog(Context context, DiaryAdapter adapter, int position) {
super(context);
this.fragment_monday = new ArrayList<String>();
this.adapter = adapter;
dba = new MyDB(context);
}
#Override
public void onClick(View v) {
fragment_monday.add(((TextView) v).getText().toString());//here is your updated(or not updated) text
// public void notifyDataSetChanged();
dismiss();
try {
saveItToDB(rowId);
} catch (Exception e) {
e.printStackTrace();
}
}
private void saveItToDB(long rowId) {
dba.open();
dba.updateDiaryEntry(((TextView) editText).getText().toString(), rowId);
dba.close();
((TextView) editText).setText("");
}
}
And here is the Diary Adapter:
public class DiaryAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ArrayList<MyDiary> fragment_monday;
public DiaryAdapter(Context context) {
mInflater = LayoutInflater.from(context);
fragment_monday = new ArrayList<MyDiary>();
getdata();
ListView list = getListView();
list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
new EditListItemDialog(Monday.this, null, position).show();
return true;
}
});
}
public void getdata(){
Cursor c = dba.getdiaries();
startManagingCursor(c);
if(c.moveToFirst()){
do{
String title =
c.getString(c.getColumnIndex(Constants.TITLE_NAME));
String content =
c.getString(c.getColumnIndex(Constants.CONTENT_NAME));
MyDiary temp = new MyDiary(title,content);
fragment_monday.add(temp);
} while(c.moveToNext());
}
}
#Override
public int getCount() {return fragment_monday.size();}
public MyDiary getItem(int i) {return fragment_monday.get(i);}
public long getItemId(int i) {return i;}
public View getView(int arg0, View arg1, ViewGroup arg2) {
final ViewHolder holder;
View v = arg1;
if ((v == null) || (v.getTag() == null)) {
v = mInflater.inflate(R.layout.diaryrow, null);
holder = new ViewHolder();
holder.mTitle = (TextView)v.findViewById(R.id.name);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.mdiary = getItem(arg0);
holder.mTitle.setText(holder.mdiary.title);
v.setTag(holder);
return v;
}
public class ViewHolder {
MyDiary mdiary;
TextView mTitle;
}
}
i found first problem at your DB class
update this method
public Cursor getdiaries()
{
Cursor c = db.query(Constants.TABLE_NAME, null, null,
null, null, null, null);
return c;
}
To
public Cursor getdiaries()
{
Cursor c = db.query(Constants.TABLE_NAME, new String[]{Constants.TITLE_NAME ,Constants.CONTENT_NAME}, null,
null, null, null, null);
return c;
}
After a long time I figured out that changing argument from 0 to different number allows me to update row with corresponding id to this number:
private void saveItToDB() {
dba.open();
dba.updateDiaryEntry(((TextView) editText).getText().toString(), 2);
dba.close();
((TextView) editText).setText("");
}
In above code I changed 0 to 2 and I was able to update content of row no 2. Here is full class code:
class EditListItemDialog extends Dialog implements View.OnClickListener {
MyDB dba;
private View editText;
private DiaryAdapter adapter;
private SQLiteDatabase db;
public EditListItemDialog(Context context) {
super(context);
dba = new MyDB(context);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_text_dialog);//here is your xml with EditText and 'Ok' and 'Cancel' buttons
View btnOk = findViewById(R.id.button_ok);
editText = findViewById(R.id.edit_text);
btnOk.setOnClickListener(this);
dba.open();
}
private List<String> fragment_monday;
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Position is the number of the item clicked
//You can use your adapter to modify the item
adapter.getItem(position); //Will return the clicked item
}
public EditListItemDialog(Context context, DiaryAdapter adapter, int position) {
super(context);
this.fragment_monday = new ArrayList<String>();
this.adapter = adapter;
dba = new MyDB(context);
}
#Override
public void onClick(View v) {
fragment_monday.add(((TextView) v).getText().toString());//here is your updated(or not updated) text
dismiss();
try {
saveItToDB();
} catch (Exception e) {
e.printStackTrace();
}
}
private void saveItToDB() {
dba.open();
dba.updateDiaryEntry(((TextView) editText).getText().toString(), 2);
dba.close();
((TextView) editText).setText("");
}
}
Now, what do I need to do in order to tell it that I want to update row that is clicked, not row number 2? Any help would be appreciated.
Here is MyDB code:
public class MyDB {
private static final String TABLE_NAME = null;
private static final String KEY_ID = null;
private SQLiteDatabase db;
private final Context context;
private final MyDBhelper dbhelper;
// Initializes MyDBHelper instance
public MyDB(Context c){
context = c;
dbhelper = new MyDBhelper(context, Constants.DATABASE_NAME, null,
Constants.DATABASE_VERSION);
}
// Closes the database connection
public void close()
{
db.close();
}
// Initializes a SQLiteDatabase instance using MyDBhelper
public void open() throws SQLiteException
{
try {
db = dbhelper.getWritableDatabase();
} catch(SQLiteException ex) {
Log.v("Open database exception caught", ex.getMessage());
db = dbhelper.getReadableDatabase();
}
}
// updates a diary entry (existing row)
public boolean updateDiaryEntry(String title, long rowId)
{
ContentValues newValue = new ContentValues();
newValue.put(Constants.TITLE_NAME, title);
return db.update(Constants.TABLE_NAME, newValue, Constants.KEY_ID + "=" + rowId, null)>0;
}
// Reads the diary entries from database, saves them in a Cursor class and returns it from the method
public Cursor getdiaries()
{
Cursor c = db.query(Constants.TABLE_NAME, null, null,
null, null, null, null);
return c;
}
}
Here is the Adapter:
public class Monday extends ListActivity {
private SQLiteDatabase db;
private static final int MyMenu = 0;
MyDB dba;
DiaryAdapter myAdapter;
private class MyDiary{
public MyDiary(String t, String c){
title=t;
content=c;
}
public String title;
public String content;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
dba = new MyDB(this);
dba.open();
setContentView(R.layout.fragment_monday);
super.onCreate(savedInstanceState);
myAdapter = new DiaryAdapter(this);
this.setListAdapter(myAdapter);
}
public class DiaryAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ArrayList<MyDiary> fragment_monday;
public DiaryAdapter(Context context) {
mInflater = LayoutInflater.from(context);
fragment_monday = new ArrayList<MyDiary>();
getdata();
ListView list = getListView();
list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
new EditListItemDialog(Monday.this, null, position).show();
return true;
}
});
}
public void getdata(){
Cursor c = dba.getdiaries();
startManagingCursor(c);
if(c.moveToFirst()){
do{
String title =
c.getString(c.getColumnIndex(Constants.TITLE_NAME));
String content =
c.getString(c.getColumnIndex(Constants.CONTENT_NAME));
MyDiary temp = new MyDiary(title,content);
fragment_monday.add(temp);
} while(c.moveToNext());
}
}
#Override
public int getCount() {return fragment_monday.size();}
public MyDiary getItem(int i) {return fragment_monday.get(i);}
public long getItemId(int i) {return i;}
public View getView(int arg0, View arg1, ViewGroup arg2) {
final ViewHolder holder;
View v = arg1;
if ((v == null) || (v.getTag() == null)) {
v = mInflater.inflate(R.layout.diaryrow, null);
holder = new ViewHolder();
holder.mTitle = (TextView)v.findViewById(R.id.name);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.mdiary = getItem(arg0);
holder.mTitle.setText(holder.mdiary.title);
v.setTag(holder);
return v;
}
public class ViewHolder {
MyDiary mdiary;
TextView mTitle;
}
}
/** Called when the user clicks the Edit button */
public void visitDiary(View view) {
Intent intent = new Intent(this, Diary.class);
startActivity(intent);
}
/** Called when the user clicks the back button */
public void visitSchedule(View view) {
Intent intent = new Intent(this, DisplayScheduleScreen.class);
startActivity(intent);
}
}
Implement getItemId(int position) in your adapter. In your onListItemClick method, call this method with the given position.
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
long itemId = adapter.getItemId(position);
saveItToDB(itemId);
}
private void saveItToDB(long itemId) {
String text = editText.getText().toString();
editText.setText("");
dba.open();
dba.updateDiaryEntry(text, itemId);
dba.close();
}
I am trying to get a list of names with total amounts from a sqlite db.
It is working in a way that shows a list of all the transactions with the
correct combined total. I also have a table in the same db that has usernames
& phone numbers, but I don't think that would be too useful for this activity.
Also, how do I use the onListItemClick to send the next activity something
that I can use to pull only names from the User the person selected? The ID
is being sent, but I don't know how to use it.
ie:
trans table:
Justin 25
Justin 25
Justin 25
Sophia 80
Hoped results:
Justin 75
Sophia 80
Actual results:
Justin 75
Justin 75
Justin 75
Sophia 80
ListActivity that populates the list (with cursor and TextView link)
public class Totals extends ListActivity {
PaymentHelper helper;
Cursor model = null;
PaymentAdapter adapter = null;
UserHelper uhelp;
Cursor umodel = null;
public final static String ID_EXTRA = "com.curtis.bookkeeping._ID";
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_person);
helper = new PaymentHelper(this);
model = helper.getAll();
startManagingCursor(model);
adapter = new PaymentAdapter(model);
setListAdapter(adapter);
}
public void onDestroy() {
super.onDestroy();
helper.close();
}
#Override
public void onListItemClick(ListView list, View view, int position, long id) {
Intent i = new Intent(Totals.this, Detail.class);
i.putExtra(ID_EXTRA, String.valueOf(id));
startActivity(i);
}
public class PaymentAdapter extends CursorAdapter {
PaymentAdapter(Cursor c) {
super(Totals.this, c, FLAG_REGISTER_CONTENT_OBSERVER);
}
#Override
public void bindView(View row, Context context, Cursor c) {
PaymentHolder holder = (PaymentHolder)row.getTag();
holder.populateFrom(c, helper);
}
#Override
public View newView(Context context, Cursor c, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.person_row, parent, false);
PaymentHolder holder = new PaymentHolder(row);
row.setTag(holder);
return row;
}
}
static class PaymentHolder {
private TextView name_line = null;
private TextView amount_line = null;
PaymentHolder(View row) {
name_line = (TextView)row.findViewById(R.id.name_row);
amount_line = (TextView)row.findViewById(R.id.amount_row);
}
void populateFrom(Cursor c, PaymentHelper helper) {
name_line.setText(helper.getName(c));
amount_line.setText(Integer.toString(helper.sumPerson(c, helper.getName(c))));
}
}
}
SQLiteOpenHelper code to retrieve info
public class PaymentHelper extends SQLiteOpenHelper{
private static final String DATABASE_NAME = "bookkeeping.db";
private static final int SCHEMA_VERSION = 1;
SQLiteDatabase db;
public PaymentHelper(Context context) {
super(context, DATABASE_NAME, null, SCHEMA_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db1) {
db = db1;
String sql = "CREATE TABLE IF NOT EXISTS trans (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, date TEXT, amount INT, note TEXT)";
//execute the sql statement
db.execSQL(sql);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public void insert(String name, String date, int amount, String note){
Log.e(name, date + " " + amount);
db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("name", name);
cv.put("date", date);
cv.put("amount", amount);
cv.put("note", note);
Log.e("Almost", "there");
db.insert("trans", "abc", cv);
Log.e("successfully", "inserted");
}
public Cursor getAll(){
String sql = "SELECT * FROM trans ORDER BY name";
Cursor cursor = getReadableDatabase().rawQuery(sql, null);
return cursor;
}
public Cursor getAllNames(){
String sql = "SELECT * FROM users";
Cursor cursor = getReadableDatabase().rawQuery(sql, null);
return cursor;
}
public String getName(Cursor c){
return c.getString(c.getColumnIndex("name"));
}
public String getDate(Cursor c){
return c.getString(c.getColumnIndex("date"));
}
public int getAmount(Cursor c){
return c.getInt(c.getColumnIndex("amount"));
}
public String getNote(Cursor c){
return c.getString(c.getColumnIndex("note"));
}
public void delete(String id){
String[] args = {id};
getWritableDatabase().delete("trans", "_id=?", args);
}
public Cursor getById(String id){
String[] args = {id};
String sql = "SELECT * FROM trans WHERE _id=?";
Cursor cursor = getReadableDatabase().rawQuery(sql, args);
return cursor;
}
public void update(String id, String name, String date, int amount, String note){
String[] args = {id};
ContentValues cv = new ContentValues();
cv.put("name", name);
cv.put("date", date);
cv.put("amount", amount);
cv.put("note", note);
getWritableDatabase().update("trans", cv, "_ID=?", args);
}
public int sumPerson(Cursor c, String name){
int total = 0;
// add up totals
String sql = "SELECT amount FROM trans WHERE name=?";
String[] aname = new String[]{name};
getReadableDatabase().rawQuery(sql,aname);
for(c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){
if(name.equals(getName(c))){
total += c.getInt(c.getColumnIndex("amount"));
}
}
return total;
}
}
This is the activity that is receiving the ID from Totals:
I would like it to show only one user (which they selected
from the totals page) with all of their transactions.
public class Detail extends ListActivity {
PaymentHelper helper;
Cursor model = null;
PaymentAdapter adapter = null;
public final static String ID_EXTRA = "com.curtis.bookkeeping._ID";
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view);
helper = new PaymentHelper(this);
model = helper.getAll();
startManagingCursor(model);
adapter = new PaymentAdapter(model);
setListAdapter(adapter);
}
public void onDestroy() {
super.onDestroy();
helper.close();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.details_menu, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.totals:
startActivity(new Intent(this, Totals.class));
break;
case R.id.users:
startActivity(new Intent(this, Users.class));
break;
case R.id.home:
startActivity(new Intent(this, MainMenu.class));
break;
}
return true;
}
#Override
public void onListItemClick(ListView list, View view, int position, long id) {
Intent i = new Intent(Detail.this, DeletePayment.class);
i.putExtra(ID_EXTRA, String.valueOf(id));
startActivity(i);
}
public class PaymentAdapter extends CursorAdapter {
PaymentAdapter(Cursor c) {
super(Detail.this, c, FLAG_REGISTER_CONTENT_OBSERVER);
}
#Override
public void bindView(View row, Context context, Cursor c) {
PaymentHolder holder = (PaymentHolder)row.getTag();
holder.populateFrom(c, helper);
}
#Override
public View newView(Context context, Cursor c, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.row, parent, false);
PaymentHolder holder = new PaymentHolder(row);
row.setTag(holder);
return row;
}
}
static class PaymentHolder {
private TextView name_line = null;
private TextView date_line = null;
private TextView amount_line = null;
private TextView note_line = null;
PaymentHolder(View row) {
name_line = (TextView)row.findViewById(R.id.name_line);
amount_line = (TextView)row.findViewById(R.id.amount_line);
date_line = (TextView)row.findViewById(R.id.date_line);
note_line = (TextView)row.findViewById(R.id.note_line);
}
void populateFrom(Cursor c, PaymentHelper helper) {
Log.e(helper.getName(c), Integer.toString(helper.getAmount(c)));
name_line.setText(helper.getName(c));
date_line.setText(helper.getDate(c));
amount_line.setText(Integer.toString(helper.getAmount(c)));
note_line.setText(helper.getNote(c));
}
}
}
I know this is long...but help would be awesome!
I feel like the "PaymentAdapter" needs to be modified to only
read two names if there is only two names. Should I be utilizing
the "UserHelper" db helper to populate this? but when I do, it only
runs one cursor through, and gets a nullpointerexception error because
it is not moving one of the cursors. Should I be making a PaymentAdapter
within PaymentAdapter to generate use of another cursor?
The following SQL query will give you the desired result:
SELECT name, SUM(amount)
FROM trans
GROUP BY name
Good day all, please been having this trouble and i can't seem to see why. Basically what am trying to do is pick a contact via the contact api, save in database, and then display in a listview. but for some reason, after i get the contacts details, my custom adapter is not called anymore, its only called on when the activity is first created, and hence empty. Please what could i have missed. Thank you.
heres my code:
public class GroupDetails extends FragmentActivity implements OnClickListener, LoaderCallbacks<Cursor> {
//variable for debugging the application
public static final String TAG = "MyApp.Debug";
//request code for using with action pick intent
static final int PICK_CONTACT = 1;
//initial variables
Button add_button;
TextView label;
ListView list;
ResponderDB dbadapter;
DueCustomCursorAdapter cursoradapter;
//DueCustomCursorLoader loader;
//cursor to retrieve contact details
private Cursor contactsCursor;
String groupname;
long rowId;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.group_detail_list);
//only intialize here. database will be open in custom cursor loader
dbadapter = new ResponderDB(this);
getSupportLoaderManager().initLoader(0, null, this);
/*Read intent and the extras passed*/
Bundle extra = getIntent().getExtras();
if(!extra.isEmpty() || extra.equals(null)){
groupname = extra.getString("group_name");
rowId = extra.getLong("rowId");
}
list = (ListView)findViewById(android.R.id.list);
add_button = (Button)findViewById(R.id.add_button_id);
label = (TextView)findViewById(R.id.group_label_id);
Log.d(TAG, "calling custom adapter here now");
cursoradapter = new DueCustomCursorAdapter(GroupDetails.this, null, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER );
list.setAdapter(cursoradapter);
add_button.setOnClickListener(this);
}
#Override
public void onClick(View view) {
int selection = view.getId();
if(selection == R.id.add_button_id){
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT);
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == PICK_CONTACT){
getContactInfo(data);
}
}
private void getContactInfo(Intent intent) {
String number = null;
String name = null;
String[] projection = {ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
CursorLoader loader = new CursorLoader(this,intent.getData(),
null,null,null,null);
contactsCursor = loader.loadInBackground();
if(contactsCursor.moveToFirst()){
String id = contactsCursor.getString(contactsCursor.getColumnIndex(ContactsContract.Contacts._ID));
name = contactsCursor.getString(contactsCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
//get the Phone Number
Cursor numberCursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI
, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] {id}, null);
while(numberCursor.moveToNext()){
number = numberCursor.getString(numberCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
}
Log.d(TAG, "Successfully added contacts for group");
//dbadapter.updateGroup(rowId, values);
dbadapter.saveContacts(name, number, String.valueOf(rowId));
cursoradapter.notifyDataSetChanged();
getSupportLoaderManager().getLoader(0).onContentChanged();
}
public static final class DueCustomCursorLoader extends SimpleCursorLoader {
public static final String TAG = "MyApp.Debug";
public static int RETRIEVE_CODE = 1;
ResponderDB dbadapter1;
int retrieveCode;
public DueCustomCursorLoader(Context context, ResponderDB dbadapter) {
super(context);
this.dbadapter1= dbadapter;
}
public DueCustomCursorLoader(Context context, ResponderDB dbadapter, int retrieveCode){
super(context);
this.dbadapter1 = dbadapter;
this.retrieveCode = retrieveCode;
}
#Override
public Cursor loadInBackground() {
Cursor cursor = null;
dbadapter1.open();
cursor = dbadapter1.readContact(retrieveCode);
return cursor;
}
}
public class DueCustomCursorAdapter extends CursorAdapter {
public static final String TAG = "SmsResponder.Debug";
private Context myContext;
public DueCustomCursorAdapter(Context context,Cursor c, int flags) {
super(context, c, flags);
myContext = context;
}
//never seem to get here
#Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder)view.getTag();
String contactName = cursor.getString(cursor.getColumnIndexOrThrow(ResponderDB.NAME));
String contactNumber = cursor.getString(cursor.getColumnIndex(ResponderDB.NUMBER));
Log.d(TAG, "contact name is " + contactName);
Log.d(TAG, "contact number is " + contactNumber);
holder.contact_name.setText(contactName);
holder.contact_number.setText(contactNumber);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
ViewHolder holder = new ViewHolder();
View view = LayoutInflater.from(myContext).inflate(R.layout.group_detail_item, parent,false);
holder.contact_name = (TextView)view.findViewById(R.id.group_item_id);
holder.contact_number = (TextView)view.findViewById(R.id.group_subitem_id);
view.setTag(holder);
return view;
}
}
static class ViewHolder {
TextView text;
TextView contact_name;
TextView contact_number;
CheckBox checkbox;
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle arg1) {
return new DueCustomCursorLoader(GroupDetails.this, dbadapter, (int)rowId);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
cursoradapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> arg0) {
cursoradapter.swapCursor(null);
}
}
Am not getting any issue from the database, so code not added here.
After saving contact to the database You need to restartLoader() to get yours database requery and let onLoadFinished to be called again to allow adapter work with new data.
I would try reversing these two lines (it looks to me like your telling the list to update itself before you update the cursor):
cursoradapter.notifyDataSetChanged();
getSupportLoaderManager().getLoader(0).onContentChanged();
To this:
getSupportLoaderManager().getLoader(0).onContentChanged();
cursoradapter.notifyDataSetChanged();