Тъй като срещате затруднения, следното е набързо съставен урок заедно с кода.
-
Създайте базата данни и таблиците в инструмент SQLite, като добавите данни според изискванията и след това ги запазете.
-
Затворете базата данни и я отворете отново, за да проверите дали таблиците и данните са според очакванията. Ако не, направете промени и след това повторете 2, докато не сте сигурни, че запазената база данни съвпада.
-
Вземете името на файла на запазената база данни и го запишете, включително разширението на файла.
-
Ако все още не сте създали проект за приложението, направете го и запазете проекта.
-
Извън IDE отидете до проектите app/src/main папка и създайте папка с име assets ако вече не съществува.
-
Копирайте файла на базата данни в папката с активи.
-
Отворете проекта в Android Studio.
-
Създайте нов Java клас с име DatabaseHelper със SuperClass като SQLiteOpenHelper (ще се разреши до
android.database.sqlite.SQLiteOpenHelper
) и поставете отметка в Показване на отмените избора Диалогово квадратче за отметка. Щракнете върху OK.
Трябва да изглежда така:-
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) {
}
}
-
Добавете ред като променлива на клас, след като
public class DatabaseHelper extends SQLiteOpenHelper {
това е като :-public static final String DBNAME = "my_dic.db";
- Отбелязвайки, че е важно стойността в кавичките да е точно същата като името на файла, който е копиран в папката с активи.
.
- Добавете следните променливи на класа
:-
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;
- Отбелязвайки, че стойностите в кавички трябва да съвпадат с имената на таблицата/колоните с повторение, които са били дефинирани в базата данни за TB_BOOKMARK, COL_BOOKMARK_KEY, COL_BOOKMARK_VALUE и COl_BOOKMARK_DATE.
- DBVERSION ще бъде номерът на версията, съхранен в полето user_version на базата данни.
- SQliteDatabase mDB е декларация за променлива, която съхранява SQLiteDatabase, когато е отворена. ЗАБЕЛЕЖКА, че в момента стойността му е нула, докато не бъде зададена.
.
-
Променете конструктора за класа Databasehelper от :-
public DatabaseHelper(контекст на контекст, име на низ, SQLiteDatabase.CursorFactory factory, int версия) {super(context, name, factory, version);}
до :-
public DatabaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
}
- Това прави така, че екземпляр на класа Databasehelper може да бъде създаден само с един параметър, контекста. Другите стойности са дефинирани или в случай на фабричния случай няма да се използва нито една, така че null означава това.
.
- Добавете метод,
ifDBExists
към класа DatabaseHelper, за да проверите дали базата данни съществува (искате само веднъж да я копирате от файла с активи)
:-
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();
}
- В допълнение към проверката дали файлът на базата данни съществува (имайте предвид, че се приема, че е валиден файл с база данни),
- Освен това, ако базата данни не съществува, може да се окаже, че директорията на базата данни не съществува, това ще я създаде, ако не съществува.
.
- Добавете друг метод
copyDBFromAssets
за да копирате файла с активите в базата данни
:-
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;
}
- Обърнете внимание, че това е умишлено дълготрайно, така че всяка неизправност да може да бъде точно определена.
Пълният клас DatabaseHelper сега ще бъде :-
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;
}
}
.
- Променете конструктора, за да стартирате
copyDBFromAssets
метод, когато/ако базата данни не съществува (с помощта наifDBExists
метод)
:-
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();
}
- Обърнете внимание, ако е имало проблем с копирането на базата данни, приложението ще бъде спряно поради
RunTimeExcpetion
издадено.
.
- Последна промяна на метода onCreate на дейност (обикновено би бил основната дейност), за да създадете екземпляр на класа DatabaseHelper. След това стартирайте приложението (ако приложението е стартирано, най-добре би било да изтриете данните на приложението, преди да го направите, само в случай, че е създадена база данни, може би празна.)
Следният код включва също заявка, която ще ви каже какви таблици съществуват в базата данни:-
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();
}
}
Въз основа на екранната снимка и файл с база данни с име my_dic.db
. Резултатът в дневника е:-
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
- Това показва, че :-
- База данни не съществуваше и директорията на базите данни беше създадена (т.е.
data/data/<package name>/databases
) - 12288 байта бяха копирани от файла с активи във файла на базата данни (т.е. беше направено успешно копие).
- Резултантната база данни има три записа в таблицата sqlite_master, таблицата BookMark, таблица, наречена android_metadata (таблица, създадена автоматично за устройства с Android от SDK, която съхранява локала) и автоматично генериран индекс за таблицата BookMark.
- База данни не съществуваше и директорията на базите данни беше създадена (т.е.
Последващ брой
По принцип обектът няма метод, наречен getClass, по-скоро трябва да използвате наследения метод getClass на фрагмента. Така че трябва да затворите върнатия фрагмент в скоби.
Така че вместо :-
String activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();
Можете да използвате :-
String activeFragment = (getSupportFragmentManager().findFragmentById(R.id.fragment_container)).getClass().getSimpleName();
Като алтернатива можете да използвате :-
Fragment activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
заедно с използването на :-
if (activeFragment instanceOf BookmarkFragment) { ...... rest of your code
вместо да използвате if (activeFragment.equals(BookmarkFragment.class.getSimpleName())) { ......