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.
Aucun commentaire:
Enregistrer un commentaire