Кроме создания новой базы данных мы также можем использовать уже существующую. Это может быть более предпочтительно, так как в этом случае база данных приложения уже будет содержать всю необходимую информацию.
Возьмем проект, созданный в предыдущей теме, где у нас была 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); } }
Вся остальная работа с данными будет той же, чтобы и в прошлых темах: