Как подключить sqlite к android studio
Перейти к содержимому

Как подключить sqlite к android studio

  • автор:

Как добавить готовую базу SQLite в Android-приложение

Сразу предупрежу, что материал не основан на моём опыте. Несколько раз встречал описание данной задачи и решил сохранить себе на всякий случай. Буду рад любым замечаниям, если использовали подобный способ.

Upd. Прошло несколько лет, материал мог слегка устареть. Появилась ещё одна статья уже на Kotlin — Ship an Android app with a pre-populated database

Как известно, обычно мы в коде создаём новую пустую базу и пользователь начинает её заполнять. Если база небольшая, то также в коде можно программно добавить нужные записи. Но если требуется большая база данных на несколько мегабайт, то невольно задумаешься о решении проблемы.

Одним из способов является копирование заранее подготовленного файла базы данных в папку assets на этапе разработки, а далее программно можно скопировать данный файл в нужную системную папку базы данных вашего приложения. После этой операции можно работать с базой данных обычным способом.

Подготовить файл базы данных можно на рабочем компьютере при помощи различных программ для работы с SQLite, например, SQLite Database Browser.

Есть небольшая тонкость — кроме таблицы, которую вы создаёте для приложения, Android также создаёт для своих целей новую таблицу android_metadata в вашей базе. Поэтому при ручном создании базы вам необходимо создать как минимум две таблицы: системную и свою рабочую.

Откройте вашу базу и добавьте новую таблицу под названием «android_metadata»:

 CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US') 

Добавим в таблицу одну строку:

 INSERT INTO "android_metadata" VALUES ('en_US') 

Далее можете создать свои таблицы для работы.

Переименуйте первичное поле id на «_id», как требует Android. В SQLite Database Browser это можно сделать, нажав на кнопку Редактировать, потом выбрав таблицу, которую вы хотите изменить, и, наконец, выбрав поле для переименования.

После выполнения указанных операций база данных готова для использования в вашем приложении.

Поместите ваш файл базы данных в папку assets вашего проекта и создайте новый класс, наследующий от SQLiteOpenHelper.

 public class DataBaseHelper extends SQLiteOpenHelper < // путь к базе данных вашего приложения private static String DB_PATH = "/data/data/YOUR_PACKAGE/databases/"; private static String DB_NAME = "myDBName"; private SQLiteDatabase myDataBase; private final Context mContext; /** * Конструктор * Принимает и сохраняет ссылку на переданный контекст для доступа к ресурсам приложения * @param context */ public DataBaseHelper(Context context) < super(context, DB_NAME, null, 1); this.mContext = context; >/** * Создает пустую базу данных и перезаписывает ее нашей собственной базой * */ public void createDataBase() throws IOException< boolean dbExist = checkDataBase(); if(dbExist)< //ничего не делать - база уже есть >else < //вызывая этот метод создаем пустую базу, позже она будет перезаписана this.getReadableDatabase(); try < copyDataBase(); >catch (IOException e) < throw new Error("Error copying database"); >> > /** * Проверяет, существует ли уже эта база, чтобы не копировать каждый раз при запуске приложения * @return true если существует, false если не существует */ private boolean checkDataBase()< SQLiteDatabase checkDB = null; try< String myPath = DB_PATH + DB_NAME; checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); >catch(SQLiteException e) < //база еще не существует >if(checkDB != null) < checkDB.close(); >return checkDB != null ? true : false; > /** * Копирует базу из папки assets заместо созданной локальной БД * Выполняется путем копирования потока байтов. * */ private void copyDataBase() throws IOException< //Открываем локальную БД как входящий поток InputStream myInput = mContext.getAssets().open(DB_NAME); //Путь ко вновь созданной БД String outFileName = DB_PATH + DB_NAME; //Открываем пустую базу данных как исходящий поток OutputStream myOutput = new FileOutputStream(outFileName); //перемещаем байты из входящего файла в исходящий byte[] buffer = new byte[1024]; int length; while ((length = myInput.read(buffer))>0) < myOutput.write(buffer, 0, length); >//закрываем потоки myOutput.flush(); myOutput.close(); myInput.close(); > public void openDataBase() throws SQLException < //открываем БД String myPath = DB_PATH + DB_NAME; myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); >@Override public synchronized void close() < if(myDataBase != null) myDataBase.close(); super.close(); >@Override public void onCreate(SQLiteDatabase db) < >@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) < >// Здесь можно добавить вспомогательные методы для доступа и получения данных из БД // вы можете возвращать курсоры через "return myDataBase.query(. )", это облегчит их использование // в создании адаптеров для ваших view > 

Теперь вы можете создать новый экземпляр класса DataBaseHelper и вызвать методы createDataBase() и openDataBase(). Не забудьте изменить YOUR_PACKAGE на имя пакета в вашем приложении в строке DB_PATH.

 DataBaseHelper myDbHelper = new DataBaseHelper(this); myDbHelper = new DataBaseHelper(this); try < myDbHelper.createDataBase(); >catch (IOException ioe) < throw new Error("Unable to create database"); >try < myDbHelper.openDataBase(); >catch(SQLException sqle) < throw sqle; >. 

Библиотека для работы с готовой базой

На Github есть проект в виде отдельной библиотеки, позволяющая упростить работу по переносу готовой базы данных с компьютера на устройство. Как я понял из описания, базу нужно заархивировать и положить в папку assets/databases/.

Другой способ

Ещё один способ, найденный в сети.

Поместим файл базы данных в zip-архив и переместим его в папку res/raw.

В методе onCreate() проверим — запускается ли приложение первый раз. Распакуем БД и переместим её на SD-карту. Установим соединение с базой. Проверим, существует ли файл БД, если не существует, то нужно его развернуть из файла.

Данный метод поместим в onCreate().

public void createDataBase() throws IOException < //получаем путь к SD-карте. File DB_PATH = myContext.getExternalCacheDir(); //создаём каталог для нашей базы данных DB_PATH.mkdirs(); //проверяем есть ли уже файл БД на карте File db = new File(DB_PATH, DB_NAME); if(!db.exists()) < //если файла нет, то попытаемся его создать db.createNewFile(); try < copyFromZipFile(); >catch (IOException e) < throw new Error("Error copying database",e); >>

Этот метод копирует файл БД из res/raw на SD-карту

private void copyFromZipFile() throws IOException < InputStream is = myContext.getResources().openRawResource(R.raw.database); File outFile = new File(DB_PATH ,DB_NAME); OutputStream myOutput = new FileOutputStream(outFile.getAbsolutePath()); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is)); try < ZipEntry ze; while ((ze = zis.getNextEntry()) != null) < ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int count; while ((count = zis.read(buffer)) != -1) < baos.write(buffer, 0, count); >baos.writeTo(myOutput); > > finally < zis.close(); myOutput.flush(); myOutput.close(); is.close(); >>

Устанавливаем соединение с БД.

public SQLiteDatabase openDataBase() throws SQLException

Подключение существующей БД SQLite в Android Studio (кратко)

В статье представлен класс для использования существующей базы данных SQLite. Данный класс позволяет обновлять базу данных через переменную DB_VERSION.

Подготовка файла базы данных SQLite

Для создания SQLite базы данных я рекомендую использовать DB Browser for SQLite. Скачайте и установите. Создайте базу данных в виде файла и сохраните его.

Добавьте файл базы данных в папку assets .

Класс для подключения к базе данных

Данный класс позволяет не только копировать существующую базу данных, но и обновлять ее в соответствии с номером версии базы данных:

//package org.harrix.sqliteexample; import android.content.Context; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class DatabaseHelper extends SQLiteOpenHelper  private static String DB_NAME = "info.db"; private static String DB_PATH = ""; private static final int DB_VERSION = 1; private SQLiteDatabase mDataBase; private final Context mContext; private boolean mNeedUpdate = false; public DatabaseHelper(Context context)  super(context, DB_NAME, null, DB_VERSION); if (android.os.Build.VERSION.SDK_INT >= 17) DB_PATH = context.getApplicationInfo().dataDir + "/databases/"; else DB_PATH = "/data/data/" + context.getPackageName() + "/databases/"; this.mContext = context; copyDataBase(); this.getReadableDatabase(); > public void updateDataBase() throws IOException  if (mNeedUpdate)  File dbFile = new File(DB_PATH + DB_NAME); if (dbFile.exists()) dbFile.delete(); copyDataBase(); mNeedUpdate = false; > > private boolean checkDataBase()  File dbFile = new File(DB_PATH + DB_NAME); return dbFile.exists(); > private void copyDataBase()  if (!checkDataBase())  this.getReadableDatabase(); this.close(); try  copyDBFile(); > catch (IOException mIOException)  throw new Error("ErrorCopyingDataBase"); > > > private void copyDBFile() throws IOException  InputStream mInput = mContext.getAssets().open(DB_NAME); // InputStream mInput = mContext.getResources().openRawResource(R.raw.info); OutputStream mOutput = new FileOutputStream(DB_PATH + DB_NAME); byte[] mBuffer = new byte[1024]; int mLength; while ((mLength = mInput.read(mBuffer)) > 0) mOutput.write(mBuffer, 0, mLength); mOutput.flush(); mOutput.close(); mInput.close(); > public boolean openDataBase() throws SQLException  mDataBase = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.CREATE_IF_NECESSARY); return mDataBase != null; > @Override public synchronized void close()  if (mDataBase != null) mDataBase.close(); super.close(); > @Override public void onCreate(SQLiteDatabase db)  > @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)  if (newVersion > oldVersion) mNeedUpdate = true; > >: 

Использование класса

В классе активности объявите переменные:

private DatabaseHelper mDBHelper; private SQLiteDatabase mDb; 

В методе onCreate пропишите следующий код:

mDBHelper = new DatabaseHelper(this); try  mDBHelper.updateDataBase(); > catch (IOException mIOException)  throw new Error("UnableToUpdateDatabase"); > try  mDb = mDBHelper.getWritableDatabase(); > catch (SQLException mSQLException)  throw mSQLException; > 

Файл базы данных в папке res/raw

Если вы добавляете файл базы данных в папку ‘res/raw`, то используйте следующую модификацию класса:

«`java //package org.harrix.sqliteexample;

import android.content.Context; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper;

import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;

В статье представлен класс для использования существующей базы данных SQLite. Данный класс позволяет обновлять базу данных через переменную DB_VERSION.

В статье представлен класс для использования существующей базы данных SQLite. Данный класс позволяет обновлять базу данных через переменную DB_VERSION.

Harrix

  • GitHub User
  • TODO@mail.ru

Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.

Работа с базами данных SQLite

В Android имеется встроенная поддержка одной из распространенных систем управления базами данных — SQLite. Для этого в пакете android.database.sqlite определен набор классов, которые позволяют работать с базами данных SQLite. И каждое приложение может создать свою базу данных.

Чтобы использовать SQLite в Android, надо создать базу данных с помощью выражение на языке SQL. После этого база данных будет храниться в каталоге приложения по пути:

DATA/data/[Название_приложения]/databases/[Название_файла_базы_данных]

ОС Android по умолчанию уже содержит ряд встроенных бад SQLite, которые используются стандартными программами — для списка контактов, для хранения фотографий с камеры, музыкальных альбомов и т.д.

Основную функциональность по работе с базами данных предоставляет пакет android.database . Функциональность непосредственно для работы с SQLite находится в пакете android.database.sqlite .

База данных в SQLite представлена классом android.database.sqlite.SQLiteDatabase . Он позволяет выполнять запросы к бд, выполнять с ней различные манипуляции.

Класс android.database.sqlite.SQLiteCursor предоставляет запрос и позволяет возвращать набор строк, которые соответствуют этому запросу.

Класс android.database.sqlite.SQLiteQueryBuilder позволяет создавать SQL-запросы.

Сами sql-выражения представлены классом android.database.sqlite.SQLiteStatement , которые позволяют с помощью плейсхолдеров вставлять в выражения динамические данные.

Класс android.database.sqlite.SQLiteOpenHelper позволяет создать базу данных со всеми таблицами, если их еще не существует.

В SQLite применяется следующая система типов данных:

  • INTEGER : представляет целое число, аналог типу int в java
  • REAL : представляет число с плавающей точкой, аналог float и double в java
  • TEXT : представляет набор символов, аналог String и char в java
  • BLOB : представляет массив бинарных данных, например, изображение, аналог типу int в java

Сохраняемые данные должны представлять соответствующие типы в java.

Создание и открытие базы данных

Для создания или открытия новой базы данных из кода Activity в Android мы можем вызвать метод openOrCreateDatabase() . Этот метод может принимать три параметра:

  • название для базы данных
  • числовое значение, которое определяет режим работы (как правило, в виде константы MODE_PRIVATE )
  • необязательный параметр в виде объекта SQLiteDatabase.CursorFactory , который представляет фабрику создания курсора для работы с бд

Например, создание базы данных app.db :

SQLiteDatabase db = getBaseContext().openOrCreateDatabase("app.db", MODE_PRIVATE, null);

Для выполнения запроса к базе данных можно использовать метод execSQL класса SQLiteDatabase. В этот метод передается SQL-выражение. Например, создание в базе данных таблицы users:

SQLiteDatabase db = getBaseContext().openOrCreateDatabase("app.db", MODE_PRIVATE, null); db.execSQL("CREATE TABLE IF NOT EXISTS users (name TEXT, age INTEGER)");

Если нам надо не просто выполнить выражение, но и получить из бд какие-либо данные, то используется метод rawQuery() . Этот метод в качестве параметра принимает SQL-выражение, а также набор значений для выражения sql. Например, получение всех объектов из базы данных:

SQLiteDatabase db = getBaseContext().openOrCreateDatabase(«app.db», MODE_PRIVATE, null); db.execSQL(«CREATE TABLE IF NOT EXISTS users (name TEXT, age INTEGER)»); Cursor query = db.rawQuery(«SELECT * FROM users;», null); if(query.moveToFirst())

Метод db.rawQuery() возвращает объект Cursor, с помощью которого мы можем извлечь полученные данные.

Возможна ситуация, когда в базе данных не будет объектов, и для этого методом query.moveToFirst() пытаемся переместиться к первому объекту, полученному из бд. Если этот метод возвратит значение false, значит запрос не получил никаких данных из бд.

Теперь для работы с базой данных сделаем простейшее приложение. Для этого создадим новый проект.

В файле activity_main.xml определим простейший графический интерфейс:

А в классе MainActivity определим взаимодействие с базой данных:

package com.example.sqliteapp; import androidx.appcompat.app.AppCompatActivity; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.view.View; import android.widget.TextView; public class MainActivity extends AppCompatActivity < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); >public void onClick(View view) < SQLiteDatabase db = getBaseContext().openOrCreateDatabase("app.db", MODE_PRIVATE, null); db.execSQL("CREATE TABLE IF NOT EXISTS users (name TEXT, age INTEGER, UNIQUE(name))"); db.execSQL("INSERT OR IGNORE INTO users VALUES ('Tom Smith', 23), ('John Dow', 31);"); Cursor query = db.rawQuery("SELECT * FROM users;", null); TextView textView = findViewById(R.id.textView); textView.setText(""); while(query.moveToNext())< String name = query.getString(0); int age = query.getInt(1); textView.append("Name: " + name + " Age: " + age + "\n"); >query.close(); db.close(); > >

По нажатию на кнопку здесь вначале создается в базе данных app.db новая таблица users, а затем в нее добавляются два объекта в базу данных с помощью SQL-выражения INSERT.

Далее с помощью выражения SELECT получаем всех добавленных пользователей из базы данных в виде курсора Cursor.

Вызовом query.moveToNext() перемещаемся в цикле while последовательно по всем объектам.

Для получения данных из курсора применяются методы query.getString(0) и query.getInt(1) . В скобках в методы передается номер столбца, из которого мы получаем данные. Например, выше мы добавили вначале имя пользователя в виде строки, а затем возраст в виде числа. Значит, нулевым столбцом будет идти строкое значение, которое получаем с помощью метода getString() , а следующим — первым столбцом идет числовое значение, для которого применяется метод getInt() .

После завершения работы с курсором и базой данных мы закрываем все связанные объекты:

query.close(); db.close();

Если мы не закроем курсор, то можем столкнуться с проблемой утечки памяти.

И если мы обратимся к приложению, то после нажатия на кнопку в текстовое поле будут выведены добавленные данные:

Как подключить внешнюю базу данных SQLite в Android?

Таблица есть — проверял через DB Browser,через него и создавал базу.

Я так понимаю, он просто не видит эту базу данных. Кидаю базу в assets (меня смутило, что не было этой папки в Android Studio 1.5.1 — создал с помощью New/ Assets Folder).

Использую этот код. Тестирую на Android 4.1

Отслеживать
задан 3 фев 2016 в 15:24
Denis Ivanov Denis Ivanov
45 1 1 серебряный знак 4 4 бронзовых знака
Возможно разрешения не хватает на чтение с диска в манифесте.
3 фев 2016 в 16:09
@ЮрийСПб, про разрешения совсем забыл
3 фев 2016 в 19:44

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

  1. Положил БД в папку assets
  2. У меня есть класс для работы с БД import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;

import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper;

public class ExternalDbOpenHelper extends SQLiteOpenHelper

//Путь к папке с базами на устройстве public static String DB_PATH; //Имя файла с базой public static String DB_NAME; public SQLiteDatabase database; public final Context context; //private boolean flagdel = true; public SQLiteDatabase getDb() < return database; >public ExternalDbOpenHelper(Context context, String databaseName) < super(context, databaseName, null, 1); this.context = context; //Составим полный путь к базам для нашего приложения DB_PATH = context.getDatabasePath(databaseName).getAbsolutePath(); DB_NAME = databaseName; openDataBase(); >/**Создаст базу, если она не создана и откроет ее*/ public void createDataBase() < boolean dbExist = checkDataBase(); if (!dbExist) < this.getReadableDatabase();//Создает и/или открывает базу данных try catch (IOException e) < throw new Error("Error copying database!"); >> > /**Проверка существования базы данных*/ private boolean checkDataBase() < SQLiteDatabase checkDb = null; String path = DB_PATH + DB_NAME; try < checkDb = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY); >catch (SQLiteException e) <> //Андроид не любит утечки ресурсов, все должно закрываться if (checkDb != null) checkDb.close(); return checkDb != null; > /**метод проверки наличия в БД таблицы*/ public boolean checkTableInDB(String nameTable)< boolean result = false; Cursor cur = database.query("sqlite_master", new String[], "type=? AND name=?", new String[], null, null, null); cur.moveToLast(); if(cur.getCount()>0) result = true; cur.close(); return result; > /**метод проверки наличия поля в таблице*/ public boolean checkFieldInTable(String nameTable, String nameField)< boolean result = false; try< Cursor cur = database.rawQuery("PRAGMA table_info('"+nameTable+"')", null); cur.moveToFirst(); while(!cur.isAfterLast()) < String name = ""; trycatch(IllegalArgumentException e)<> if(name.equals(nameField)) < result = true; break; >cur.moveToNext(); > cur.close(); cur = null; >catch(SQLException e)<> return result; > /**Метод копирования базы*/ private void copyDataBase() throws IOException < // Открываем поток для чтения из уже созданной нами БД источник в assets InputStream externalDbStream = context.getAssets().open(DB_NAME); // Путь к уже созданной пустой базе в андроиде String outFileName = DB_PATH + DB_NAME; // Теперь создадим поток для записи в эту БД побайтно OutputStream localDbStream = new FileOutputStream(outFileName); // Собственно, копирование byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = externalDbStream.read(buffer)) >0) < localDbStream.write(buffer, 0, bytesRead); >// Мы будем хорошими мальчиками (девочками) и закроем потоки localDbStream.close(); externalDbStream.close(); > /** Метод получения всех данных из таблицы*/ public Cursor getAllData(String dbTable) < return database.query(dbTable, null, null, null, null, null, null); >/** Метод получения данных из таблицы по условию*/ public Cursor getDataByWhere(String table, String[] columns, String where, String[] where_args) < return database.query(table, columns, where, where_args, null, null, null); >/**Метод открытия БД*/ public SQLiteDatabase openDataBase() throws SQLException < String path = DB_PATH + DB_NAME; if (database == null) < createDataBase(); database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE); >return database; > @Override public synchronized void close() < if (database != null) < database.close(); >super.close(); > @Override public void onCreate(SQLiteDatabase db) <> @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) <> 

    Получаю данные в любом нужном мне месте кода. Ниже метод получения данных. Смысл в том, что если БД с определенной версией не найдена, то она будет скопирована в папку с установленным приложением и далее получена на нее ссылка с дальнейшим использованием. Очень удобно. Советую.

private void getDataFromDB()< ExternalDbOpenHelper dbOpenHelper = new ExternalDbOpenHelper(context, DB_NAME); SQLiteDatabase db = dbOpenHelper.getDb(); String orderby = MeData.getOrderBy(); String table = (!mode.equals(MODE_PREV))?MeData.getTable():MeData.getTable_prev(); String columns[] = MeData.getColumns(); Cursor cur = null; trycatch(Exception e) < if(cur != null) cur.close(); cur= null; if(db != null) db.close(); db = null; if(dbOpenHelper != null) dbOpenHelper.close(); dbOpenHelper = null; return; >cur.moveToFirst(); while(!cur.isAfterLast()) < try< int ND = cur.getInt(cur.getColumnIndex("ND")); int NM = cur.getInt(cur.getColumnIndex("NM")); int NY = cur.getInt(cur.getColumnIndex("NY")); >catch(Exception e) <> cur.moveToNext(); > if(cur != null) cur.close(); cur= null; if(db != null) db.close(); db = null; if(dbOpenHelper != null) dbOpenHelper.close(); dbOpenHelper = null; 

P.S. Не могу толком вставить код. прошу прощения, разберетесь.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *