Eftersom du har problem är följande en hastigt ihopsatt handledning tillsammans med kod.
-
Skapa databasen och tabellerna i ett SQLite-verktyg, lägg till data efter behov och spara dem sedan.
-
Stäng databasen och öppna den igen för att kontrollera att tabellerna och data är som förväntat. Om inte gör ändringar och upprepa sedan 2 tills du är säker på att den sparade databasen matchar.
-
Skaffa filnamnet för den sparade databasen och registrera det inklusive filtillägget.
-
Om du ännu inte har skapat ett projekt för appen gör du det och sparar projektet.
-
Utanför IDE:n navigera till projektens app/src/huvudmapp och skapa en mapp med namnet tillgångar om det inte redan finns.
-
Kopiera databasfilen till tillgångsmappen.
-
Öppna projektet i Android Studio.
-
Skapa en ny Java-klass med namnet DatabasHelper med SuperClass som SQLiteOpenHelper (kommer att lösas till
android.database.sqlite.SQLiteOpenHelper
) och markera Visa markeringar Kryssruta i dialogrutan. Klicka på OK.
Det ska se ut så här:-
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) {
}
}
-
Lägg till en rad, som en klassvariabel, efter
public class DatabaseHelper extends SQLiteOpenHelper {
det är som :-public static final String DBNAME = "my_dic.db";
- Notera att det är viktigt att värdet inom citattecken är exakt detsamma som filnamnet som kopierades till tillgångsmappen.
.
- Lägg till följande klassvariabler
:-
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;
- Notera att värdena inom citattecken måste matcha respetstabellen/kolumnnamnen som definierades i databasen för TB_BOOKMARK, COL_BOOKMARK_KEY, COL_BOOKMARK_VALUE och COl_BOOKMARK_DATE.
- DBVERSION kommer att vara versionsnumret som lagras i databasens user_version-fält.
- SQliteDatabase mDB är en deklaration för en variabel att hålla SQLiteDatabasen när den har öppnats. OBS för närvarande är dess värde null tills det har ställts in.
.
-
Ändra konstruktorn för klassen Databasehelper från :-
public DatabaseHelper(Kontextkontext, Stringnamn, SQLiteDatabase.CursorFactory factory, int version) {super(kontext, namn, fabrik, version);}
till :-
public DatabaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
}
- Detta gör det så att en instans av klassen Databasehelper kan skapas med bara en parameter, kontexten. De andra värdena har definierats eller i fallet med fabriken kommer inga att användas, så null betyder detta.
.
- Lägg till en metod,
ifDBExists
till DatabaseHelper-klassen för att kontrollera om databasen finns (du vill bara kopiera den från tillgångsfilen en gång)
:-
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();
}
- Förutom att kontrollera att databasfilen finns (observera att den antas vara en giltig databasfil),
- Om databasen inte finns kan det dessutom vara så att databaskatalogen inte existerar, detta kommer att skapa den om den inte finns.
.
- Lägg till en annan metod
copyDBFromAssets
för att kopiera tillgångsfilen till databasen
:-
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;
}
- Observera att detta är avsiktligt långrandigt, så att alla fel kan upptäckas.
Den kompletta DatabaseHelper-klassen skulle nu vara :-
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;
}
}
.
- Ändra konstruktorn för att köra
copyDBFromAssets
metod när/om databasen inte finns (med hjälp avifDBExists
metod)
:-
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();
}
- Observera att om det var problem med att kopiera databasen kommer appen att stoppas på grund av
RunTimeExcpetion
utfärdat.
.
- Ändra senast en aktivitets onCreate-metod (skulle normalt vara huvudaktiviteten) för att skapa en instans av klassen DatabaseHelper. Kör sedan appen (om appen har körts är det bäst att ta bort appens data innan du gör det, ifall en databas, kanske tom, har skapats.)
Följande kod innehåller också en fråga som berättar vilka tabeller som finns i databasen :-
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();
}
}
Baserat på skärmdumpen och en databasfil med namnet my_dic.db
. Utdata i loggen är :-
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
- Detta indikerar att :-
- Databasen fanns inte och databaskatalogen skapades (dvs.
data/data/<package name>/databases
) - 12288 byte kopierades från tillgångsfilen till databasfilen (dvs. en lyckad kopia gjordes).
- Den resulterande databasen har tre poster i sqlite_master-tabellen, BookMark-tabellen, en tabell som heter android_metadata (en tabell som automatiskt skapas för Android-enheter av SDK som lagrar lokalen) och ett automatiskt genererat index för BookMark-tabellen.
- Databasen fanns inte och databaskatalogen skapades (dvs.
Efterföljande nummer
Objektet har i princip inte en metod som heter getClass, utan du måste använda fragmentets ärvda getClass-metod. Så du måste omge det returnerade fragmentet inom parentes.
Så istället för :-
String activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();
Du kan använda :-
String activeFragment = (getSupportFragmentManager().findFragmentById(R.id.fragment_container)).getClass().getSimpleName();
Alternativt kan du använda :-
Fragment activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
tillsammans med att använda :-
if (activeFragment instanceOf BookmarkFragment) { ...... rest of your code
istället för att använda if (activeFragment.equals(BookmarkFragment.class.getSimpleName())) { ......