Кроме создания новой базы данных мы также можем использовать уже существующую. Это может быть более предпочтительно, так как в этом случае база данных приложения уже будет содержать всю необходимую информацию.
Возьмем проект, созданный в предыдущей теме, где у нас была MainActivity, которая выводила список объектов, и UserActivity, которая позволяла добавлять, редактировать и удалять объекты из БД
Для начала создадим базу данных SQLite. В этом нам может помочь такой инструмент как Sqlitebrowser. Он бесплатный и доступен для различных операционных систем по адресу https://sqlitebrowser.org/. Хотя можно использовать и другие способы для создания начальной БД.
Sqlitebrowser представляет графический интерфейс для создания базы данных и определения в ней всех необходимых таблиц:
Как видно на скриншоте, я определяю таблицу users с тремя полями: _id, name, age. Общая команда на создание таблицы будет следующей:
CREATE TABLE `users` ( `_id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, `name` TEXT NOT NULL, `year` INTEGER NOT NULL );
Там же в программе добавим несколько элементов в созданную таблицу:
После создания таблицы добавим в проект в Android Studio папку assets, а в папку assets - только что созданную базу данных. Для этого перейдем к полному опеределению проекта, нажмем на папку main правой кнопкой мыши и в меню выберем New -> Directory:
Затем в появившемся окошке выберем пункт src\main\assets и нажмем на Enter для ее добавления в проект::
И затем скопируем в нее нашу базу данных:
В моем случае база данных называется "cityinfo.db".
Изменим код DatabaseHelper следующим образом:
package com.example.sqliteapp;
import android.database.SQLException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;
import android.content.Context;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
class DatabaseHelper extends SQLiteOpenHelper {
private static String DB_PATH; // полный путь к базе данных
private static String DB_NAME = "cityinfo.db";
private static final int SCHEMA = 1; // версия базы данных
static final String TABLE = "users"; // название таблицы в бд
// названия столбцов
static final String COLUMN_ID = "_id";
static final String COLUMN_NAME = "name";
static final String COLUMN_YEAR = "year";
private Context myContext;
DatabaseHelper(Context context) {
super(context, DB_NAME, null, SCHEMA);
this.myContext=context;
DB_PATH =context.getFilesDir().getPath() + DB_NAME;
}
@Override
public void onCreate(SQLiteDatabase db) { }
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
void create_db(){
File file = new File(DB_PATH);
if (!file.exists()) {
//получаем локальную бд как поток
try(InputStream myInput = myContext.getAssets().open(DB_NAME);
// Открываем пустую бд
OutputStream myOutput = new FileOutputStream(DB_PATH)) {
// побайтово копируем данные
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
}
catch(IOException ex){
Log.d("DatabaseHelper", ex.getMessage());
}
}
}
public SQLiteDatabase open()throws SQLException {
return SQLiteDatabase.openDatabase(DB_PATH, null, SQLiteDatabase.OPEN_READWRITE);
}
}
По умолчанию база данных будет размещаться во внешнем хранилище, выделяемом для приложения в папке /data/data/[название_пакета]/databases/, и чтобы получить полный путь к базе данных в конструкторе используется выражение:
DB_PATH =context.getFilesDir().getPath() + DB_NAME;
Метод onCreate() нам не нужен, так как нам не требуется создание встроенной базы данных. Зато здесь определен дополнительный метод
create_db(), цель которого копирование базы данных из папки assets в то место, которое указано в переменной DB_PATH.
Кроме этого здесь также определен метод открытия базы данных open() с помощью метода SQLiteDatabase.openDatabase()
Новый способ организации подключения изменит использование DatabaseHelper в activity. Так, обновим класс MainActivity:
package com.example.sqliteapp;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.SimpleCursorAdapter;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.widget.ListView;
public class MainActivity extends AppCompatActivity {
ListView userList;
DatabaseHelper databaseHelper;
SQLiteDatabase db;
Cursor userCursor;
SimpleCursorAdapter userAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userList = findViewById(R.id.list);
userList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(getApplicationContext(), UserActivity.class);
intent.putExtra("id", id);
startActivity(intent);
}
});
databaseHelper = new DatabaseHelper(getApplicationContext());
// создаем базу данных
databaseHelper.create_db();
}
@Override
public void onResume() {
super.onResume();
// открываем подключение
db = databaseHelper.open();
//получаем данные из бд в виде курсора
userCursor = db.rawQuery("select * from " + DatabaseHelper.TABLE, null);
// определяем, какие столбцы из курсора будут выводиться в ListView
String[] headers = new String[]{DatabaseHelper.COLUMN_NAME, DatabaseHelper.COLUMN_YEAR};
// создаем адаптер, передаем в него курсор
userAdapter = new SimpleCursorAdapter(this, android.R.layout.two_line_list_item,
userCursor, headers, new int[]{android.R.id.text1, android.R.id.text2}, 0);
userList.setAdapter(userAdapter);
}
// по нажатию на кнопку запускаем UserActivity для добавления данных
public void add(View view) {
Intent intent = new Intent(this, UserActivity.class);
startActivity(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
// Закрываем подключение и курсор
db.close();
userCursor.close();
}
}
И также изменим класс UserActivity:
package com.example.sqliteapp;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class UserActivity extends AppCompatActivity {
EditText nameBox;
EditText yearBox;
Button delButton;
Button saveButton;
DatabaseHelper sqlHelper;
SQLiteDatabase db;
Cursor userCursor;
long userId=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user);
nameBox = findViewById(R.id.name);
yearBox = findViewById(R.id.year);
delButton = findViewById(R.id.deleteButton);
saveButton = findViewById(R.id.saveButton);
sqlHelper = new DatabaseHelper(this);
db = sqlHelper.open();
Bundle extras = getIntent().getExtras();
if (extras != null) {
userId = extras.getLong("id");
}
// если 0, то добавление
if (userId > 0) {
// получаем элемент по id из бд
userCursor = db.rawQuery("select * from " + DatabaseHelper.TABLE + " where " +
DatabaseHelper.COLUMN_ID + "=?", new String[]{String.valueOf(userId)});
userCursor.moveToFirst();
nameBox.setText(userCursor.getString(1));
yearBox.setText(String.valueOf(userCursor.getInt(2)));
userCursor.close();
} else {
// скрываем кнопку удаления
delButton.setVisibility(View.GONE);
}
}
public void save(View view){
ContentValues cv = new ContentValues();
cv.put(DatabaseHelper.COLUMN_NAME, nameBox.getText().toString());
cv.put(DatabaseHelper.COLUMN_YEAR, Integer.parseInt(yearBox.getText().toString()));
if (userId > 0) {
db.update(DatabaseHelper.TABLE, cv, DatabaseHelper.COLUMN_ID + "=" + userId, null);
} else {
db.insert(DatabaseHelper.TABLE, null, cv);
}
goHome();
}
public void delete(View view){
db.delete(DatabaseHelper.TABLE, "_id = ?", new String[]{String.valueOf(userId)});
goHome();
}
private void goHome(){
// закрываем подключение
db.close();
// переход к главной activity
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
}
Вся остальная работа с данными будет той же, чтобы и в прошлых темах: