I'm new to StackOverflow so I'm not sure how this works, but I really need some help with this app I'm building in Android Studio. I have a pre-populated chemicals.sqlite database that I am trying to search through in Android Studio. Basically, the app I'm designing is going to allow a user to search for a compound by name and it will display information about it. For some reason, my program is saying that it can't display any of the values that I'm trying to search in the app's emulator. It just always shows the "No Match Found".
Here is my DatabaseHelper class:
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "chemicals.sqlite";
private static final String TABLE_OSHA = "osha";
public static final String COLUMN_COMPOUND = "compound";
public static final String COLUMN_H = "h";
public static final String COLUMN_F = "f";
public static final String COLUMN_R = "r";
public static final String COLUMN_SN = "sn";
public DataBaseHelper(Context context, String name,
SQLiteDatabase.CursorFactory factory, int version) {
super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_OSHA_TABLE = "CREATE TABLE " +
TABLE_OSHA + "("
+ COLUMN_COMPOUND + " TEXT," + COLUMN_H
+ " TEXT," + COLUMN_F + " TEXT," + COLUMN_R + " TEXT," + COLUMN_SN + " TEXT" + ")";
db.execSQL(CREATE_OSHA_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion,
int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_OSHA);
onCreate(db);
}
public Compound findCompound(String compoundname) {
String query = "Select * FROM " + TABLE_OSHA + " WHERE " + COLUMN_COMPOUND + "= '" + compoundname + "'";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
Compound compound = new Compound();
if (cursor.moveToFirst()) {
cursor.moveToFirst();
compound.setH(cursor.getString(0));
compound.setF(cursor.getString(1));
compound.setR(cursor.getString(2));
compound.setSN(cursor.getString(3));
// cursor.moveToNext();
cursor.close();
} else {
compound = null;
}
db.close();
return compound;
}
}
Here is my compound class:
public class Compound {
private String _compound;
private String _h;
private String _f;
private String _r;
private String _sn;
public Compound() {
}
public Compound(String compound, String h, String f, String r, String sn) {
this._compound = compound;
this._h = h;
this._f = f;
this._r = r;
this._sn = sn;
}
public Compound(String h, String f, String r, String sn) {
this._h = h;
this._f = f;
this._r = r;
this._sn = sn;
}
public void setCompound(String compound) {
this._compound = compound;
}
public String getCompound() {
return this._compound;
}
public void setH(String h) {
this._h = h;
}
public String getH() {
return this._h;
}
public void setF(String f) {
this._f = f;
}
public String getF() {
return this._f;
}
public void setR(String r) {
this._r = r;
}
public String getR(){
return this._r;
}
public void setSN(String sn){
this._sn = sn;
}
public String getSN(){
return this._sn;
}
}
And here is my main class:
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class oshaSearch extends AppCompatActivity {
TextView txtH;
TextView txtR;
TextView txtF;
TextView txtSN;
EditText txtCompound;
Button btnSearch;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_osha_search);
txtF = (TextView) findViewById(R.id.txtF);
txtR = (TextView) findViewById(R.id.txtR);
txtH = (TextView) findViewById(R.id.txtH);
txtSN = (TextView) findViewById(R.id.txtSN);
txtCompound = (EditText) findViewById(R.id.searchCompound);
btnSearch = (Button) findViewById(R.id.btnSearch);
}
public void lookupCompound (View view) {
DataBaseHelper dbHandler = new DataBaseHelper(this, null, null, 1);
Compound compound =
dbHandler.findCompound(txtCompound.getText().toString());
if (compound != null) {
txtH.setText(String.valueOf(compound.getH()));
txtF.setText(String.valueOf(compound.getF()));
txtR.setText(String.valueOf(compound.getR()));
txtSN.setText(String.valueOf(compound.getSN()));
} else {
txtH.setText("No Match Found");
}
}
}
Any and all help is greatly appreciated. Please help me out.
Additional information: The database is in the assets folder, All values in the database are text fields, The user is searching by compound name, The database has a .sqlite extension. Thank you all in advanced.
You have to copy your database which you said is in the assets folder to newly created database -
private void copyDataBase(String dbname) throws IOException {
// Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(dbname);
// Path to the just created empty db
String outFileName = getDatabasePath(dbname);
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
you first need to check if database is properly created or not, for that
public DataBaseHelper(Context context) {
super(context, Environment.getExternalStorageDirectory()+"/"+DATABASE_NAME, null, 1);
}
use this constructor , this will save your app database in external storage of your phone.
before that give permission to external storage in manifest file.
and use sqliteManager application from google play store to check database structure.
Or you can use stetho to debug database of android.
reference link:http://code.tutsplus.com/tutorials/debugging-android-apps-with-facebooks-stetho--cms-24205
Related
At first the app would just crash when I started it with an emulator, Not sure what I changed to get it to run but now it will run the onCreate method however, when I implement the addButtonClicked method the app just stalls and the Android Monitor displays "Suspending all threads" every few seconds and I'm not sure where to even begin debugging. Any pointers in the right direction would be greatly appreciated as I'm fairly new to Android development.
MainActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
EditText testInput;
TextView testText;
MyDBHandler dbHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testInput = (EditText) findViewById(R.id.testInput);
testText = (TextView) findViewById(R.id.testText);
dbHandler = new MyDBHandler(this, null, null, 1);
printDatabase();
}
//Add product to database
public void addButtonClicked(View view){
Products product = new Products((testInput.getText().toString()));
dbHandler.addProduct(product);
printDatabase();
}
// Delete Items
public void deleteButtonClicked(View view){
String inputText = testText.getText().toString();
dbHandler.deleteProduct(inputText);
printDatabase();
}
public void printDatabase(){
String dbString = dbHandler.databaseToString();
testText.setText(dbString);
testInput.setText("");
}
}
Products.java
public class Products {
private int _id;
private String _productname;
public Products(){
}
public Products(String productname) {
this._productname = productname;
}
public void set_id(int _id) {
this._id = _id;
}
public void set_productname(String _productname) {
this._productname = _productname;
}
public int get_id() {
return _id;
}
public String get_productname() {
return _productname;
}
}
MyDBHandler.java
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.Cursor;
import android.content.Context;
import android.content.ContentValues;
public class MyDBHandler extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 15;
private static final String DATABASE_NAME = "products.db";
public static final String TABLE_PRODUCTS = "products";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_PRODUCTNAME = "productname";
public MyDBHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String query = "CREATE TABLE " + TABLE_PRODUCTS +"(" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT ," +
COLUMN_PRODUCTNAME +" TEXT " +
");";
db.execSQL(query);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_PRODUCTS);
onCreate(db);
}
//Add new row to the database
public void addProduct(Products product){
ContentValues values = new ContentValues();
values.put(COLUMN_PRODUCTNAME, product.get_productname());
SQLiteDatabase db = getWritableDatabase();
db.insert(TABLE_PRODUCTS, null, values);
db.close();
}
//Delete product from database
public void deleteProduct(String productName){
SQLiteDatabase db = getWritableDatabase();
db.execSQL("DELETE FROM " + TABLE_PRODUCTS + " WHERE " + COLUMN_PRODUCTNAME + "=\"" + productName + "\";" );
}
//Print of DB as sting
public String databaseToString(){
String dbString = "";
SQLiteDatabase db = getWritableDatabase();
String query = "SELECT * FROM " + TABLE_PRODUCTS + " WHERE 1";
//Cursor point to a location in your results
Cursor c = db.rawQuery(query, null);
//Move to the first row in your results
c.moveToFirst();
while (!c.isAfterLast()){
if(c.getString(c.getColumnIndex("productname"))!= null){
dbString += c.getString(c.getColumnIndex("productname"));
dbString += "\n";
}
}
db.close();
return dbString;
}
}
for your databaseToString method you are performing a retrieve operation. You should be doing a read operation in a thread other than UI thread. Try fetching in AsyncTask. It should work. Implementation for your databaseToString should be handled by AsyncTask.
Happy Coding..
I'm hoping my question isn't too broad. What I would really like to know is how to tell exactly where my code is hitting a wall.
I'm not getting errors from my debugger, the app just crashes when the emulator starts an activity that uses a sqlite database (3rd activity in). I am positive it is the addition of sqlite into my code that causes the crash because it ran before I added it.
This code simply needs to access and read from an external database that I created and pasted into the assets folder. I reviewed the sqlite database in firefox's SQLite Manager; the information seems to be formatted correctly.
I created an assets folder within app/src/Main to facilitate the addition of the external database "ex3.db". Then I copied and pasted the database file there.
So here is the code. LetterImage is a class that holds strings retrieved from the sqlite database. MyDBHandler creates an empty database, copies the old one into it, and fills LetterImage with the values returned from a query based on a string. LoadSubjectActivity calls them both to search the database and return a string.
LetterImage:
public class LetterImage {
private Integer _ID;
private String _letter;
private String _bigfilename;
private String _littlefilename;
//Constructor(s)
public LetterImage(){
}
public LetterImage(Integer ID, String letter, String bigfilename, String littlefilename){
this._ID = ID;
this._letter = letter;
this._bigfilename = bigfilename;
this._littlefilename = littlefilename;
}
public LetterImage(String letter){
this._letter = letter;
}
//End Constructors
//Begin setters and getters
//ID is primary key
public void setID(Integer ID){
this._ID = ID;
}
public Integer getID(){
return this._ID;
}
//letter is main identifier used to search database
// passed to LoadSubjectActivity
// from ChooseSubjectABCActivity as extra from intent
public void setLetter(String letter){
this._letter = letter;
}
public String getLetter(){
return this._letter;
}
//Capital letter image file name
public void setBigFileName(String bigfilename){
this._bigfilename = bigfilename;
}
public String getBigFileName(){
return this._bigfilename;
}
//Lowercase Letter image file name
public void setLittleFileName(String littlefilename){
this._littlefilename = littlefilename;
}
public String getLittleFileName(){
return this._littlefilename;
}
}
Now, here is MyDBHandler:
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.content.Context;
import android.database.Cursor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
public class MyDBHandler extends SQLiteOpenHelper{
private final Context myContext;
private static Context context;
private static final int DATABASE_VERSION = 1;
private static String DB_PATH = "data/data" + context.getPackageName() + "/databases/";
private static final String DATABASE_NAME = "ex3.db";
public static final String TABLE_IMAGES = "tbl1";
private SQLiteDatabase myDataBase;
//Fields in Database
public static final String COLUMN_ID = "_id";
public static final String COLUMN_BIGIMAGEFILE = "bigImage";
public static final String COLUMN_LITTLEIMAGEFILE = "littleImage";
public static final String COLUMN_LETTER = "letter";
//Constructor
public MyDBHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.myContext = context;
}
//if there is no existing database, create an empty one
public void createDatabase() throws IOException{
boolean dbExist = checkDataBase();
if(dbExist) {
//do nothing
}else {
//call this method and create an empty database
this.getReadableDatabase();
try {
copyDataBase();
} catch(IOException e){
throw new Error("Error copying database");
}
}
}
//check to see if there is an existing database
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DATABASE_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e){
throw new Error("Unable to open database");
}
if(checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
//fills new empty database with existing database ex3
private void copyDataBase() throws IOException{
InputStream myInput = myContext.getAssets().open(DATABASE_NAME);
String outFileName = DB_PATH + DATABASE_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
//opens the new database
public void openDatabase() throws SQLException {
String myPath = DB_PATH + DATABASE_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
#Override
public synchronized void close(){
if(myDataBase != null)
myDataBase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase db){
}
#Override
public void onUpgrade(SQLiteDatabase db, int OldVersion, int newVersion){
}
//creates an instance of letter LetterImage
//queries the new database by searching for the row with where the value of COLUMN_LETTER = letter
//fills LetterImage with the values from that row
public LetterImage findLetter(String letter) {
String query = "Select * FROM " + TABLE_IMAGES + " WHERE " + COLUMN_LETTER + " = \"" + letter + "\"";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
LetterImage LetterImage = new LetterImage();
if (cursor.moveToFirst()) {
cursor.moveToFirst();
LetterImage.setID(Integer.parseInt(cursor.getString(0)));
LetterImage.setBigFileName(cursor.getString(1));
LetterImage.setLittleFileName(cursor.getString(2));
LetterImage.setLetter(cursor.getString(3));
cursor.close();
} else {
LetterImage = null;
}
db.close();
return LetterImage;
}
}
Finally, here are the pertinent parts of the LoadSubjectActivity class:
public class LoadSubjectActivity extends MainActivity{
private DrawingView drawView;
private ImageButton currPaint;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_load_subject);
//receives string letter, from last activity
//letter will be used to search array and return files names of the images to be used
Intent intent = getIntent();
String letter = intent.getExtras().getString("letter");
//displayFN calls testDB(letter) to test the database
//It should simply display the string returned by testDB()
TextView displayFN = (TextView)findViewById(R.id.display_filenames);
displayFN.setText(testDB(letter.toLowerCase()));
//Eventually, button images will be filled dynamically
ImageButton bigLetter = (ImageButton)findViewById(R.id.big_letter);
ImageButton littleLetter = (ImageButton)findViewById(R.id.little_letter);
bigLetter.setImageResource(R.drawable.biga);
littleLetter.setImageResource(R.drawable.littlea);
drawView = (DrawingView)findViewById(R.id.drawing);
LinearLayout paintLayout = (LinearLayout)findViewById(R.id.paint_colors);
currPaint = (ImageButton)paintLayout.getChildAt(0);
currPaint.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.paint_pressed));
}
//Function to test the database takes a string as an argument to search the database
public String testDB(String letter){
//create a new instance of dbHandler
MyDBHandler dbHandler = new MyDBHandler(this);
//try to either create an empty database or open the existing one
try{
dbHandler.createDatabase();
} catch (IOException ioe){
throw new Error("Unable to create database");
}
try{
dbHandler.openDatabase();
} catch(SQLException sqle){
sqle.printStackTrace();
throw new Error ("unable to open database");
}
LetterImage letterImage = dbHandler.findLetter(letter);
String blFileName = letterImage.getBigFileName();
//return the big letter image file name;
return blFileName;
}
Anyway, I apologize in advance for any obvious problems. I have traced the logic to the best of my ability...I am teaching myself java and sql...this is my first android project. Any and all insight is greatly appreciated.
I figured out one way to fix this:
1.) rewrite checkDatabase(). I referenced this tutorial: How to use an existing database with an Android application, and found this:
private boolean checkDataBase(){
File dbFile = new File(DB_PATH + DATABASE_NAME);
//Log.v("dbFile", dbFile + " "+ dbFile.exists());
return dbFile.exists();
}
2.) Hard code DB_PATH name, since context.getFilesDir and getDatabasePath() weren't returning the paths I needed.
***going through logcat and tracing the errors back to the exact place the problem started was how I found what I needed to change. In this instance, checkDatabase() wasn't returning false to createDatabase(), so the code was trying to open a database that didn't exist.
Below is my database that I have already created and it works fine, it can save the data to the database,I am really new to this android project and need guidance on how to display all data that was saved inside the listview.
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;
public class BmiDatabase {
private data helper;
private SQLiteDatabase help;
private Context context;
public BmiDatabase(Context context){
helper = new data(context);
help = helper.getWritableDatabase();
this.context=context;
}
public long insertData(String bmi, String status, String weight){
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(data.NAME, bmi);
contentValues.put(data._STATUS, status);
contentValues.put(data.WEIGHT, weight);
long id = db.insert(data.DATABASE_TABLE, null, contentValues);
db.close();
return id;
}
public String getAllData(){
SQLiteDatabase db = helper.getWritableDatabase();
String[] columns = {data.UID, data.NAME, data._STATUS, data.WEIGHT};
Cursor cursor = db.query(data.DATABASE_TABLE, columns, null, null, null, null, null);
StringBuffer buffer = new StringBuffer();
while (cursor.moveToNext())
{
// int index1 = cursor.getColumnIndex(data.UID);
// int cid = cursor.getInt(index1);
int cid = cursor.getInt(0);
String bmi = cursor.getString(1);
String status = cursor.getString(2);
String weight = cursor.getString(3);
buffer.append(cid +" "+bmi+" kg "+status+" "+weight+ "\n");
}
return buffer.toString();
}
public static class data extends SQLiteOpenHelper{
private Context context;
private static final String DATABASE_NAME = "bmidatabase";
private static final String DATABASE_TABLE = "bmitable";
private static final int DB_VERSION = 7;
public static final String UID = "_id";
public static final String NAME = "Bmi";
public static final String _STATUS = "Status";
public static final String WEIGHT = "Weight";
private static final String DROP_TABLE= "DROP TABLE IF EXISTS "+DATABASE_TABLE;
private static final String CREATE_TABLE = "CREATE TABLE "+DATABASE_TABLE+" ("+UID+" INTEGER PRIMARY KEY AUTOINCREMENT ," +
" "+NAME+" VARCHAR(255)," +
" "+_STATUS+" VARCHAR(255)," +
""+WEIGHT+" VARCHAR(255));";
public data(Context context){
super(context, DATABASE_NAME, null, DB_VERSION);
this.context=context;
}
public void getAllData(){
}
#Override
public void onCreate(SQLiteDatabase db) {
try{
db.execSQL(CREATE_TABLE);
Message.message(context,"Database Created");
}
catch (SQLException e){
Message.message(context, "Failed" +e);
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
try{
Message.message(context, "DATABASE DELETED");
db.execSQL(DROP_TABLE);
onCreate(db);
}
catch(SQLException e){
Message.message(context, "SQL FAILED");
}
}
}
}
Below is the code for my mainactivity, it shows that I can display it using a toast, but I have no idea how to call the method to populate the list view with those data.
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
//private static DataHelper DataHelper;
//DataHelper helper = new DataHelper(this);
private static BmiDatabase data;
private EditText weightinputid;
private EditText heightinputid;
private Button buttonBMI, save, detail;
private TextView BMIStatus;
private TextView BMIfinal;
private double weight =0.0;
private double height =0.0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// setupDB();
// setDB();
initializeApp();
}
private void initializeApp(){
weightinputid = (EditText) findViewById(R.id.weightid);
heightinputid = (EditText) findViewById(R.id.heightid);
buttonBMI = (Button) findViewById(R.id.buttonBMI);
BMIfinal= (TextView) findViewById(R.id.BMIfinal);
BMIStatus = (TextView) findViewById(R.id.BMIstatus);
save = (Button) findViewById(R.id.button);
detail = (Button)findViewById(R.id.button1);
data = new BmiDatabase(this);
}
public void calculateBMI (View v){
String status;
weight= Double.parseDouble(weightinputid.getText().toString());
height= Double.parseDouble(heightinputid.getText().toString());
double bmi = weight/(height/100*height/100);
String result = String.format("%.2f", bmi);
Log.d("MainActivity", result);
BMIfinal.setText(result, TextView.BufferType.NORMAL);
if(bmi < 16){
status = "Seriously Underweight";
}
else if(bmi >=16.0 && bmi < 18.0){
status = "Underweight";
}
else if(bmi >=18.0 && bmi <24.0){
status = "Normal";
}
else{
status = "Obese";
}
BMIStatus.setText(status);
}
public void save(View v){
String bmi = BMIfinal.getText().toString();
String status = BMIStatus.getText().toString();
String weight = weightinputid.getText().toString();
long id = data.insertData(weight, bmi, status);
if(id<0)
{
Message.message(this, "");
}
else
{
Message.message(this, "");
}
}
public void detail(View v){
String d = data.getAllData();
Message.message(this, d);
}
}
I am trying to update current credits column of the only row in the database using a drop down spinner which gets values from an arraylist. Very unsure about how to go about doing this operation. Thank you for any help in advance.
My database code:
package com.example.parkangel;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class UDbHelper extends SQLiteOpenHelper
{
public static final String KEY_ROWID = "_id";
public static final String KEY_PFNAME = "payeeFname";
public static final String KEY_PSNAME = "payeeSname";
public static final String KEY_CARD = "card";
public static final String KEY_CREDITS = "credits";
private static final String DATABASE_NAME = "UserData.db";
private static final String DATABASE_TABLE = "UserTable";
private static final int DATABASE_VERSION = 1;
//private UDbHelper dbHelper;
//private final Context ourContext;
private static UDbHelper instance;
private SQLiteDatabase ourDatabase;
public UDbHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public static UDbHelper getInstance(Context context)
{
if (instance == null)
{
instance = new UDbHelper(context);
}
return instance;
}
#Override
public void onCreate(SQLiteDatabase db)
{
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" +
KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
KEY_PFNAME + " TEXT NOT NULL, " + KEY_PSNAME + "
TEXT NOT NULL, " +
KEY_CARD + " TEXT NOT NULL, " + KEY_CREDITS + " TEXT
NOT NULL);");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
onCreate(db);
}
public synchronized UDbHelper open() throws SQLException
{
System.out.println ("running open");
if(ourDatabase == null || !ourDatabase.isOpen())
ourDatabase = getWritableDatabase();
return this;
}
public String getData()
{
// TODO Auto-generated method stub
String[] columns = new String[] {KEY_ROWID, KEY_PFNAME, KEY_PSNAME,
KEY_CARD, KEY_CREDITS};
Cursor c = ourDatabase.query(DATABASE_TABLE, columns, null, null,
null, null, null);
String result = " ";
int iRow = c.getColumnIndexOrThrow(KEY_ROWID);
int iPFname = c.getColumnIndexOrThrow(KEY_PFNAME);
int iPSname = c.getColumnIndexOrThrow(KEY_PSNAME);
int iCard = c.getColumnIndexOrThrow(KEY_CARD);
int iCredits = c.getColumnIndexOrThrow(KEY_CREDITS);
for(c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){
result = result + c.getString(iRow) + " " +
c.getString(iPFname) + " " +
c.getString(iPSname)
+ " " + c.getString(iCard) + " " +
c.getString(iCredits) + "\n";
}
return result;
}
}
My main activity code I will be doing the operation through:
package com.example.parkangel;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
public class Balance extends Activity{
Button add;
TextView display;
Spinner spinner3;
String[] money = {"Select amount", "£1", "£2", "£5", "£10"};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.balance_layout);
TextView tv = (TextView) findViewById(R.id.firstn);
UDbHelper db = new UDbHelper(this);
db.open();
String data = db.getData();
db.close();
tv.setText(data);
ArrayAdapter<String> adapter3 = new ArrayAdapter<String>(Balance.this,
android.R.layout.simple_spinner_item, money);
spinner3 = (Spinner) findViewById (R.id.moneytoadd);
spinner3.setAdapter(adapter3);
add = (Button) findViewById(R.id.topup);
}
public void onClick(View arg0)
{
}
public void updateActivity(View view){
Intent book = new Intent(Balance.this, BookTicket.class);
startActivity(book);
}
public void addBalance(View view){
Intent addB = new Intent(Balance.this, Balance.class);
startActivity(addB);
}
public void doUpdate(View view){
Intent upd = new Intent(Balance.this, UpdateTicket.class);
startActivity(upd);
}
}
Your question is fairly compound, getting selected field from spinner, updating database... I'm not going to provide a complete answer, but this should get you started:
This is how you would get the selected field from the spinner, which you can then use to update your database. One word of warning, I believe setOnItemSelectedListener is called when it is initially set, so you may need to ignore the first call.
Spinner spinner;
spinner.setOnItemSelectedListener( new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View view, int arg2,
long arg3) {
if(! (view instanceof TextView)){
// view is probably a textview, but record type if not.
System.out.println("incorrect view type " + view.getClass().getSimpleName());
return;
}
EditText et = (EditText) view;
String fieldName = et.getText().toString().trim();
//Now we got selected name, send name
//to a function that updates our database.
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
I didn't find the problem but I can tell you that your code is VERY INEFFICIENT. You are using String to build your result in the getData method. Each time you try to append the new data (Row) to the old one you are creating a new string to hold the new data. If you are retrieving 1000 row from the database, this means that you are creating 1000 string to build the final one. I recommend using StringBuilder instead as following:
StringBuilder strBuilder= new StringBuilder();
for(c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){
strBuilder.append( c.getString(iRow) + " " +
c.getString(iPFname) + " " +
c.getString(iPSname)
+ " " + c.getString(iCard) + " " +
c.getString(iCredits) + "\n");
}
return str= strBuilder.toString();
Here is an example of how to insert into your DB:
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_PFNAME , editText1.getText().toString());
values.put(KEY_PSNAME , stringArrayList.get(position));
values.put(KEY_CARD , "12345677");
values.put(KEY_CREDITS , "55");
// Inserting Row
db.insert(DATABASE_TABLE, null, values);
db.close(); // Closing database connection
I'm entirely new to Android Java, especially database linkage. So far I've got this, which all seems to work, I just now need to get the database values from the database to an array.
package com.example.sleepertrain5;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseHelper extends SQLiteOpenHelper{
private static String DB_PATH = "/sleepertrain5/assets";
private static String DB_NAME="info2.sqlite";
private SQLiteDatabase myDatabase;
private final Context myContext;
public DataBaseHelper(Context context){
super(context, DB_NAME, null, 1);
this.myContext=context;
}
public void createDataBase() throws IOException{
boolean dbExist = checkDataBase();
if(dbExist){
//nothing needs done
}else{
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e){
throw new Error("Error copying database");
}
}
}
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
//no databases they don't exist
}
if (checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
private void copyDataBase() throws IOException{
InputStream myInput = myContext.getAssets().open(DB_NAME);
String outFileName = DB_PATH +DB_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length=myInput.read(buffer))>0){
myOutput.write(buffer,0,length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException{
//Open database
String myPath = DB_PATH + DB_NAME;
myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
public synchronized void close(){
if(myDatabase != null)
myDatabase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
How would I go about reading from this into an array? I'm struggling to make sense of this at the moment, so any help would be fantastic.
EDIT: The plan is to read the data, which is coordinates and names, into the array, which I can then use later to draw markers onto a GoogleMap. GoogleMap is all set up and I think I know what I'm doing from there, but this is the part I fall down on. The array would have to be multidimensional.
Ok, so the easiest way to work with SQLite in my opinion is using this three-class approach. I've read through a few tutorials and neither really did the trick for me....
So, here we go.
Table definition
package com.test.sqlite;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
public class ContactTable
{
//key identifiers / column names
public static final String KEY_ROWID = "_id";
public static final String KEY_NAME = "name";
public static final String KEY_URI = "uri";
public static final String TABLE_NAME = "contacts";
//useful stuff
public static final String[] TABLE_COLUMNS = { KEY_ROWID, KEY_NAME, KEY_URI }; //public makes it more useful
private static final String[] TABLE_COLTYPES = { "integer primary key autoincrement", "text not null", "text not null" };
// Database creation SQL statement in lazy-pretty version
private static final String TABLE_CREATE = "create table " + TABLE_NAME + "("
+ TABLE_COLUMNS[0] + " " + TABLE_COLTYPES[0] + ","
+ TABLE_COLUMNS[1] + " " + TABLE_COLTYPES[1] + ","
+ TABLE_COLUMNS[2] + " " + TABLE_COLTYPES[2] + ");";
private static final String LOGTAG = "ContactTable";
public static void onCreate(SQLiteDatabase database)
{
database.execSQL(TABLE_CREATE);
}
public static void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion)
{
Log.w(LOGTAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data");
database.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(database);
}
public static void scratch(SQLiteDatabase database)
{
database.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
database.execSQL(TABLE_CREATE);
}
}
Now that we have set that up, we need Database Helper class, to ease the use of it.
The helper class
package com.test.sqlite;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
public class ContactDBHelper extends SQLiteOpenHelper
{
// 'main' package name
private static final String PACKAGE_NAME = "com.test.demo";
private static final String DATABASE_PATH = "/data/data/" + PACKAGE_NAME + "/databases/";
private static final String DATABASE_NAME = "contactdata";
private static final int DATABASE_VERSION = 1;
private Context myContext;
public ContactDBHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
myContext = context;
}
// Method is called during creation of the database
#Override
public void onCreate(SQLiteDatabase database)
{
ContactTable.onCreate(database);
}
// Method is called during an upgrade of the database,
// e.g. if you increase the database version
#Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion)
{
ContactTable.onUpgrade(database, oldVersion, newVersion);
}
public void scratch(SQLiteDatabase database)
{
ContactTable.scratch(database);
}
/**
* Creates a empty database on the system and rewrites it with your own
* database.
* */
public void createDataBase() throws IOException
{
boolean dbExist = checkDataBase();
if (dbExist)
{
// do nothing - database already exist
} else
{
// By calling this method and empty database will be created into
// the default system path
// of your application so we are gonna be able to overwrite that
// database with our database.
File dirFile = new File(DATABASE_PATH);
if (!dirFile.exists())
{
dirFile.mkdir();
}
this.getReadableDatabase();
try
{
copyDataBase();
} catch (IOException e)
{
throw new Error("Error copying database");
}
}
}
/**
* Check if the database already exist to avoid re-copying the file each
* time you open the application.
*
* #return true if it exists, false if it doesn't
*/
private boolean checkDataBase()
{
SQLiteDatabase checkDB = null;
try
{
String myPath = DATABASE_PATH + DATABASE_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e)
{
// database does't exist yet.
}
if (checkDB != null) checkDB.close();
return checkDB != null ? true : false;
}
/**
* Copies your database from your local assets-folder to the just created
* empty database in the system folder, from where it can be accessed and
* handled. This is done by transfering bytestream.
* */
private void copyDataBase() throws IOException
{
// Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DATABASE_NAME);
// Path to the just created empty db
String outFileName = DATABASE_PATH + DATABASE_NAME;
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0)
{
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
/*
public void openDataBase() throws SQLException
{
// Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
*/
}
And finally, the adapter, which totally does what you want.
DatabaseAdapter
package com.test.sqlite;
import java.util.ArrayList;
import com.test.demo.Contact;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import static com.test.sqlite.ContactTable.*; //contains database fields
public class ContactDBAdapter
{
private Context context;
private SQLiteDatabase db;
private ContactDBHelper dbHelper;
public ContactDBAdapter(Context context)
{
this.context = context;
}
public synchronized ContactDBAdapter open() throws SQLException
{
dbHelper = new ContactDBHelper(context);
db = dbHelper.getWritableDatabase();
return this;
}
public synchronized void close()
{
dbHelper.close();
}
/**
* Create a new Contact entry. If the entry is successfully created return the new
* rowId for that note, otherwise return a -1 to indicate failure.
*/
public long createRow(Contact contact)
{
ContentValues values = createContentValue(contact);
return db.insert(TABLE_NAME, null, values);
}
/**
* Update a row / entry
*/
public boolean updateRow(long rowIndex, Contact contact)
{
ContentValues values = createContentValue(contact);
return db.update(TABLE_NAME, values, KEY_ROWID + "=" + rowIndex, null) > 0;
}
/**
* Deletes a row
*/
public boolean deleteRow(long rowIndex)
{
return db.delete(TABLE_NAME, KEY_ROWID + "=" + rowIndex, null) > 0;
}
public void deleteAllRows()
{
for(int i = 0; i < fetchAllEntries().getCount(); i++)
deleteRow(i);
}
/**
* Return a Cursor over the list of all Contacts in the database
*
* #return Cursor over all contacts
*/
public Cursor fetchAllEntries()
{
return db.query(TABLE_NAME, TABLE_COLUMNS, null, null, null, null, null);
}
/**
* Return a Cursor positioned at the defined Contact
*/
public Cursor fetchEntry(long rowIndex) throws SQLException
{
Cursor mCursor = db.query(true, TABLE_NAME, TABLE_COLUMNS, KEY_ROWID + "=" + rowIndex, null, null, null, null, null);
if (mCursor != null)
{
mCursor.moveToFirst();
}
return mCursor;
}
/**
* Fetch all entries and rebuild them as Contact objects in an ArrayList.
* If no results are found, an empty list is returned.
*
* #return ArrayList of Contacts
*/
public ArrayList<Contact> fetchAllContacts()
{
ArrayList<Contact> res = new ArrayList<Contact>();
Cursor resultSet = fetchAllEntries();
if (resultSet.moveToFirst() != false)
for(int i = 0; i < resultSet.getCount(); i++)
{
String name = resultSet.getString(resultSet.getColumnIndex(KEY_NAME));
String URI = resultSet.getString(resultSet.getColumnIndex(KEY_URI));
Contact c = new Contact(name, URI);
res.add(c);
if(resultSet.moveToNext() == false)
break;
}
resultSet.close();
return res;
}
public synchronized void reflectWith(ArrayList<Contact> contacts)
{
// deleteAllRows();
dbHelper.scratch(db);
contacts.trimToSize();
//empty contact
Contact empty = new Contact();
empty.empty();
for(Contact c : contacts)
{
if(!c.getName().equals(empty.getName()))
createRow(c); //if not empty, add it
}
}
private ContentValues createContentValue(Contact contact)
{
ContentValues values = new ContentValues();
values.put(KEY_NAME, contact.getName());
values.put(KEY_URI, contact.getURI());
return values;
}
}
this is how it's used:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
dbAdapter = new ContactDBAdapter(getApplicationContext());
dbAdapter.open();
setContentView(R.layout.main);
// list stuff
contacts = new ArrayList<Contact>();
contacts = dbAdapter.fetchAllContacts();
//empty placeholders
if (contacts.size() < 5) for (int i = 0; i < 5 - contacts.size(); i++)
{
Contact c = new Contact();
c.empty();
contacts.add(c);
}
// contacts.addAll(dbAdapter.fetchAllContacts());
...
}
If you have questions, do ask.
Android uses SQLite database and SQLite query syntax for database accessing.
For querying the database directly through the SQLiteDatabase db variable you can do:
String table = CONTACT_TABLE;
String columns = {CONTACT_COLUMN_NAME};
String selection = CONTACT_COLUMN_NAME + "=" + MY_NAME;
String[] selectionArgs = {"wangyif2"};
Cursor c = db.query(table, columns, selection, selectionArgs, null, null, null, null);
This will return you a Cursor object, which you can understand as an iterator that contains all the result matching your query. You can then step through the cursor like you would with any array that is converted to an iterator.
c.moveToFirst();
while (!c.isAfterLast())
{
arr[i] = cur.getString(0);
i++;
c.moveToNext();
}