I'm following a tutorial about setting up SQLite database with Android Java. I've created a database and a simple table to contain data about food and its calories. I've setup a few buttons with functions to enter data, view, get information about a specific entry, modify and delete it.
All works well except the button to get a specific entry. When I click on the 'Get Information' button, it's supposed to return with the food name and its calories value, according to the row ID I put.
Can anyone help to look at my code here, to check what's wrong or missing?
Here is the code for the classes. I've excluded some parts which are not related.
Creating the database:
public class FormDatabase
{
public static final String KEY_ROWID = "_id";
public static final String KEY_FOOD = "food_name";
public static final String KEY_CALORIE = "food_calories";
private static final String DATABASE_NAME = "Calories";
private static final String DATABASE_TABLE = "FoodTable";
private static final int DATABASE_VERSION = 2;
private DbHelper ourHelper;
private final Context ourContext;
private SQLiteDatabase ourDatabase;
private static class DbHelper extends SQLiteOpenHelper
{
public DbHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// TODO Auto-generated constructor stub
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" +
KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT , " +
KEY_FOOD + " TEXT NOT NULL , " +
KEY_CALORIE + " TEXT NOT NULL);"
);
}
public String getFood(long l) throws SQLException{
// get data of food name
String[] columns = new String[]{ KEY_ROWID, KEY_FOOD, KEY_CALORIE};
Cursor c = ourDatabase.query(DATABASE_TABLE, columns, KEY_ROWID + "=" + l, null, null, null, null);
if (c != null){
c.moveToFirst();
String food = c.getString(1);
return food;
}
return null;
}
public String getCalorie(long l) throws SQLException{
// get data of food calorie
String[] columns = new String[]{ KEY_ROWID, KEY_FOOD, KEY_CALORIE};
Cursor c = ourDatabase.query(DATABASE_TABLE, columns, KEY_ROWID + "=" +
l, null, null, null, null);
if (c != null){
c.moveToFirst();
String calorie = c.getString(2);
return calorie;
}
return null;
}
Another class for setting the main page:
public class DatabaseMain extends Activity implements OnClickListener{
Button sqlUpdate, sqlView, sqlModify, sqlGetInfo, sqlDelete;
EditText sqlFood, sqlCalorie, sqlRow;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.database_main);
sqlUpdate = (Button) findViewById(R.id.bSQLUpdate);
sqlFood = (EditText) findViewById(R.id.etSQLFood);
sqlCalorie = (EditText) findViewById(R.id.etSQLCalorie);
sqlView = (Button) findViewById (R.id.bSQLopenView);
sqlView.setOnClickListener(this);
sqlUpdate.setOnClickListener(this);
sqlRow = (EditText) findViewById(R.id.etSQLrowInfo);
sqlModify = (Button) findViewById(R.id.bSQLmodify);
sqlGetInfo = (Button) findViewById(R.id.bgetInfo);
sqlDelete = (Button) findViewById(R.id.bSQLdelete);
sqlDelete.setOnClickListener(this);
sqlModify.setOnClickListener(this);
sqlDelete.setOnClickListener(this);
}
public void onClick(View arg0)
{
// When click on buttons, data entry into database, view, modify and
delete row
switch (arg0.getId())
{
case R.id.bgetInfo:
try {
String s = sqlRow.getText().toString();
long l = Long.parseLong(s);
FormDatabase foodcal = new FormDatabase(this);
foodcal.open();
String returnedFood = foodcal.getFood(l);
String returnedCalories = foodcal.getCalorie(l);
foodcal.close();
sqlFood.setText(returnedFood);
sqlCalorie.setText(returnedCalories);
}catch (Exception e)
{
String error = e.toString();
Dialog d = new Dialog(this);
d.setTitle("This is an error!");
TextView tv = new TextView(this);
tv.setText(error);
d.setContentView(tv);
d.show();
}
break;
}
}
The database_main layout xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width ="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView1"
android:text="Food"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"/>
<EditText
android:id="#+id/etSQLFood"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text" >
</EditText>
<TextView
android:id="#+id/textView3"
android:text="Food Calorie"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<EditText
android:id="#+id/etSQLCalorie"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" >
</EditText>
<Button
android:text="Update SQLite Database"
android:id="#+id/bSQLUpdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
<Button
android:text="View"
android:id="#+id/bSQLopenView"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
<TextView
android:id="#+id/textView2"
android:text="Enter Row ID"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<EditText
android:id="#+id/etSQLrowInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" >
<requestFocus></requestFocus>
</EditText>
<Button
android:text="Get Information"
android:id="#+id/bgetInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
<Button
android:text="Edit Entry"
android:id="#+id/bSQLmodify"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
<Button
android:text="Delete Entry"
android:id="#+id/bSQLdelete"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
</LinearLayout>
to add a check to your switch statement, add a default case:
switch (arg0.getId())
{
case R.id.bgetInfo:
... do something...
break;
default:
//this will handle everything else
// write out the argument for debugging, eg:
Console.WriteLine(arg0.getId().ToString());
break;
}
this will tell you what is coming through. if arg0.getId() is not R.id.bgetInfo, the event won't fire...
Cursor c = ourDatabase.query(DATABASE_TABLE, columns, KEY_ROWID + "=" +
l, null, null, null, null);
instead using above statement use this one
Cursor c = ourDatabase.query(DATABASE_TABLE, columns, KEY_ROWID + "=?",
new String[] { String.valueOf(l) }, null, null, null, null);
Related
I have created an app with an SQLite database and a ListView that I want to populate using the database. To do this I have written an adapter class called HomeListAdapter. This class takes 4 string arrays as input and that is where my problem is. At first, I just used random string arrays to populate the ListView by typing them myself, for example:
String[] homelist_name_short = {
"Flower", "Bush", "Tree"};
String[] homelist_name_long = {
"Red rose", "Berry bush", "Oak"};
String[] homelist_date = {
"20-9-2017", "11-10-2017", "12-10-2017"};
String[] homelist_price = {
"€1.50", "€2.48", "€0.68"};
Now I want this to be put into the listview automatically and to do that I have written the code that can be seen below..
I have created a class called Home:
public class Home {
private String mShortHomeName;
private String mLongHomeName;
private String mHomeDate;
private String mHomePrice;
public Home(String ShortName, String LongName, String Date, String Price) {
this.mShortHomeName = ShortName;
this.mLongHomeName = LongName;
this.mHomeDate = Date;
this.mHomePrice = Price;
}
public String getShortName() {
return this.mShortHomeName;
}
public String getLongName() {
return this.mLongHomeName;
}
public String getDate() {
return this.mHomeDate;
}
public String getPrice() {
return this.mHomePrice;
}
}
Added the following to my DatabaseHelper:
public Cursor getAllHomesAsCursor() {
SQLiteDatabase db = this.getWritableDatabase();
String[] columns = {"rowid as _id","*"};
return db.query(TABLE_NAME,columns,null,null,null,null,null);
}
The following to the activity that contains my listview:
DatabaseHelper db = new DatabaseHelper(getActivity());
Cursor csr = db.getAllHomesAsCursor();
HLAdapter adapter = new HLAdapter(getActivity(), csr);
listView.setAdapter(adapter);
The HLAdapter looks as follows:
public class HLAdapter extends CursorAdapter {
public HLAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
#Override
public View newView(Context context, Cursor csr, ViewGroup parent) {
return LayoutInflater.from(context).inflate(
R.layout.homelist_listview_layout,
parent,
false
);
}
#Override
public void bindView(View view, Context context, Cursor csr) {
TextView sname = (TextView) view.findViewById(R.id.homelist_name_short);
TextView lname = (TextView) view.findViewById(R.id.homelist_name_long);
TextView date = (TextView) view.findViewById(R.id.homelist_date);
TextView price = (TextView) view.findViewById(R.id.homelist_price);
sname.setText(csr.getString(csr.getColumnIndex("name_short")));
lname.setText(csr.getString(csr.getColumnIndex("name_long")));
date.setText(csr.getString(csr.getColumnIndex("date")));
price.setText(csr.getString(csr.getColumnIndex("price")));
}
}
My DatabaseHelper class looks as follows:
public class DatabaseHelper extends SQLiteOpenHelper{
public static final String DATABASE_NAME = "Main.db";
public static final String TABLE_NAME = "current_table";
public static final String COL_1 = "name_short";
public static final String COL_2 = "name_long";
public static final String COL_3 = "date";
public static final String COL_4 = "price";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + TABLE_NAME + " (name_short TEXT,name_long TEXT, due_date TEXT, price TEXT) ");
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
public Cursor getAllHomesAsCursor() {
SQLiteDatabase db = this.getWritableDatabase();
String[] columns = {"rowid as _id","*"};
return db.query(TABLE_NAME,columns,null,null,null,null,null);
}
public boolean insertData(String name_short, String name_long, String due_date, String price) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL_1,name_short);
contentValues.put(COL_2,name_long);
contentValues.put(COL_3,due_date);
contentValues.put(COL_4,price);
long result = db.insert(TABLE_NAME,null,contentValues);
if(result == -1)
return false;
else
return true;
}
public void deleteAllData() {
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("DELETE FROM " + TABLE_NAME);
}
public Cursor getAllData() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor res = db.rawQuery("SELECT * FROM " + TABLE_NAME ,null);
return res;
}
public Cursor getSpecifiedColumnData(String column) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("SELECT column FROM " + TABLE_NAME,null);
return res;
}
}
I would think that my code should be working fine, but when I run the app. It closes immediately. Can you tell me what the problem is?
I believe the issue is that you need 4 String arrays to be passed to the adapter, so doing it like above you'd need to have a unique equivalent of getAllData for each type.
However considering that a house has a short name, long name, date and price a better approach could to consider all of these properties as an object and thus create a class. You could then create a List not of String objects but as a List of House objects, you'd be able to get them all in one go etc.
So (P.S. for the sake of my sanity I've incorporated the SO4522191 into the following so I can keep some sort of track of the code) :-
1) Create your Home Object to hold all values/properties of a house:-
1-a) Create a file the same as your home name, it's going to be a java class file.
In this case I've called it SO45422191Home, the code could be along the lines of :-
public class SO45422191Home {
private String mShortHomeName;
private String mLongHomeName;
private String mHomeDate;
private String mHomePrice;
public SO45422191Home(String ShortName, String LongName, String Date, String Price) {
this.mShortHomeName = ShortName;
this.mLongHomeName = LongName;
this.mHomeDate = Date;
this.mHomePrice = Price;
}
public String getShortName() {
return this.mShortHomeName;
}
public String getLongName() {
return this.mLongHomeName;
}
public String getDate() {
return this.mHomeDate;
}
public String getPrice() {
return this.mHomePrice;
}
}
Explanation
Using the above we can create a SO45422191Home object, in code elsewhere e.g. in your activity, by using something
like SO45422191Home Myhome = new SO45422191Home("Flower","Red
Rose","20-9-2017","1.50");.
With the MyHome object you can extract the properties e.g.
MyHome.getPrice() would return a String with a value of 1.50.
Similar for the other properties.
You can create an array of objects e.g. SO45422191Home[] homes = new
SO45422191Home[3]; will create an array of 3 (empty) SO45422191Home
objects. We could set the first element of the array using homes[0] =
new SO45422191Home("Bush","Cherry","11-10-2017","2.48");
2) Create a means of getting an array of SO45422191Home objects from the database.
here's some code for this:-
public List<SO45422191Home> getAllHomes() {
List<SO45422191Home> rv = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor csr = db.query(HOMETABLE,null,null,null,null,null,null);
while (csr.moveToNext()) {
SO45422191Home h = new SO45422191Home(
csr.getString(csr.getColumnIndex(SHORTHOMENAME)),
csr.getString(csr.getColumnIndex(LONGHOMENAME)),
csr.getString(csr.getColumnIndex(HOMEDATE)),
csr.getString(csr.getColumnIndex(HOMEPRICE))
);
rv.add(h);
}
csr.close();
return rv;
}
Explanation You used List and added elements to the list, List is similar but for SO45422191Home objects rather
than String objects.
The Database is opened, if not already open, using SQLiteDatabase db
= this.getWritableDatabase();.
All rows are extracted into a cursor.
The cursor is traversed each row at a time.
For each row a SO45422191Home object is created by getting the respective data from the cursor
(Note that csr.getColumnIndex(columnname) is used
rather than hard coding the column's index/offset, doing so can reduce
the chance for errors and also reduce overheads should changes be
applied.).
The the new object is added to the list.
Obviously column names would have to be adjusted, you may also want to add db.close() before the return.
3) Amend your adapter to take and use the the single list of objects rather than the 4 List.
here's an example adapter for use by a List (Note that R.layout.homeentry is the layout used for each entry in the ListView), the layout is below in the section re Cursor Adapter:-
public class AdapterHomeList2 extends ArrayAdapter {
List<SO45422191Home> homes;
LayoutInflater lInflater;
public AdapterHomeList2(Context context, List<SO45422191Home> homes) {
super(context,R.layout.homeentry, homes);
lInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.homes = homes;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.homeentry, parent, false);
}
TextView sname = (TextView) view.findViewById(R.id.shortname);
TextView lname = (TextView) view.findViewById(R.id.longname);
TextView date = (TextView) view.findViewById(R.id.date);
TextView price = (TextView) view.findViewById(R.id.price);
sname.setText(homes.get(position).getShortName());
lname.setText(homes.get(position).getLongName());
date.setText(homes.get(position).getDate());
price.setText(homes.get(position).getPrice());
return view;
}
}
This is the code for an ArrayList :-
public class AdapterHomeList3 extends ArrayAdapter {
ArrayList<SO45422191Home> homes;
LayoutInflater lInflater;
public AdapterHomeList3(Context context, ArrayList<SO45422191Home> homes) {
super(context,R.layout.homeentry, homes);
lInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.homes = homes;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.homeentry, parent, false);
}
TextView sname = (TextView) view.findViewById(R.id.shortname);
TextView lname = (TextView) view.findViewById(R.id.longname);
TextView date = (TextView) view.findViewById(R.id.date);
TextView price = (TextView) view.findViewById(R.id.price);
sname.setText(homes.get(position).getShortName());
lname.setText(homes.get(position).getLongName());
date.setText(homes.get(position).getDate());
price.setText(homes.get(position).getPrice());
return view;
}
}
Using a CursorAdapter
1) Add a new method to extract a cursor with all rows (NOTE! for cursor adapter a row named _id is required)
public Cursor getAllHomesAsCursor() {
SQLiteDatabase db = this.getWritableDatabase();
String[] columns = {"rowid as _id","*"};
return db.query(HOMETABLE,columns,null,null,null,null,null);
}
Note! instead of all columns i.e. coding null as the second parameter
to 'query' (which doesn't get the hidden rowid column (assuming
WITHOUT ROWID hasn't been used)), will will get the rowid (a unqiue
row identifier) and name this AS _id to suite the Cursor Adapter
hence "rowid as _id", the following * as the second element of
the columns array means all rows (specifying null as 2nd parameter
result in SELECT * .....).
Otherwise it's pretty simple. NOTE you must not close the database,
otherwise you can't access the cursor.
2) You will need a layout for each item in the list, as you would for a custom array adapter and it can be the same one i.e. there are no diferences according to which adapter is used. e.g. I created :-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/shortname"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/longname"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/date"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/price"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
</LinearLayout>
3) Create The Cursor Adpater as a class file, very similar to an Array Adapter.
public class AdapterHomeList extends CursorAdapter {
public AdapterHomeList(Context context, Cursor cursor) {
super(context, cursor,0);
}
#Override
public View newView(Context context, Cursor csr, ViewGroup parent) {
return LayoutInflater.from(context).inflate(
R.layout.homeentry, //<< layout for each list item
parent,
false
);
}
#Override
public void bindView(View view, Context context, Cursor csr) {
TextView sname = (TextView) view.findViewById(R.id.shortname);
TextView lname = (TextView) view.findViewById(R.id.longname);
TextView date = (TextView) view.findViewById(R.id.date);
TextView price = (TextView) view.findViewById(R.id.price);
sname.setText(csr.getString(csr.getColumnIndex(SO45422191.SHORTHOMENAME)));
lname.setText(csr.getString(csr.getColumnIndex(SO45422191.LONGHOMENAME)));
date.setText(csr.getString(csr.getColumnIndex(SO45422191.HOMEDATE)));
price.setText(csr.getString(csr.getColumnIndex(SO45422191.HOMEPRICE)));
}
}
Note! R.layout.homeentry being the layout for the list entries
and id's are from this.
4) From the respective activity, get the cursor, get an instance of the adapter and set the ListView to use the adapter.
e.g.:-
Cursor csr = dbhlp.getAllHomesAsCursor();
AdapterHomeList ahl = new AdapterHomeList(this,csr);
ListView hl = (ListView) this.findViewById(R.id.homelist);
hl.setAdapter(ahl);
result :-
Using cursor.getColumnIndex()
getColumnIndex
int getColumnIndex (String columnName)
Returns the zero-based index for the given column name, or -1 if the
column doesn't exist. If you expect the column to exist use
getColumnIndexOrThrow(String) instead, which will make the error more
clear.
SQLiteCursor
Using getColumnIndex as opposed to specifying the index removes the need to manually determine column offsets.
For example purposes, there is a table, named items with 3 columns, named as name, date and price :-
Using a query that uses the equivalent of SELECT * FROM items, the query will return a cursor with 3 columns, name, date and price
column name would have an offset of 0.
column date would have an offset of 1.
column price would have an offset of 2.
To extract the date from the cursor you could code cursor.getString(1);
However, if you were to have a query based upon SELECT date, price, name FROM items then the offsets would be:-
column name would have an offset of 2.
column date would have an offset of 0.
column price would have an offset of 1.
In this case you'd have to code cursor.getString(0); to extract the date.
It could be easy to inadvertently code the wrong offset, especially when using larger tables or when joining tables or when introducing generated columns.
Using cursor.getString(cursor.getColumnIndex("date")); could be used in both situations as it would return 1 in the first case and 0 in the second case.
Above, as an example, sname.setText(csr.getString(csr.getColumnIndex(SO45422191.SHORTHOMENAME))); has been coded.
Home.SHORTHOMENAME is a class varaible defined in the Database Helper (i.e. SO45422191 is the DatabaseHelper Class and SHORTHOMENAME is the class variable) that equates to the column name of the respective column as can be seen from the Database Helper code extract:-
public class SO45422191 extends SQLiteOpenHelper {
public static final String DBNAME = "SO45422191";
public static final String HOMETABLE = "homes";
public static final String SHORTHOMENAME = "shorthomename";
public static final String LONGHOMENAME = "longhomename";
public static final String HOMEDATE = "homedate";
public static final String HOMEPRICE = "homeprice";
// constructor
public SO45422191(Context context) {
super(context, DBNAME , null , 1);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("create table " + HOMETABLE +
"(" +
SHORTHOMENAME + " TEXT, " +
LONGHOMENAME + " TEXT, " +
HOMEDATE + " TEXT, " +
HOMEPRICE + ")");
So, here is the case, in the onPostExecute method I have used a ListView and I have adapted a list adapter in it in order to display the objects (events) in a list view. The problem is that the adapter recognizes the objects but it does not display them in the ListView. I have looked of how to populate an Array of Hashmaps with a List adapter and I am prettu sure that I have done it correctly in my code. I think that the problem might be in the xml file. Any ideas that can guide me to the right direction?
This is my xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
<TextView
android:id="#+id/id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="2dip"
android:paddingTop="6dip"
android:textSize="16sp"/>
<TextView
android:id="#+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="2dip" />
<TextView
android:id="#+id/date"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="start"/>
<TextView
android:id="#+id/time"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="start" />
<TextView
android:id="#+id/time_end"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="start" />
</LinearLayout>
And the .java file:
public class EventsJSONActivity extends ListActivity {
private static String url = "http://mob.students.acg.edu/json3.php";
public static final String TAG_EVENT_INFO = "eventsinfo";
public static final String TAG_ID = "id";
public static final String TAG_TITLE = "title";
public static final String TAG_DATE = "date";
public static final String TAG_TIME = "time";
public static final String TAG_TIME_END = "time_end";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_events_json);
new GetEvents().execute();
}
class GetEvents extends AsyncTask<Void,Void,Void> {
ArrayList<HashMap<String,String>> eventList;
ProgressDialog proDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
proDialog = new ProgressDialog(EventsJSONActivity.this);
Log.d("prodialog: ","Setting Message.");
proDialog.setMessage("Please wait...");
Log.d("prodialog: ","Setting cancellable.");
proDialog.setCancelable(false);
Log.d("prodialog: ","Showing...");
proDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
WebRequest webreq = new WebRequest();
String url = "http://mob.students.acg.edu/json3.php";
String jsonStr = webreq.makeWebServiceCall(url,WebRequest.POSTRequest);
Log.d("Response: ", "> " + jsonStr);
eventList = ParseJSON(jsonStr);
Log.d("eventList info: " , eventList.toString());
return null;
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#Override
protected void onPostExecute(Void requestresult) {
super.onPostExecute(requestresult);
if (proDialog.isShowing()) {
proDialog.dismiss();
Log.d("prodialog: ","dismissing dialog.");
}
Log.d("Listadapter: ", "eventList: " + eventList.toString());
ListAdapter adapter = new SimpleAdapter(
EventsJSONActivity.this,eventList,
android.R.layout.simple_list_item_1,
new String[] {TAG_ID, TAG_TITLE, TAG_DATE, TAG_TIME, TAG_TIME_END},
new int[] {R.id.id,R.id.title,R.id.date,R.id.time,R.id.time_end});
Log.d("Listadapter: ","data fed");
ListView lv = (ListView)findViewById(android.R.id.list);
lv.setAdapter(adapter);
Log.d("Listadapter: ",adapter.getCount() + " items set");
}//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
private ArrayList<HashMap<String,String>> ParseJSON(String json) {
if (json != null) {
try {
ArrayList<HashMap<String,String>> eventList = new ArrayList<>();
JSONObject jsonObj = new JSONObject(json);
JSONArray events = jsonObj.getJSONArray(TAG_EVENT_INFO);
for (int i = 0; i < events.length(); i++) {
JSONObject j = events.getJSONObject(i);
String id = j.getString(TAG_ID);
String title = j.getString(TAG_TITLE);
String date = j.getString(TAG_DATE);
String time = j.getString(TAG_TIME);
String time_end = j.getString(TAG_TIME_END);
HashMap<String,String> event = new HashMap<String,String>();
event.put(TAG_ID,id);
event.put(TAG_TITLE,title);
event.put(TAG_DATE,date);
event.put(TAG_TIME,time);
event.put(TAG_TIME_END,time_end);
/*event.put(TAG_ID,"id");
event.put(TAG_TITLE,"title");
event.put(TAG_DATE,"date");
event.put(TAG_TIME,"time");
event.put(TAG_TIME_END,"time_end");*/
eventList.add(event);
}
Log.d("EventList > ", eventList.toString());
return eventList;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
} else {
Log.e("ServiceHandler", "No data received from HTTP Request");
return null;
}
}
}
}
Try checking the solution that was posted here ... updating ListView from AsyncTask. The runOnUiThread runnable may be what you are missing since the code you have here looks correct. If that doesn't work, you can try creating class levels variables for the listview and/or adapter and modify them in the onPostExecute of AsyncTask.
Hope this helps!
I'm studing android and the excercise I'll do is this one:
You have the Five Continental with relative state/capital.
Create an Activity with two spinner and une button .
When you select Continent from the first spinner the second spinner should display only the state of the relative continent. When you click on the button a dialog box should show:
Continental: Selected Contiental;
State:Selected State;
StateCapital: the capital of the state.
I don't want to use any db (I'm a dummy at the moment) can you help me ?
I think is more simple to use arrays.
I Create my string xml
<string name="Select_continent">Select Continent</string>
<string-array name="continent">
<item>Usa</item>
<item>Europe</item>
<item>Australia</item>
<item>Asia</item>
<item>Africa</item>
</string-array>
<string name="Select_state_usa">Select State</string>
<string-array name="Usa">
<item>Alabama</item>
<item>Ohio</item>
<item>Florida</item>
<item>...</item>
<string name="Select_state_eu">Select State</string>
<string-array name="Europe">
<item>Germany</item>
<item>Italy</item>
<item>England</item>
<item>...</item>
Then I create my main.xml
<Spinner
android:id="#+id/spinner1"
android:layout_width="300dp"
android:layout_height="50dp"
android:entries="#array/continent"
android:prompt="#string/Select_continent"
android:gravity="center"
/>
<TextView
android:id="#+id/TextView01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=" Select continent:"
android:textColor="#000" />
<Spinner
android:id="#+id/spinner2"
android:layout_width="297dp"
android:layout_height="50dp"
/>
And then I create MyActivity.java
public class MyActivity extends Activity {
private Spinner spinner1, spinner2;
private Button btnSubmit;
final Context context = this;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.Myactivity);
addItemsOnSpinner2();
addListenerOnButton();
addListenerOnSpinnerItemSelection();
}
//add items into spinner dynamically
public void addItemsOnSpinner2() {
spinner2 = (Spinner) findViewById(R.id.spinner2);
List<String> list = new ArrayList<String>();
list.add("Austria");
list.add("Italy");
list.add("Germany");
list.add("France");
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>
this,android.R.layout.simple_spinner_item,list);dataAdapter.setDropDownViewResource
android.R.layout.simple_spinner_dropdown_item);spinner2.setAdapter(dataAdapter);
}
public void addListenerOnSpinnerItemSelection(){
spinner1 = (Spinner) findViewById(R.id.spinner1);
}
//get the selected dropdown list value
public void addListenerOnButton() {
spinner1 = (Spinner) findViewById(R.id.spinner1);
spinner2 = (Spinner) findViewById(R.id.spinner2);
btnSubmit = (Button) findViewById(R.id.btnSubmit);
btnSubmit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {AlertDialog.Builder alertDialogBuilder3 = new AlertDialog.Builder
(context);
alertDialogBuilder3
.setTitle("Continent")
.setIcon(R.drawable.info)
.setMessage("Continent " + "\n " + String.valueOf (spinner1.getSelectedItem()) +
"\n " + String.valueOf(spinner2.getSelectedItem()) +
"\nCapital : " )
.setNeutralButton("Ok",null)
.create() // create one
.show();
}
});
}}
Can you help me to add the relative state to the continent?
Initialize both spinners, populate the continent spinner and set OnItemSelected() listener, switch-case on the selected item, populate the second spinner according to the case.
EDITED:
Sure! Please note, however that I am currently on my tablet so I will not be able to test out the code before handing it out to you.
public class MyClass extends Activity
{
ArrayList<String> continents;
ArrayList<String> statesOfContA;
ArrayList<String> statesOfContB;
Spinner conts;
Spinner states;
Button btnShowToast;
String continentValue;
String stateValue;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
btnShowToast = (Button)findViewById(R.id.btnShow);
continents = new ArrayList<String>();
statesOfContA = new ArrayList<String>();
statesOfContB = new ArrayList<String>();
continents.add("Continent A");
continents.add("Continent B");
statesOfContA.add("State A");
statesOfContA.add("State B");
statesOfContB.add("State A");
statesOfContB.add("State B");
conts = (Spinner)findViewById(R.id.spConts);
states = (Spinner)findViewById(R.id.spStates);
ArrayAdapter<String> contAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, continents);
conts.setAdapter(contAdapter);
conts.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View v, int pos,
long arg3)
{
ArrayAdapter<String> stateAdapter;
String choice = parent.getItemAtPosition(pos).toString();
continentValue = continents.getSelectedItem().toString();
switch(choice)
{
case "Continent A":
stateAdapter = new ArrayAdapter<String>(MyClass.this, android.R.layout.simple_spinner_item, statesOfContA);
states.setAdapter(stateAdapter);
break;
case "Continent B":
stateAdapter = new ArrayAdapter<String>(MyClass.this, android.R.layout.simple_spinner_item, statesOfContB);
states.setAdapter(stateAdapter);
break;
}
Toast t = Toast.makeText(getApplicationContext(), "Continent: " + continentValue + " State: " + stateValue, Toast.LENGTH_LONG;
t.show();
}
});
btnShowToast.setOnClickListener(new View.setOnClickListener()
{
#Override
public void onClick(View v)
{
Toast t = Toast.makeText(getApplicationContext(), "Continent: " continentValue + " State: " + stateValue, Toast.LENGTH_LONG;
t.show();
}
}
}
}
Watch out for any spelling mistakes as well! If this doesn't work, kindly let me know so we can find another solution :)
Good luck!
Im just starting to learn how to create and use a database.
Here is the error I get:03-23 01:34:35.861: E/AndroidRuntime(613): Caused by: android.database.sqlite.SQLiteException: near "in": syntax error: , while compiling: create table payouts(_id integer primary key autoincrement, date text not null, casino text not null, game text not null, in text not null, out text not null, gain text not null);
I have gone over it, and I cant seem to figure out why it will not work.
Any help would be much appreciated.
package kris.databasetester;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DBAdapter
{
public static final String KEY_ROWID = "_id";
public static final String KEY_DATE = "date";
public static final String KEY_CASINO = "casino";
public static final String KEY_GAME = "game";
public static final String KEY_IN = "in";
public static final String KEY_OUT = "out";
public static final String KEY_GAIN = "gain";
private static final String TAG = "DBAdapter";
private static final String DATABASE_NAME = "casinodb";
private static final String DATABASE_TABLE = "payouts";
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_CREATE = "create table payouts(_id integer primary key autoincrement, " + "date text not null, casino text not null, " + "game text not null, in text not null, out text not null, gain text not null);";
// private static final String date = null;
private final Context context;
private DatabaseHelper DBHelper;
private SQLiteDatabase db;
public DBAdapter(Context ctx)
{
this.context = ctx;
DBHelper = new DatabaseHelper(context);
} //DBAdapter Closer
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(DATABASE_CREATE);
} //onCreate Closer
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destory all old data");
db.execSQL("DROP TABLE IF EXISTS payouts");
onCreate(db);
} //onUpgrade Closer
} //DatabaseHelper Closer
//Opens the Database
public DBAdapter open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}//DBAdapter Open Closer
//Closes the Database
public void close()
{
DBHelper.close();
} //DBAdapter Close Closer
//Insert a GamePlay into Database
public long insertTitle(String date, String casino, String game, String in, String out, String gain)
{
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_DATE, date);
initialValues.put(KEY_CASINO, casino);
initialValues.put(KEY_GAME, game);
initialValues.put(KEY_IN, in);
initialValues.put(KEY_OUT, out);
initialValues.put(KEY_GAIN, gain);
return db.insert(DATABASE_NAME, null, initialValues);
} //Insert Title Closer
// Deletes a particular title
public boolean deleteTitle(long rowId)
{
return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
} //Delete Title Closer
//Retrieves all titles
public Cursor getAllTitles()
{
return db.query(DATABASE_TABLE, new String[]
{
KEY_ROWID, KEY_DATE, KEY_CASINO, KEY_GAME, KEY_IN, KEY_OUT, KEY_GAIN
},null, null, null, null, null);
} //Gets all titles closer
//Retrieves a particular Title
public Cursor getTitle(long rowId) throws SQLException
{
Cursor mCursor = db.query(true, DATABASE_TABLE, new String[]
{KEY_ROWID, KEY_DATE, KEY_CASINO, KEY_GAME, KEY_IN, KEY_OUT, KEY_GAIN},
KEY_ROWID + "=" + rowId, null, null, null, null, null);
if (mCursor != null)
{
mCursor.moveToFirst();
}
return mCursor;
} //getTitle Closer
//Updates a title
// public boolean updateTitle(long rowId, String KEY_DATE, String KEY_CASINO, String KEY_GAME, String KEY_IN, String KEY_OUT, String KEY_GAIN)
// {
// ContentValues args = new ContentValues();
// args.put(KEY_DATE, date);
// args.put(KEY_CASINO, casino);
// args.put(KEY_GAME, game);
// args.put(KEY_IN, in);
// args.put(KEY_OUT, out);
// args.put(KEY_GAIN, gain);
// return db.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
// } //Update Title Closer
} //Class Closer
-----------------------------
package kris.databasetester;
import android.app.Activity;
import android.os.Bundle;
public class DatabaseTesterActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
#SuppressWarnings("unused")
DBAdapter db = new DBAdapter(this);
//---add 2 titles---
db.open();
// long id;
// id = db.insertTitle("09/08/2012","The Sands","BlackJack", "400", "500", "100");
// db.close();
}
}
-------------------------------
it's telling you that in is not an allowable name for a column, which is because it's reserved for other uses in the SQL language.
i am having this problem with the android database. I adopted the DBAdapter file the NotepadAdv3 example from the google android page.
DBAdapter.java
public class DBAdapter {
private static final String TAG = "DBAdapter";
private static final String DATABASE_NAME = "PasswordDb";
private static final String DATABASE_TABLE = "myuserdata";
private static final String DATABASE_USERKEY = "myuserkey";
private static final int DATABASE_VERSION = 2;
public static final String KEY_USERKEY = "userkey";
public static final String KEY_TITLE = "title";
public static final String KEY_DATA = "data";
public static final String KEY_ROWID = "_id";
private final Context mContext;
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;
private static final String DB_CREATE_KEY =
"create table " + DATABASE_USERKEY
+ " ("
+ "userkey text not null"
+");";
private static final String DB_CREATE_DATA =
"create table " + DATABASE_TABLE
+ " ("
+ "_id integer primary key autoincrement, "
+ "title text not null"
+ "data text"
+");";
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(DB_CREATE_KEY);
db.execSQL(DB_CREATE_DATA);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion,
int newVersion)
{
Log.w(TAG, "Upgrading database from version " + oldVersion
+ " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS myuserkey");
db.execSQL("DROP TABLE IF EXISTS myuserdata");
onCreate(db);
}
}
public DBAdapter(Context ctx)
{
this.mContext = ctx;
}
public DBAdapter Open() throws SQLException{
try {
mDbHelper = new DatabaseHelper(mContext);
}
catch(Exception e){
Log.e(TAG, e.toString());
}
mDb = mDbHelper.getWritableDatabase();
return this;
}
public void close(){
mDbHelper.close();
}
public Long storeKey(String userKey){
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_USERKEY, userKey);
try {
mDb.delete(DATABASE_USERKEY, "1=1", null);
}
catch(Exception e)
{
Log.e(TAG, e.toString());
}
return mDb.insert(DATABASE_USERKEY, null, initialValues);
}
public String retrieveKey() {
final Cursor c;
try {
c = mDb.query(DATABASE_USERKEY, new String[] {
KEY_USERKEY},
null,
null,
null,
null,
null);
}catch(Exception e){
Log.e(TAG, e.toString());
return "";
}
if(c.moveToFirst()){
return c.getString(0);
}
else{
Log.d(TAG, "UserKey Empty");
}
return "";
}
//not including any function related to "myuserdata" table
}
Class1.java
{
mUserKey = mDbHelper.retrieveKey();
mDbHelper.storeKey(Key);
}
the error that i am receiving is from Log.e(TAG, e.toString()) in the methods retrieveKey() and storeKey()
"no such table: myuserkey: , while compiling: SELECT userkey FROM myuserkey"
Did you pop the DB version so onUpgrade fires? You're at version 2 in the example above but if you changed the schema since version 2 then you need to pop the version again.
i think you are not mention your provider tag in AndroidManifest.xml .Check it.
u have to mention the tag like
<provider android:name=".name of providerclass"
android:authorities="authority path" />