As you are having difficulties the following is a hastily put together tutorial along with code.
Create the database and tables in an SQLite tool, adding data as required and then Save it.
Close the database and re-open it to check that the tables and data are as expected. If not make changes and then repeat 2 until you are sure that the saved database matches.
Obtain the filename of the saved database and record it including the file extension.
If you haven't yet created a Project for the App then do so and save the project.
Outside of the IDE navigate to the projects app/src/main folder and create a folder named assets if it doesn't already exist.
Copy the database file into the assets folder.
Open the Project in Android Studio.
Create a new Java Class named DatabaseHelper with SuperClass as SQLiteOpenHelper (will resolve to android.database.sqlite.SQLiteOpenHelper
) and tick the Show Select Overrides Dialog checkbox. The click OK.
It should look like :-
public class DatabaseHelper extends SQLiteOpenHelper {
public Databasehelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
Add a line, as a class variable, after public class DatabaseHelper extends SQLiteOpenHelper {
that is like :-
public static final String DBNAME = "my_dic.db";
- Noting that it is important that the value within the quotes is the exactly the same as the file name that was copied into the assets folder.
.
- Add the following class variables
:-
public static final int DBVERSION = 1;
public static final String TB_BOOKMARK = "Bookmark";
public static final String COL_BOOKMARK_KEY = "key";
public static final String COL_BOOKMARK_VALUE = "value";
public static final String COL_BOOKMARK_DATE = "date";
SQLiteDatabase mDB;
- Noting that the values in quotes need to match the respetice table/column names that were defined in the database for TB_BOOKMARK, COL_BOOKMARK_KEY, COL_BOOKMARK_VALUE and COl_BOOKMARK_DATE.
- DBVERSION will be the version number stored in the database's user_version field.
- SQliteDatabase mDB is a declartion for a variable to hold the SQLiteDatabase when it has been opened. NOTE currently it's value is null until it has been set.
.
Change the constructor for the Databasehelper class from :-
public DatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
to :-
public DatabaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
}
- This makes it so the an instance of the Databasehelper class can be created with just one parameter, the context. The other values have been defined or in the case of the factory none will be used, so null signifies this.
.
- Add a method,
ifDBExists
to the DatabaseHelper class to check to see if the database exists (you only want to copy it from the assets file once)
:-
private boolean ifDBExists(Context context) {
String dbparent = context.getDatabasePath(DBNAME).getParent();
File f = context.getDatabasePath(DBNAME);
if (!f.exists()) {
Log.d("NODB MKDIRS","Database file not found, making directories."); //<<<< remove before the App goes live.
File d = new File(dbparent);
d.mkdirs();
//return false;
}
return f.exists();
}
- In addition to checking that the database file exists (note it is assumed to be a valid database file),
- Additionally, if the database doesn't exist then it may be that the database directory doesn't exist, this will create it if it doesn't exist.
.
- Add another method
copyDBFromAssets
to copy the asset file to the database
:-
private boolean copyDBFromAssets(Context context) {
Log.d("CPYDBINFO","Starting attemtpt to cop database from the assets file.");
String DBPATH = context.getDatabasePath(DBNAME).getPath();
InputStream is;
OutputStream os;
int length = 8192;
long bytes_read = 0;
long bytes_written = 0;
byte[] buffer = new byte[length];
try {
is = context.getAssets().open(DBNAME);
} catch (IOException e) {
Log.e("CPYDB FAIL - NO ASSET","Failed to open the Asset file " + DBNAME);
e.printStackTrace();
return false;
}
try {
os = new FileOutputStream(DBPATH);
} catch (IOException e) {
Log.e("CPYDB FAIL - OPENDB","Failed to open the Database File at " + DBPATH);
e.printStackTrace();
return false;
}
Log.d("CPYDBINFO","Initiating copy from asset file" + DBNAME + " to " + DBPATH);
while (length >= 8192) {
try {
length = is.read(buffer,0,length);
} catch (IOException e) {
Log.e("CPYDB FAIL - RD ASSET",
"Failed while reading in data from the Asset. " +
String.valueOf(bytes_read) +
" bytes read ssuccessfully."
);
e.printStackTrace();
return false;
}
bytes_read = bytes_read + length;
try {
os.write(buffer,0,length);
} catch (IOException e) {
Log.e("CPYDB FAIL - WR ASSET","failed while writing Database File " +
DBPATH +
". " +
String.valueOf(bytes_written) +
" bytes written successfully.");
e.printStackTrace();
return false;
}
bytes_written = bytes_written + length;
}
Log.d("CPYDBINFO",
"Read " + String.valueOf(bytes_read) + " bytes. " +
"Wrote " + String.valueOf(bytes_written) + " bytes."
);
try {
os.flush();
is.close();
os.close();
} catch (IOException e ) {
Log.e("CPYDB FAIL - FINALISING","Failed Finalising Database Copy. " +
String.valueOf(bytes_read) +
" bytes read." +
String.valueOf(bytes_written) +
" bytes written."
);
e.printStackTrace();
return false;
}
return true;
}
- Note this is intentionally long-winded, so that any failure can be pin-pointed.
The complete DatabaseHelper class would now be :-
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DBNAME = "my_dic.db"; // <<<< VERY IMPORTANT THAT THIS MATCHES DATABASE FILE NAME
public static final int DBVERSION = 1;
public static final String TB_BOOKMARK = "Bookmark";
public static final String COL_BOOKMARK_KEY = "key";
public static final String COL_BOOKMARK_VALUE = "value";
public static final String COL_BOOKMARK_DATE = "date";
SQLiteDatabase mDB;
public DatabaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
if (!ifDBExists(context)) {
if (!copyDBFromAssets(context)) {
throw new RuntimeException("Failed to Copy Database From Assets Folder");
}
}
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
private boolean ifDBExists(Context context) {
String dbparent = context.getDatabasePath(DBNAME).getParent();
File f = context.getDatabasePath(DBNAME);
if (!f.exists()) {
Log.d("NODB MKDIRS","Database file not found, making directories.");
File d = new File(dbparent);
d.mkdirs();
//return false;
}
return f.exists();
}
private boolean copyDBFromAssets(Context context) {
Log.d("CPYDBINFO","Starting attemtpt to cop database from the assets file.");
String DBPATH = context.getDatabasePath(DBNAME).getPath();
InputStream is;
OutputStream os;
int length = 8192;
long bytes_read = 0;
long bytes_written = 0;
byte[] buffer = new byte[length];
try {
is = context.getAssets().open(DBNAME);
} catch (IOException e) {
Log.e("CPYDB FAIL - NO ASSET","Failed to open the Asset file " + DBNAME);
e.printStackTrace();
return false;
}
try {
os = new FileOutputStream(DBPATH);
} catch (IOException e) {
Log.e("CPYDB FAIL - OPENDB","Failed to open the Database File at " + DBPATH);
e.printStackTrace();
return false;
}
Log.d("CPYDBINFO","Initiating copy from asset file" + DBNAME + " to " + DBPATH);
while (length >= 8192) {
try {
length = is.read(buffer,0,length);
} catch (IOException e) {
Log.e("CPYDB FAIL - RD ASSET",
"Failed while reading in data from the Asset. " +
String.valueOf(bytes_read) +
" bytes read ssuccessfully."
);
e.printStackTrace();
return false;
}
bytes_read = bytes_read + length;
try {
os.write(buffer,0,length);
} catch (IOException e) {
Log.e("CPYDB FAIL - WR ASSET","failed while writing Database File " +
DBPATH +
". " +
String.valueOf(bytes_written) +
" bytes written successfully.");
e.printStackTrace();
return false;
}
bytes_written = bytes_written + length;
}
Log.d("CPYDBINFO",
"Read " + String.valueOf(bytes_read) + " bytes. " +
"Wrote " + String.valueOf(bytes_written) + " bytes."
);
try {
os.flush();
is.close();
os.close();
} catch (IOException e ) {
Log.e("CPYDB FAIL - FINALISING","Failed Finalising Database Copy. " +
String.valueOf(bytes_read) +
" bytes read." +
String.valueOf(bytes_written) +
" bytes written."
);
e.printStackTrace();
return false;
}
return true;
}
}
.
- Change the constructor to run the
copyDBFromAssets
method when/if the Database doesn't exist (using the ifDBExists
method)
:-
public DatabaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
if (!ifDBExists(context)) {
if (!copyDBFromAssets(context)) {
throw new RuntimeException("Failed to Copy Database From Assets Folder");
}
}
mDB = this.getWritableDatabase();
}
- Note if there was an issue copying the Database then the App will be stopped due to the
RunTimeExcpetion
issued.
.
- Last amend an activity's onCreate method (would normally be the main activity) to create an instance of the DatabaseHelper class. Then run the App (if the App has been run it would be best to delete the App's data before doing so, just in case a database, perhaps empty, has been created.)
The following code also includes a query that will tell you what tables exist in the database :-
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DatabaseHelper mDBHlpr = new DatabaseHelper(this);
Cursor csr = mDBHlpr.getWritableDatabase().query(
"sqlite_master",
null,null,null,null,null,null
);
while (csr.moveToNext()) {
Log.d("DB TABLES", csr.getString(csr.getColumnIndex("name")));
}
csr.close();
}
}
Based upon the screen shot and a database file named my_dic.db
. The output in the Log is :-
06-16 02:28:45.208 4467-4467/? D/NODB MKDIRS: Database file not found, making directories.
06-16 02:28:45.208 4467-4467/? D/CPYDBINFO: Starting attemtpt to cop database from the assets file.
Initiating copy from asset filemy_dic.db to /data/data/com.mydictionaryapp.mydictionaryapp/databases/my_dic.db
Read 12288 bytes. Wrote 12288 bytes.
06-16 02:28:45.224 4467-4467/? D/DB TABLES: Bookmark
sqlite_autoindex_Bookmark_1
android_metadata
- This indicates that :-
- The database didn't exist and the databases directory was created (i.e.
data/data/<package name>/databases
)
- 12288 bytes were copied from the asset file to the database file (i.e. a successful copy was made).
- The resultant database has three entries in the sqlite_master table, the BookMark table, a table called android_metadata (a table automatically create for android devices by the SDK which stores the locale) and an automatically generated index for the BookMark table.
Subsequent Issue
Basically the object doesn't have a method called getClass, rather you need to use the Fragment's inherited getClass method. So you need to enclose the returned fragment in parenthesis's.
So instead of :-
String activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();
You could use :-
String activeFragment = (getSupportFragmentManager().findFragmentById(R.id.fragment_container)).getClass().getSimpleName();
Alternately you could use :-
Fragment activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
along with using :-
if (activeFragment instanceOf BookmarkFragment) { ...... rest of your code
instead of using if (activeFragment.equals(BookmarkFragment.class.getSimpleName())) { ......