Database does not display data correctly - java

I have a problem, namely, I have an application that displays in the RecyclerView 2 types of salads and after pressing, one of them should show a view showing their exact details with the option of whether or not we like it. These data are obviously retrieved from the database. And everything works until we just go to a detailed view - when we click on the picture of Greek salad we get a blank view, but what is interesting when we click on the chicken salad we get just a view of Greek salad? So where does the view of the chicken salad? And why the views turned into places. I attach the code at the bottom with the pictures so that you can understand exactly what the problem is.
DatabaseHelper
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "app";
private static final int DB_VERSION = 1;
public MiodzioDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE SALAD (_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "NAME TEXT, "
+ "IMAGE_RESOURCE_ID INTEGER, "
+ "FAVORITE INTEGER);");
insertSalatki(db, "Greek salad", R.drawable.salad_greek, 0);
insertSalatki(db, "Chicken salad", R.drawable.salad_chicken, 0);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
private static void insertSalatki(SQLiteDatabase db, String name, int resourceId, int favorite){
ContentValues saladValues = new ContentValues();
salatkiValues.put("NAME", name);
salatkiValues.put("IMAGE_RESOURCE_ID", resourceId);
salatkiValues.put("Favorite", favorite);
db.insert("SALAD", null, salatkiValues);
}
}
Salad
public class Salad {
private String name;
private int imageResourceId;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getImageResourceId() {
return imageResourceId;
}
public void setImageResourceId(int imageResourceId) {
this.imageResourceId = imageResourceId;
}
}
SaladDetailActivity
public class SaladDetailActivity extends AppCompatActivity {
public static final String EXTRA_SALAD = "salad";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_salatki_detail);
int salads = (Integer) getIntent().getExtras().get(EXTRA_SALAD);
try {
SQLiteOpenHelper miodzioDatabaseHelper = new MiodzioDatabaseHelper(this);
SQLiteDatabase db = miodzioDatabaseHelper.getWritableDatabase();
Cursor cursor = db.query("SALATKI",
new String[]{"NAME", "IMAGE_RESOURCE_ID", "FAVORITE"},
"_id = ?",
new String[]{Integer.toString(salads)},
null, null, null);
if(cursor != null) {
if (cursor.moveToFirst()) {
do {
String nameText = cursor.getString(0);
int photoId = cursor.getInt(1);
boolean isFavorite = (cursor.getInt(2) == 1);
TextView name = (TextView) findViewById(R.id.salad_text);
name.setText(nameText);
ImageView photo = (ImageView) findViewById(R.id.salad_image);
photo.setImageResource(photoId);
photo.setContentDescription(nameText);
CheckBox favorite = (CheckBox) findViewById(R.id.favorite);
favorite.setChecked(isFavorite);
}while (cursor.moveToNext());
}
}
cursor.close();
db.close();
}catch (SQLiteException e){
Toast.makeText(this, "Database does not work!", Toast.LENGTH_SHORT).show();
}
Toolbar myChildToolbar = (Toolbar) findViewById(R.id.my_child_toolbar_salad_detail);
setSupportActionBar(myChildToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_create_order:
Intent intent = new Intent(this, AddActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void onFavoriteClicked(View view) {
int salads = (Integer) getIntent().getExtras().get(EXTRA_SALAD);
CheckBox favorite = (CheckBox) findViewById(R.id.favorite);
ContentValues saladValues = new ContentValues();
saladValues.put("FAVORITE", favorite.isChecked());
SQLiteOpenHelper databaseHelper = new DatabaseHelper(this);
SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.update("SALAD", saladValues,
"_id = ?", new String[]{Integer.toString(salads)});
db.close();
}
}
SaladMaterialFragment
public class SaladMaterialFragment extends Fragment {
private DatabaseHelper dataBaseHelper;
private Cursor cursor;
private ArrayList<Salad> arrayList = new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
RecyclerView saladRecyler = (RecyclerView) inflater.inflate(R.layout.fragment_salad_material, container, false);
try{
SQLiteOpenHelper databaseHelper = new databaseHelper(inflater.getContext());
SQLiteDatabase db = databaseHelper.getReadableDatabase();
cursor = db.query("SALAD",
new String[] {"NAME", "IMAGE_RESOURCE_ID"},
null, null, null, null, null);
if(cursor != null){
if(cursor.moveToFirst()){
do{
Salad salads = new Salad();
salad.setName(cursor.getString(0));
salad.setImageResourceId(cursor.getInt(1));
arrayList.add(salad);
}while (cursor.moveToNext());
}
}
}catch (SQLiteException e){
Toast.makeText(inflater.getContext(), "Database does not work!", Toast.LENGTH_SHORT).show();
}
CaptionedImagesAdapter adapter = new CaptionedImagesAdapter(getActivity(), arrayList);
saladRecyler.setAdapter(adapter);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 2);
saladRecyler.setLayoutManager(gridLayoutManager);
adapter.setListener(new CaptionedImagesAdapter.Listener() {
#Override
public void onClick(int position) {
Intent intent = new Intent(getActivity(), SaladDetailActivity.class);
intent.putExtra(SaladDetailActivity.EXTRA_SALAD, position);
getActivity().startActivity(intent);
}
});
return salatkaRecyler;
}
}
SaladDetailLayout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.hfad.SaladDetailActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/my_child_toolbar_salad_detail"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="#android:color/holo_green_light"
android:elevation="4dp"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
/>
<TextView
android:id="#+id/salatki_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<ImageView
android:id="#+id/salad_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"/>
<CheckBox
android:id="#+id/favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/favorite"
android:onClick="onFavoriteClicked"/>
So when I click on Salad greek, I get an empty view only with the option of whether it is a favorite. And when I hit the chicken salad I get a view of the Greek Salad. I have no idea what's going on?

Problem is in the onClick method in SaladMaterialFragment class.
You are passing the position of the item, and in ArrayList indexing is starting with 0.
But in Database insertion, _id INTEGER PRIMARY KEY AUTOINCREMENT, Database indexing will start with 1.
So you need to change onClick method with below.
adapter.setListener(new CaptionedImagesAdapter.Listener() {
#Override
public void onClick(int position) {
Intent intent = new Intent(getActivity(), SaladDetailActivity.class);
intent.putExtra(SaladDetailActivity.EXTRA_SALAD, position+1);
getActivity().startActivity(intent);
}
});
Just change position with position+1.

Also you are inserting the int value of your drawable resource which is not a good idea. This value is not necessarily constant throughout the life of your app -- a later version may issue a new value to this resource.
So please do not do this.
insertSalatki(db, "Greek salad", R.drawable.salad_greek, 0);
Instead map the drawable to an independent yet constant reference. Some thing like:
insertSalatki(db, "Greek salad", idSaladGreek, 0);
So, since you have potentially many rows in your database with the same salad type (eg. Greek Salad) with potentially many different resource ids, when you query your database for a salad type yon might be getting the wrong resource id. This might be causing the problem of you not being able to display your image.
Test this by comparing the int value coming from the database (int photoId = cursor.getInt(1)) and the int value of R.drawable.salad_greek.
In your SaladDetailActivity you should also check to see if you are getting a valid value for:
int salads = (Integer) getIntent().getExtras().get(EXTRA_SALAD);

Related

The ListView doesn't show me a list with names from database. I use SimpleCursorAdapter

im trying to implement database to my aplication. It is first time when i am doing this.
I have a layout with list view and im using a SimpleCoursorAdapter to transport data from dataBase to my ListView. The aplication doesn't show anything. ListView is empty i don't know why.
It is my TopLevelActivity
public class TopLevelActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_top_level);
AdapterView.OnItemClickListener itemClickListener =
new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView,
View v,
int position,
long id) {
if(position == 0){
Intent intent = new Intent(TopLevelActivity.this, DrinkCategoryActivity.class);
startActivity(intent);
}
if(position == 1){
Intent intent = new Intent(TopLevelActivity.this, SnacksCategoryActivity.class);
startActivity(intent);
}
}
};
ListView listView = (ListView) findViewById(R.id.list_options);
listView.setOnItemClickListener(itemClickListener);
}
}
xml from TopLevelActivity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".TopLevelActivity">
<ImageView
android:layout_width="200dp"
android:layout_height="100dp"
android:src="#drawable/starbuzz_logo"
android:contentDescription="#string/starbuzz_logo"/>
<ListView
android:id="#+id/list_options"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="#array/options"/>
</LinearLayout>
the DrinkCategoryActivity i think here is somethink wrong
public class DrinkCategoryActivity extends Activity {
private SQLiteDatabase db;
private Cursor cursor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink_category);
ListView listDrinks = (ListView) findViewById(R.id.list_drinks);
SQLiteOpenHelper coffeinaDatabaseHelper = new CoffeinaDatabaseHelper(this);
try {
db = coffeinaDatabaseHelper.getReadableDatabase();
cursor = db.query("DRINK",
new String[]{"_id", "NAME"},
null, null, null, null, null);
SimpleCursorAdapter listAdapter = new SimpleCursorAdapter
(this,
android.R.layout.simple_list_item_1,
cursor,
new String[]{"NAME"},
new int[]{android.R.id.text1},0
);
listDrinks.setAdapter(listAdapter);
} catch (SQLiteException e) {
Toast toast = Toast.makeText(this, "Baza danych jest niedostepna",
Toast.LENGTH_SHORT);
toast.show();
}
AdapterView.OnItemClickListener itemClickListener =
new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> listDrinks,
View itemView,
int position,
long id) {
Intent intent = new Intent(DrinkCategoryActivity.this,
DrinkActivity.class);
intent.putExtra(DrinkActivity.EXTRA_DRINKID, (int) id);
startActivity(intent);
}
};
listDrinks.setOnItemClickListener(itemClickListener);
}
public void onDestroy() {
super.onDestroy();
cursor.close();
db.close();
}
}
xml from DrinkCategoryActivity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".DrinkCategoryActivity">
<ListView
android:id="#+id/list_drinks"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
DrinkAtivity
public class DrinkActivity extends AppCompatActivity {
public static final String EXTRA_DRINKID = "drinkId";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink);
int drinkId = (Integer)getIntent().getExtras().get(EXTRA_DRINKID);
SQLiteOpenHelper starbuzzDatabaseHelper = new CoffeinaDatabaseHelper(this);
try{
SQLiteDatabase db = starbuzzDatabaseHelper.getReadableDatabase();
Cursor cursor = db.query("DRINK",
new String[]{"NAME", "DESCRIPTION", "IMAGE_RESORUCE_ID"},
"_id = ?",
new String[]{Integer.toString(drinkId)},
null, null, null);
if(cursor.moveToFirst()){
String nameText = cursor.getString(0);
String descriptionText = cursor.getString(1);
int photoId = cursor.getInt(2);
TextView name = (TextView)findViewById(R.id.name);
name.setText(nameText);
TextView description = (TextView)findViewById(R.id.description);
description.setText(descriptionText);
ImageView photo = (ImageView)findViewById(R.id.latte);
photo.setImageResource(photoId);
photo.setContentDescription(nameText);
}
cursor.close();
db.close();
}catch (SQLiteException e){
Toast toast = Toast.makeText(this, "Bada danych jest niedostepna",
Toast.LENGTH_SHORT);
toast.show();
}
}
}
xml from DrinkActivity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".DrinkActivity">
<ImageView
android:id="#+id/latte"
android:layout_width="190dp"
android:layout_height="190dp"/>
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
and my DataBaseHelper and here can be also somethink wrong.
The complicator doesn't show any error.
package com.hfad.coffeina;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class CoffeinaDatabaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "coffeina";
private static final int DB_VERSION = 2;
CoffeinaDatabaseHelper(Context context){
super(context, DB_NAME, null, DB_VERSION);
}
public void onCreate(SQLiteDatabase db){
updateMyDatabase(db, 0, DB_VERSION);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
updateMyDatabase(db, oldVersion, newVersion);
}
private static void insertDrink(SQLiteDatabase db, String name, String description,
int resourceId){
ContentValues drinkValues = new ContentValues();
drinkValues.put("NAME", name);
drinkValues.put("DESCRIPTION", description);
drinkValues.put("IMAGE_RESOURCE_ID", resourceId);
db.insert("DRINK", null, drinkValues);
}
private void updateMyDatabase(SQLiteDatabase db, int oldVersion, int newVersion){
if(oldVersion < 1){
db.execSQL("CREATE TABLE DRINK (_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+"NAME TEXT, "
+"DESCRIPTON TEXT , "
+"IMAGE_RESOURCE_ID INTEGER);");
insertDrink(db, "Latte", "Czarne espresso z gorącym mlekiem i mleczną pianką.",
R.drawable.latte);
insertDrink(db, "Cappucciono", "Czarne espresso z dużą ilościa spienionego mleka",
R.drawable.cappuccino);
insertDrink(db, "Espresso", "Czarna kawa ze świeżo mielonych ziaren najwyższej jakości.",
R.drawable.filter);
}
if(oldVersion < 2){
db.execSQL("ALTER TABLE DRINK ADD COLUMN FAVORITE NUMERIC;");
}
}
}
The print Screen from emulator enter image description here
The Issue
I believe that your prime issue is that in the DRINK table you define a column name using +"DESCRIPTON TEXT , " yet you refer to the DESCRIPTION column (tion as opposed to ton) elsewhere including when inserting the 3 initial rows. Hidden/disguised because they are in try .... catch constructs.
Note that wrapping SQLite stuff in try .... catch is typically unhelpful and leads to confusion, especially if the log isn't checked when testing.
That is the log would show something like :-
07-21 17:29:20.748 4340-4340/a.a.so68457788javesqlitelistview E/SQLiteLog: (1) table DRINK has no column named DESCRIPTION
07-21 17:29:20.749 4340-4340/a.a.so68457788javesqlitelistview E/SQLiteDatabase: Error inserting NAME=Latte DESCRIPTION=Czarne espresso z gorącym mlekiem i mleczną pianką. IMAGE_RESOURCE_ID=10
android.database.sqlite.SQLiteException: table DRINK has no column named DESCRIPTION (code 1): , while compiling: INSERT INTO DRINK(NAME,DESCRIPTION,IMAGE_RESOURCE_ID) VALUES (?,?,?)
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:887)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:498)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1469)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341)
at a.a.so68457788javesqlitelistview.CoffeinaDatabaseHelper.insertDrink(CoffeinaDatabaseHelper.java:32)
at a.a.so68457788javesqlitelistview.CoffeinaDatabaseHelper.updateMyDatabase(CoffeinaDatabaseHelper.java:42)
at a.a.so68457788javesqlitelistview.CoffeinaDatabaseHelper.onCreate(CoffeinaDatabaseHelper.java:18)
As such the database will be empty and hence why the ListView shows nothing.
I would suggest ALWAYS using a single definition for database components and ALWAYS referring to the components using the single definition.
Suggested Fix/Improvment
Perhaps consider using :-
class CoffeinaDatabaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "coffeina";
private static final int DB_VERSION = 2;
public static final String DRINK_TABLENAME = "DRINK";
public static final String DRINK_ID_COLUMN = BaseColumns._ID; // Android _id column name
public static final String DRINK_NAME_COLUMN = "NAME";
public static final String DRINK_DESCRIPTION_COLUMN = "DESCRIPTION";
public static final String DRINK_IMAGE_RESOURCE_ID_COLUMN = "IMAGE_RESOURCE_ID";
public static final String DRINK_FAVORITE_COLUMN = "FAVOURITE";
CoffeinaDatabaseHelper(Context context){
super(context, DB_NAME, null, DB_VERSION);
}
public void onCreate(SQLiteDatabase db){
updateMyDatabase(db, 0, DB_VERSION);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
updateMyDatabase(db, oldVersion, newVersion);
}
private static void insertDrink(SQLiteDatabase db, String name, String description,
int resourceId){
ContentValues drinkValues = new ContentValues();
drinkValues.put(DRINK_NAME_COLUMN, name);
drinkValues.put(DRINK_DESCRIPTION_COLUMN, description);
drinkValues.put(DRINK_IMAGE_RESOURCE_ID_COLUMN, resourceId);
db.insert(DRINK_TABLENAME, null, drinkValues);
}
private void updateMyDatabase(SQLiteDatabase db, int oldVersion, int newVersion){
if(oldVersion < 1){
/* no need for autoincrement id's will be generated without the overheads
check https://sqlite.org/autoinc.html for details/why
*/
db.execSQL("CREATE TABLE " + DRINK_TABLENAME + " (" + DRINK_ID_COLUMN + " INTEGER PRIMARY KEY, "
+ DRINK_NAME_COLUMN + " TEXT,"
+ DRINK_DESCRIPTION_COLUMN +" TEXT , "
+ DRINK_IMAGE_RESOURCE_ID_COLUMN + " INTEGER);");
insertDrink(db, "Latte", "Czarne espresso z gorącym mlekiem i mleczną pianką.",10);
insertDrink(db, "Cappucciono", "Czarne espresso z dużą ilościa spienionego mleka", 11);
insertDrink(db, "Espresso", "Czarna kawa ze świeżo mielonych ziaren najwyższej jakości.", 12);
}
if(oldVersion < 2){
db.execSQL("ALTER TABLE DRINK ADD COLUMN " + DRINK_FAVORITE_COLUMN + " NUMERIC;");
}
}
}
NOTE for testing the image resource id's have been made up, these will need to be changed to reflect your original code.
And then subsequently referring the the database components elsewhere using the constants. For example consider the following version of the DrinkCategoryActivity class :-
public class DrinkCategoryActivity extends AppCompatActivity {
CoffeinaDatabaseHelper coffeinaDatabaseHelper; //<<<<< ADDED you want instance of YOUR helper not an SQLiteOpenHelper
SQLiteDatabase db;
Cursor cursor;
SimpleCursorAdapter listAdapter; //<<<<< Better here, more scope
ListView listDrinks;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink_category);
listDrinks = (ListView) findViewById(R.id.list_drinks);
// SQLiteOpenHelper coffeinaDatabaseHelper = new CoffeinaDatabaseHelper(this);
coffeinaDatabaseHelper = new CoffeinaDatabaseHelper(this);
db = coffeinaDatabaseHelper.getWritableDatabase(); // get readable will typically get writeable anyway
setOrRefreshListView();
}
private void setOrRefreshListView() {
cursor = db.query(CoffeinaDatabaseHelper.DRINK_TABLENAME,
new String[]{"_id", CoffeinaDatabaseHelper.DRINK_NAME_COLUMN},
null, null, null, null, null);
if (listAdapter == null) {
listAdapter = new SimpleCursorAdapter(
this,
android.R.layout.simple_list_item_1, cursor,
new String[]{"NAME"},
new int[]{android.R.id.text1}, 0);
listDrinks.setAdapter(listAdapter);
listDrinks.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(view.getContext(), DrinkActivity.class);
intent.putExtra(DrinkActivity.EXTRA_DRINKID, l);
startActivity(intent);
}
});
} else {
listAdapter.swapCursor(cursor);
}
}
/* If returning to Activity (from DrinkActivity) refresh the ListView
just in case it has changed
*/
#Override
protected void onResume() {
super.onResume();
setOrRefreshListView();
}
#Override
protected void onDestroy() {
super.onDestroy();
cursor.close();
}
}
Using the above then :-
Additional
taking the above further then a working (albeit without the images) and more concise version of the DrinkActity is :-
public class DrinkActivity extends AppCompatActivity {
public static final String EXTRA_DRINKID = "drinkId";
CoffeinaDatabaseHelper DBHelper;
SQLiteDatabase db;
TextView name,description;
ImageView photo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink);
long drinkId = this.getIntent().getLongExtra(DrinkActivity.EXTRA_DRINKID,-1); // Should be LONG
DBHelper = new CoffeinaDatabaseHelper(this);
db = DBHelper.getWritableDatabase();
name = this.findViewById(R.id.name);
description = this.findViewById(R.id.description);
Cursor cursor = db.query(CoffeinaDatabaseHelper.DRINK_TABLENAME,
null,
CoffeinaDatabaseHelper.DRINK_ID_COLUMN +" = ?",
new String[]{String.valueOf(drinkId)}, // cope with Long
null, null, null);
if(cursor.moveToFirst()){
name.setText(cursor.getString(cursor.getColumnIndex(CoffeinaDatabaseHelper.DRINK_NAME_COLUMN)));
description.setText(cursor.getString(cursor.getColumnIndex(CoffeinaDatabaseHelper.DRINK_DESCRIPTION_COLUMN)));
//<<<<< COMMENTED OUT FOR TESTING (as invalid resource id's have been used) >>>>>
//photo.setImageResource(cursor.getInt(cursor.getColumnIndex(CoffeinaDatabaseHelper.DRINK_IMAGE_RESOURCE_ID_COLUMN)));
//photo.setContentDescription(cursor.getString(cursor.getColumnIndex(CoffeinaDatabaseHelper.DRINK_NAME_COLUMN)));
} else {
Toast.makeText(this, "Bada danych jest niedostepna", Toast.LENGTH_SHORT).show();
}
cursor.close();
//db.close(); don't close, resource expensive to open
}
}
So selecting Latte gives :-

Search and display entries in SQLite Database

So I recently got into Android programming and have been following this tutorial on how to insert, update, delete and view data in an SQLite database. Now, I would also like to add a search functionality to this SQLite database where I can search for a name (the columns I'm using are name, contact and DOB) and if the searched for name matches an existing one in the database, display this row/entry from the database in the application. I figured this could be done in a similar way as the viewing/updating the database, so I tried coming up with a solution for this with these as reference, however after having tried a good amount of ways that seemed reasonable to me I still haven't gotten it to work, so I'd greatly appreciate any help with this! I feel like I was close w/ some of my attempts but something with the logic didn't click completely.
MainActivity.java:
package com.example.sqliteapplication;
import ...
public class MainActivity extends AppCompatActivity {
EditText name, contact, dob;
Button insert, update, delete, view, search;
DBHelper DB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name = findViewById(R.id.name);
contact = findViewById(R.id.contact);
dob = findViewById(R.id.dob);
insert = findViewById(R.id.btnInsert);
update = findViewById(R.id.btnUpdate);
delete = findViewById(R.id.btnDelete);
view = findViewById(R.id.btnView);
search = findViewById(R.id.btnSearch);
DB = new DBHelper(this);
insert.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String nameTXT = name.getText().toString();
String contactTXT = contact.getText().toString();
String dobTXT = dob.getText().toString();
Boolean checkinsertdata = DB.insertuserdata(nameTXT, contactTXT, dobTXT);
if(checkinsertdata==true)
Toast.makeText(MainActivity.this, "New Entry Inserted", Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "New Entry Not Inserted", Toast.LENGTH_SHORT).show();
} });
update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String nameTXT = name.getText().toString();
String contactTXT = contact.getText().toString();
String dobTXT = dob.getText().toString();
Boolean checkupdatedata = DB.updateuserdata(nameTXT, contactTXT, dobTXT);
if(checkupdatedata==true)
Toast.makeText(MainActivity.this, "Entry Updated", Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "New Entry Not Updated", Toast.LENGTH_SHORT).show();
} });
delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String nameTXT = name.getText().toString();
Boolean checkudeletedata = DB.deletedata(nameTXT);
if(checkudeletedata==true)
Toast.makeText(MainActivity.this, "Entry Deleted", Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "Entry Not Deleted", Toast.LENGTH_SHORT).show();
} });
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Cursor res = DB.getdata();
if(res.getCount()==0){
Toast.makeText(MainActivity.this, "No Entry Exists", Toast.LENGTH_SHORT).show();
return;
}
StringBuffer buffer = new StringBuffer();
while(res.moveToNext()){
buffer.append("Name :"+res.getString(0)+"\n");
buffer.append("Contact :"+res.getString(1)+"\n");
buffer.append("Date of Birth :"+res.getString(2)+"\n\n");
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setCancelable(true);
builder.setTitle("User Entries");
builder.setMessage(buffer.toString());
builder.show();
} });
}
}
DBHelper.java:
package com.example.sqliteapplication;
import ...
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, "Userdata.db", null, 1);
}
#Override
public void onCreate(SQLiteDatabase DB) {
DB.execSQL("create Table Userdetails(name TEXT primary key," +
"contact TEXT, dob TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase DB, int oldVersion, int newVersion) {
DB.execSQL("drop Table if exists Userdetails");
}
public Boolean insertuserdata(String name, String contact, String dob) {
SQLiteDatabase DB = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("name", name);
contentValues.put("contact", contact);
contentValues.put("dob", dob);
long result = DB.insert("Userdetails",
null, contentValues);
if (result == -1) {
return false;
} else {
return true;
}
}
public Boolean updateuserdata(String name, String contact, String dob) {
SQLiteDatabase DB = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("contact", contact);
contentValues.put("dob", dob);
Cursor cursor = DB.rawQuery(
"Select * from Userdetails where name = ?", new String[]{name});
if (cursor.getCount() > 0) {
long result = DB.update("Userdetails",
contentValues, "name=?",
new String[]{name});
if (result == -1) {
return false;
} else {
return true;
}
} else {
return false;
}
}
public Boolean deletedata(String name) {
SQLiteDatabase DB = this.getWritableDatabase();
Cursor cursor = DB.rawQuery(
"Select * from Userdetails where name = ?", new String[]{name});
if (cursor.getCount() > 0) {
long result = DB.delete("Userdetails", "name=?",
new String[]{name});
if (result == -1) {
return false;
} else {
return true;
}
} else {
return false;
}
}
public Cursor getdata () {
SQLiteDatabase DB = this.getWritableDatabase();
Cursor cursor = DB.rawQuery(
"Select * from Userdetails ", null);
return cursor;
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
tools:context=".MainActivity">
<TextView
android:id="#+id/texttitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Please enter details below"
android:textSize="24dp"
android:layout_marginTop="20dp"
/>
<EditText
android:id="#+id/name"
android:hint="Name"
android:textSize="24dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/texttitle"
android:inputType="textPersonName"
/>
<EditText
android:id="#+id/contact"
android:hint="Contact"
android:textSize="24dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/name"
android:inputType="number"
/>
<EditText
android:id="#+id/dob"
android:hint="Date of Birth"
android:textSize="24dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/contact"
android:inputType="number"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/btnInsert"
android:textSize="24dp"
android:text="Insert New Data"
android:layout_marginTop="30dp"
android:layout_below="#+id/dob"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/btnUpdate"
android:textSize="24dp"
android:text="Update Data"
android:layout_below="#+id/btnInsert"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/btnDelete"
android:textSize="24dp"
android:text="Delete Data"
android:layout_below="#+id/btnUpdate"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/btnView"
android:textSize="24dp"
android:text="View Data"
android:layout_below="#+id/btnDelete"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/btnSearch"
android:textSize="24dp"
android:text="Search Data"
android:layout_below="#+id/btnView"
/>
</RelativeLayout>
Sorry in advance for perhaps some bad explanations/something not making sense, I'm only a few weeks into this and got a lot to learn for sure! Thanks
You can modify getdata() so that it takes as an argument the name, or part of the name that you search for:
public Cursor getdata(String name) {
SQLiteDatabase DB = this.getWritableDatabase();
String sql = "Select * from Userdetails";
String[] selectionArgs = null;
if (name != null) {
sql += " where name LIKE '%' || ? || '%'";
selectionArgs = new String[] {name};
}
return DB.rawQuery(sql, selectionArgs);
}
and you should also modify in the listener of the button view the call to getdata() to pass null so that you get as result all the rows of the table:
Cursor res = DB.getdata(null);
Then you create the listener for the button search:
search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String searchName = name.getText().toString().trim();
if (searchName.length() == 0) return;
Cursor res = DB.getdata(searchName);
if(res.getCount()==0){
Toast.makeText(MainActivity.this, "No Entry Exists", Toast.LENGTH_SHORT).show();
return;
}
StringBuffer buffer = new StringBuffer();
while(res.moveToNext()){
buffer.append("Name :"+res.getString(0)+"\n");
buffer.append("Contact :"+res.getString(1)+"\n");
buffer.append("Date of Birth :"+res.getString(2)+"\n\n");
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setCancelable(true);
builder.setTitle("User Entries");
builder.setMessage(buffer.toString());
builder.show();
}
});
Note that there is no need to query the table before you insert, update, delete a row.
You can perform the operation that you want and then examine the result of the method insert() or update() or delete() to decide whether it was successful or not.
Remember that only insert() returns -1 if unsuccessful.
update() and delete() return the number of affected (updated/deleted) rows.
So, I would write the code like this:
package com.example.sqliteapplication;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, "Userdata.db", null, 1);
}
#Override
public void onCreate(SQLiteDatabase DB) {
DB.execSQL("create Table Userdetails(name TEXT primary key, contact TEXT, dob TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase DB, int oldVersion, int newVersion) {
DB.execSQL("drop Table if exists Userdetails");
}
public Boolean insertuserdata(String name, String contact, String dob) {
SQLiteDatabase DB = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("name", name);
contentValues.put("contact", contact);
contentValues.put("dob", dob);
long result = DB.insert("Userdetails", null, contentValues);
return (result != -1);
}
public Boolean updateuserdata(String name, String contact, String dob) {
SQLiteDatabase DB = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("contact", contact);
contentValues.put("dob", dob);
long result = DB.update("Userdetails", contentValues, "name = ?", new String[]{name});
return (result > 0);
}
public Boolean deletedata(String name) {
SQLiteDatabase DB = this.getWritableDatabase();
long result = DB.delete("Userdetails", "name = ?", new String[]{name});
return (result > 0);
}
public Cursor getdata(String name) {
SQLiteDatabase DB = this.getWritableDatabase();
String sql = "Select * from Userdetails";
String[] selectionArgs = null;
if (name != null) {
sql += " where name LIKE '%' || ? || '%'";
selectionArgs = new String[] {name};
}
return DB.rawQuery(sql, selectionArgs);
}
}
and for the activity class:
package com.example.sqliteapplication;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
EditText name, contact, dob;
Button insert, update, delete, view, search;
DBHelper DB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name = findViewById(R.id.name);
contact = findViewById(R.id.contact);
dob = findViewById(R.id.dob);
insert = findViewById(R.id.btnInsert);
update = findViewById(R.id.btnUpdate);
delete = findViewById(R.id.btnDelete);
view = findViewById(R.id.btnView);
search = findViewById(R.id.btnSearch);
DB = new DBHelper(this);
insert.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String nameTXT = name.getText().toString().trim();
String contactTXT = contact.getText().toString().trim();
String dobTXT = dob.getText().toString().trim();
Boolean checkinsertdata = DB.insertuserdata(nameTXT, contactTXT, dobTXT);
if(checkinsertdata==true)
Toast.makeText(MainActivity.this, "New Entry Inserted", Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "New Entry Not Inserted", Toast.LENGTH_SHORT).show();
}
});
update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String nameTXT = name.getText().toString().trim();
String contactTXT = contact.getText().toString().trim();
String dobTXT = dob.getText().toString().trim();
Boolean checkupdatedata = DB.updateuserdata(nameTXT, contactTXT, dobTXT);
if(checkupdatedata==true)
Toast.makeText(MainActivity.this, "Entry Updated", Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "New Entry Not Updated", Toast.LENGTH_SHORT).show();
}
});
delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String nameTXT = name.getText().toString().trim();
Boolean checkudeletedata = DB.deletedata(nameTXT);
if(checkudeletedata==true)
Toast.makeText(MainActivity.this, "Entry Deleted", Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "Entry Not Deleted", Toast.LENGTH_SHORT).show();
}
});
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Cursor res = DB.getdata(null);
if(res.getCount()==0){
Toast.makeText(MainActivity.this, "No Entry Exists", Toast.LENGTH_SHORT).show();
return;
}
StringBuffer buffer = new StringBuffer();
while(res.moveToNext()){
buffer.append("Name :"+res.getString(0)+"\n");
buffer.append("Contact :"+res.getString(1)+"\n");
buffer.append("Date of Birth :"+res.getString(2)+"\n\n");
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setCancelable(true);
builder.setTitle("User Entries");
builder.setMessage(buffer.toString());
builder.show();
}
});
search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String searchName = name.getText().toString().trim();
if (searchName.length() == 0) return;
Cursor res = DB.getdata(searchName);
if(res.getCount()==0){
Toast.makeText(MainActivity.this, "No Entry Exists", Toast.LENGTH_SHORT).show();
return;
}
StringBuffer buffer = new StringBuffer();
while(res.moveToNext()){
buffer.append("Name :"+res.getString(0)+"\n");
buffer.append("Contact :"+res.getString(1)+"\n");
buffer.append("Date of Birth :"+res.getString(2)+"\n\n");
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setCancelable(true);
builder.setTitle("User Entries");
builder.setMessage(buffer.toString());
builder.show();
}
});
}
}
In DBHelper.java add:
public Cursor getDataByName(String name){
SQLiteDatabase db = this.getWritableDatabase();
return db.rawQuery("SELECT * FROM Userdetails WHERE name LIKE '%"+name+"'%", null);
}
In MainActivity.java:
Add a new global EditText:
EditText name, contact, dob, **search**;
onCreate() add:
search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
searchInDatabase();
}
}
Somewhere in your MainActivity.java add this new method.
private void searchInDatabaseByName(){
Cursor res = DB.getDataByName(name.getText().toString());
if(res.getCount()==0){
Toast.makeText(MainActivity.this, "No Entry Exists", Toast.LENGTH_SHORT).show();
return;
}
Cursor res = DB.getdata();
if(res.getCount()==0){
Toast.makeText(MainActivity.this, "No Entry Exists", Toast.LENGTH_SHORT).show();
return;
}
StringBuffer buffer = new StringBuffer();
while(res.moveToNext()){
buffer.append("Name :"+res.getString(0)+"\n");
buffer.append("Contact :"+res.getString(1)+"\n");
buffer.append("Date of Birth :"+res.getString(2)+"\n\n");
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setCancelable(true);
builder.setTitle("User Entries");
builder.setMessage(buffer.toString());
builder.show();
}
Now the explanation:
In sqlite you can query for data using the LIKE keyword. for example in order to find all the rows with the name 'Bob' you can query for
SELECT * FROM Userdetails WHERE name LIKE '%Bob%'
Then, the returned cursor will contain all the rows that have the name Bob.
Then we've added another EditText variable to search (you'll need to add it to the main_acitivity.xml as well).
Now you can use that to type in the name you want to search and then click the 'search' button, which in return will call the 'searchInDatabaseByName' method which does the exact same thing as your 'view' button but simply goes to our new DBHelper method 'getDataByName'.
Please notice that its recommended to let the DBHelper do all the stuff of fetching the actual data (meaning it will get the cursor and also parse it)
You might want to create a model class for your User entity.
and then the database method will return an arraylist of users which will later be much easier to show in a Dialog (or even better, in a ListView)

Updating a certain value and saving it in offline database

I'm developing a tiny app that has a value in a textview set to 150,000 by default. Each month I reset the value back to the default. Every time I spend some of that amount, I open my app and enter the amount I spent and the details of what it was spent on.
What I did was create an offline database to store all the times I spent some of that amount, along with it's id and details. Each time I press the "spend" button, the total amount is reduced by the amount I have entered in the EditText.
I haven't implemented how I'll update the total amount yet, I believe I have to use something called sharedpreference number.
This is the main activity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button spendMoney = (Button)this.findViewById(R.id.spendMoney);
Button test = (Button)this.findViewById(R.id.test);
TextView totalTxt = (TextView) this.findViewById(R.id.totalTxt);
final EditText spendAmount = (EditText)this.findViewById(R.id.spendAmount);
// int totalAmount = Integer.parseInt(totalTxt.getText().toString());
final Paid_DB db = new Paid_DB(this);
spendMoney.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
db.addPayment(new Payment(0, (Integer.parseInt(spendAmount.getText().toString())), "Test Details"));
}
});
//totalAmount = totalAmount - Integer.parseInt(spendAmount.getText().toString());
// totalTxt.setText(totalAmount);
test.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(null, DetailsActivity.class);
startActivity(i);
}
});
XML file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.user.paid.MainActivity">
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="13dp"
android:layout_marginStart="13dp"
android:layout_marginTop="53dp"
android:fontFamily="sans-serif"
android:text="Total:"
android:textSize="30sp"
tools:layout_editor_absoluteX="25dp"
tools:layout_editor_absoluteY="36dp" />
<EditText
android:id="#+id/spendAmount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number"
tools:layout_editor_absoluteX="72dp"
tools:layout_editor_absoluteY="143dp"
android:layout_marginBottom="38dp"
android:layout_above="#+id/spendMoney"
android:layout_centerHorizontal="true" />
<Button
android:id="#+id/spendMoney"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Spend Money"
tools:layout_editor_absoluteX="115dp"
tools:layout_editor_absoluteY="215dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<TextView
android:id="#+id/totalTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/textView3"
android:layout_alignBottom="#+id/textView3"
android:layout_alignEnd="#+id/spendMoney"
android:layout_alignRight="#+id/spendMoney"
android:fontFamily="sans-serif"
android:text="150,000"
android:textSize="30sp"
tools:layout_editor_absoluteX="25dp"
tools:layout_editor_absoluteY="36dp" />
<Button
android:id="#+id/test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test"
tools:layout_editor_absoluteX="134dp"
tools:layout_editor_absoluteY="358dp"
android:layout_marginBottom="90dp"
android:layout_alignParentBottom="true"
android:layout_alignLeft="#+id/spendMoney"
android:layout_alignStart="#+id/spendMoney" />
This is the object I enter into the offline database, containing the id, the amount spent, and details of the payment:
public class Payment {
private int id;
private int amount;
private String details;
public Payment(){}
public Payment(int id, int amount, String details) {
this.id = id;
this.amount = amount;
this.details = details;
}
public Payment(int id, int amount) {
this.id = id;
this.amount = amount;
}
public Payment(int amount, String details) {
this.amount = amount;
this.details = details;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
} }
This is the offline database:
ublic class Paid_DB extends SQLiteOpenHelper {
// All Static variables
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "Payments_DB";
// Contacts table name
private static final String PAYMENT_TABLE = "PaymentTable";
// Contacts Table Columns names
private static final String PAY_ID = "id";
private static final String PAY_AMOUNT = "amount";
private static final String PAY_DETAILS = "details";
Paid_DB(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_CONTACTS_TABLE = "CREATE TABLE " + PAYMENT_TABLE + "("
+ PAY_ID + " INTEGER PRIMARY KEY," + PAY_AMOUNT + " INTEGER,"
+ PAY_DETAILS + " TEXT" + ")";
db.execSQL(CREATE_CONTACTS_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + PAYMENT_TABLE);
onCreate(db);
}
public void addPayment(Payment payment){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(PAY_AMOUNT, payment.getAmount());
values.put(PAY_DETAILS, payment.getDetails()); // Contact Phone Number
// Inserting Row
db.insert(PAYMENT_TABLE, null, values);
db.close();
}
void addListItem(ArrayList<String> listItem) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
for (int i = 0; i < listItem.size(); i++) {
Log.e("vlaue inserting==", "" + listItem.get(i));
values.put(PAY_AMOUNT, listItem.get(i));
db.insert(PAYMENT_TABLE, null, values);
}
db.close(); // Closing database connection
}
Cursor getListItem() {
String selectQuery = "SELECT * FROM " + PAYMENT_TABLE;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
return cursor;
}}
And finally, this is the details activity, it contains a list view that stores and displays all the payments that have been made:
public class DetailsActivity extends AppCompatActivity {
ArrayList<String> detailsListArrayList;
private ListView lv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
lv = (ListView) findViewById(R.id.listView);
detailsListArrayList = new ArrayList<>();
detailsListArrayList.add("Item1");
detailsListArrayList.add("Item2");
detailsListArrayList.add("Item3");
detailsListArrayList.add("Item4");
detailsListArrayList.add("Item5");
Paid_DB db = new Paid_DB(this);
db.addListItem(detailsListArrayList);
Cursor cursor = db.getListItem();
Log.e("count", " " + cursor.getCount());
if (cursor != null) {
cursor.moveToNext();
do {
Log.e("value==", "" + cursor.getString(1));
} while (cursor.moveToNext());
}
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
this,
android.R.layout.simple_list_item_1,
detailsListArrayList );
lv.setAdapter(arrayAdapter);
}
}
XML file:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.user.paid.DetailsActivity">
<ListView
android:id="#+id/listView"
android:layout_width="368dp"
android:layout_height="495dp"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp" />
Every time I click on the "test" button, the app crashes. And every time I try to add a new entry using the "spend" button, the app also crashes. What did I do wrong?
What I can tell from here (without the error log) is:
1) your app crashes when pressing the test-button because you are starting an activity there without passing a contextobject. Try this:
public void onClick(View v) {
Intent i = new Intent(getApplicationContext(), DetailsActivity.class);
startActivity(i);
}
2) The spend button tries to add a new payment entry to your database. But in your database schema , you declare the PAY_ID as a primary key. Later in your addPayment() you are just passing the PAY_AMOUNT and PAY_DETAILS, so you are missing the PAY_ID which seems to lead to a crash.
EDIT: something like this should return all the payments as an ArrayList (may Contain bugs, just wrote it in this editor).
public ArrayList<Payment> getAllPayments() {
ArrayList<Payment> result = new ArrayList<>();
Cursor c = db.query("PAYMENTS",new String[]{"PAY_ID","PAY_AMOUNT","PAY_DETAIL"},null,null,null,null,null); ;
c.moveToFirst();
while(! c.isAfterLast())
{
int s1=c.getInt(0);
int s2=c.getInt(1);
String s3=c.getString(2);
results.add(new Payment(s1,s2,s3));
c.moveToNext();
}
return results;
}
To update your ListView, you should have a closer look a this link, that explains how to work with ListViews and a custom ListView adapter Custom Adapter for List View

How would I create new activity where I would have option to add new items from database?

I have created database following this tutorial, and I have created one button in main activity which will take users to another activity where they would add some new items. But I don't know how would I do this with ArrayList because I want to add new items in ListView. I want something like this to have in my application. Any help would be appricieated.
Here's the code of DataBase:
public class DatabaseHandler extends SQLiteOpenHelper {
// All Static variables
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "itemManager";
// Contacts table name
private static final String TABLE_ITEMS = "items";
// Contacts Table Columns names
private static final String KEY_ID = "id";
private static final String KEY_TITLE = "title";
private static final String KEY_PRICE = "price";
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Creating Tables
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_ITEMS_TABLE = "CREATE TABLE " + TABLE_ITEMS + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + KEY_TITLE + " TEXT,"
+ KEY_PRICE + " TEXT" + ")";
db.execSQL(CREATE_ITEMS_TABLE);
}
// Upgrading database
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + TABLE_ITEMS);
// Create tables again
onCreate(db);
}
/**
* All CRUD(Create, Read, Update, Delete) Operations
*/
// Adding new item
void addItem(Item item) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_TITLE, item.getTitle()); // Title Name
values.put(KEY_PRICE, item.getPrice()); // Price
// Inserting Row
db.insert(TABLE_ITEMS, null, values);
db.close(); // Closing database connection
}
// Getting item
Item getItem(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_ITEMS, new String[] { KEY_ID,
KEY_TITLE, KEY_PRICE }, KEY_ID + "=?",
new String[] { String.valueOf(id) }, null, null, null, null);
if (cursor != null)
cursor.moveToFirst();
Item item = new Item(Integer.parseInt(cursor.getString(0)),
cursor.getString(1), cursor.getString(2));
// return item
return item;
}
// Getting All Items
public List<Item> getAllItems() {
List<Item> itemsList = new ArrayList<Item>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_ITEMS;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Item item = new Item();
item.setID(Integer.parseInt(cursor.getString(0)));
item.setTitle(cursor.getString(1));
item.setPrice(cursor.getString(2));
// Adding contact to list
itemsList.add(item);
} while (cursor.moveToNext());
}
// return items list
return itemsList;
}
// Updating single item
public int updateItem(Item item) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_TITLE, item.getTitle());
values.put(KEY_PRICE, item.getPrice());
// updating row
return db.update(TABLE_ITEMS, values, KEY_ID + " = ?",
new String[] { String.valueOf(item.getID()) });
}
// Deleting single item
public void deleteItem(Item item) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_ITEMS, KEY_ID + " = ?",
new String[] { String.valueOf(item.getID()) });
db.close();
}
// Getting items Count
public int getItemsCount() {
String countQuery = "SELECT * FROM " + TABLE_ITEMS;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
cursor.close();
// return count
return cursor.getCount();
}
}
and here is the code of MainActivity:
public class MainActivity extends BaseActivity {
Button addItem;
private Toolbar toolbar;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FrameLayout frameLayout = (FrameLayout)findViewById(R.id.frame_container);
// inflate the custom activity layout
LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View activityView = layoutInflater.inflate(R.layout.activity_main, null,false);
frameLayout.addView(activityView);
// Setting toolbar
toolbar = (Toolbar) findViewById(R.id.app_bar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
DatabaseHandler db = new DatabaseHandler(this);
addItem = (Button) findViewById(R.id.button1);
addItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, AddActivity.class);
startActivity(intent);
}
});
}
}
Here's my Main Activity layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<include
android:id="#+id/app_bar"
layout="#layout/app_bar" />
<Button
android:id="#+id/button1"
style="#style/MyCustomButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="#string/button" />
<ListView
android:id="#+id/list"
android:layout_margin="5dp"
android:layout_below="#+id/relativeLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/button1"
android:layout_centerHorizontal="true"
android:divider="#color/list_divider_row"
android:dividerHeight="10.0sp"
android:listSelector="#drawable/list_row_selector" >
</ListView>
<RelativeLayout
android:id="#+id/relativeLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/listView1"
android:layout_alignRight="#+id/listView1"
android:layout_below="#+id/app_bar"
android:padding="10dp" >
<TextView
android:id="#+id/item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="10dp"
android:layout_marginTop="4dp"
android:text="Items"
android:textColor="#474747"
android:textSize="16sp" />
<TextView
android:id="#+id/item_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="5dp"
android:layout_marginTop="4dp"
android:layout_toRightOf="#+id/item_text"
android:text="(2)"
android:textColor="#474747"
android:textSize="14sp" />
<TextView
android:id="#+id/total_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="Rs. 5700"
android:textColor="#000000"
android:textSize="20dp" />
</RelativeLayout>
</RelativeLayout>
In a nutshell, you need to pass the "result" of adding an item back to the main activity. Then, if there was an item added, you should call your adapter to update the adapter data.
// Your previous code
addItem = (Button) findViewById(R.id.button1);
addItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, AddActivity.class);
startActivityForResult(intent, ADD_ITEM_REQ_CODE);
}
});
// Then handle the result
public void onActivityResult(int reqCode, int resultCode, Intent data){
if (reqCode == ADD_ITEM_REQ_CODE && resultCode == RESULT_OK){
// get your ListView adapter and update data
mListAdapter.notifyDataSetChanged();
}
}
Your second activity, the one that adds an item should call setResult(RESULT_OK) when the item was added successfully and setResult(RESULT_CANCELLED) otherwise.
There some other things with your code, for instance, where do you populate your ListView? Normally, you would get the instance though a findViewById and set an adapter to that ListView, with the corresponding data.
Honestly, I think you should have a look to the tutorials again, specially these:
http://developer.android.com/training/basics/intents/result.html
http://developer.android.com/guide/topics/ui/layout/listview.html

Android contacts - Retrieved Android contacts, how to put them in a simple ListView?

for part of my application I require a list of all contacts (with phone numbers) to be displayed when the option is selected.
Here is the activity which is called when the button is pressed:
package com.example.prototype01;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
public class nominateContactsActivity extends Activity {
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.nominatecontactslayout);
Cursor c = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
String contactName, contactTelNumber = "";
String contactID;
c.moveToFirst();
for (int i = 0; i < c.getCount(); i++) {
contactName = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
contactID = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID));
if (Integer.parseInt(c.getString(c.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
Cursor pCur = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { contactID },null);
while (pCur.moveToNext()) {
contactTelNumber = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
}
Log.i("name ", contactName + " ");
Log.i("number ", contactTelNumber + " ");
c.moveToNext();
}
}
}
As you can see, this code returns the Name and Phone Number of all contacts stored on the handset. Currently, these are simply echoed to logcat. I can't seem to work out how to list these items in a listview instead, with just the name and number displayed. I have followed a couple of tutorials to no avail and so reluctantly i seek your kind assistance. I say reluctantly as I'm sure this question has been answered many times, I just can't seem to apply the solutions to my code!
Thank you in advance!!
Kind Regards,
Antwan
Here is what I would do to put contacts in a listView
In your activity:
private ListView mContactsListView;
private ListContactItemAdapter mContactsListAdapter;
this.mContactsListAdapter = new ListContactItemAdapter(this, R.layout.contact_row);
// after doing setContentView, assuming you have defined a listview in your layout file
this.mContactsListView= (ListView) this.findViewById(R.id.contactsListView);
// You may want to create a custom adapter, which I wrote below for showing you example
this.mContactsListView.setAdapter(this.mContactsListAdapter);
for (/* each contact */) {
Contact contact = new Contact();
contact.name = contactName;
contact.number = contactNumber;
this.mContactsListAdapter.add(contact);
}
// In order to refresh your list and make data appear
this.mContactsListAdapter.notifyDataSetChanged();
Of course in my example you need a model object containing contact data:
public class Contact {
public String name;
public String number;
}
And this could be your custom adapter using the Contact class above:
public class ListContactItemAdapter extends ArrayAdapter<Contact> {
private int mLineLayout;
private LayoutInflater mInflater;
public ListContactItemAdapter(Context pContext, int pLineLayout) {
super(pContext, pLineLayout);
this.mLineLayout = pLineLayout;
this.mInflater = (LayoutInflater) pContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
static class ViewHolder {
TextView contactName;
TextView contactNumber;
}
#Override
public View getView(int pPosition, View pView, ViewGroup pParent) {
ViewHolder holder;
if (pView == null) {
pView = this.mInflater.inflate(this.mLineLayout, null);
holder = new ViewHolder();
holder.contactName = (TextView) pView.findViewById(R.id.contactName);
holder.contactNumber = (TextView) pView.findViewById(R.id.contactNumber);
pView.setTag(holder);
} else {
holder = (ViewHolder) pView.getTag();
}
Contact contact = getItem(pPosition);
if (contact != null) {
holder.contactName.setText(contact.name);
holder.contactNumber.setText(contact.number);
}
return pView;
}
}
For that example your need a layout to define rows, of your listview. This could be a contact_row.xml example:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/contactName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6dp"
android:text="Contact name"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/contactNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/contactName"
android:paddingLeft="6dp"
android:text="number"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
I didn't try but this should work. And anyway, I hope it will make you understand how listviews basically work.
Here is one way to adapt what you already have. I added comments before everything I changed to explain along the way:
public class nominateContactsActivity extends Activity {
// Add a list to keep all the "name: number" strings
private List<String> mNameNumber = new ArrayList<String>();
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.nominatecontactslayout);
Cursor c = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
String contactName, contactTelNumber = "";
String contactID;
// You only need to find these indices once
int idIndex = c.getColumnIndex(ContactsContract.Contacts._ID);
int hasNumberIndex = c.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
int nameIndex = c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
// This is simpler than calling getCount() every iteration
while(c.moveToNext()) {
contactName = c.getString(nameIndex);
contactID = c.getString(idIndex);
// If this is an integer ask for an integer
if (c.getInt(hasNumberIndex)) > 0) {
Cursor pCur = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { contactID },null);
while (pCur.moveToNext()) {
contactTelNumber = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
// Store the "name: number" string in our list
mNameNumber.add(contactName + ": " + contactTelNumber);
}
}
}
// Find the ListView, create the adapter, and bind them
ListView listView = (ListView) findViewById(R.id.listView);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mNameNumber);
listView.setAdapter(adapter);
}
}

Categories