Цель
Я хочу реализовать геозону в своем приложении, но мне нужно поддерживать фильтрацию по этим геозонам на основе их близости к пользователю.
Подход
Шаги приняты
Модуль R * Tree отключен для SQLite на Android. Чтобы исправить это, вам нужно добавить собственную библиотеку SQLite в ваш проект.
Существует несколько вариантов для добавления привязок Android в пользовательскую библиотеку SQLite.
Первый вариант не отвечал моим потребностям, и добавление исходного кода является последним средством, которое не должно разрешать мои текущие проблемы.
Я выбрал второй параметр и включил модуль R * Tree, установив -DSQLITE_ENABLE_RTREE
в 1 в src/main/java/jni/sqlite/Android.mk
:
# Enable SQLite extensions.
LOCAL_CFLAGS += -DSQLITE_ENABLE_FTS5
LOCAL_CFLAGS += -DSQLITE_ENABLE_RTREE=1
LOCAL_CFLAGS += -DSQLITE_ENABLE_JSON1
LOCAL_CFLAGS += -DSQLITE_ENABLE_FTS3
Я также выполнил шаг 3 и добавил вывод в свой проект, добавив .aar в папку libs.
build.gradle
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
// other dependencies
}
другие файлы кода
Импорт был обновлен, и библиотека была загружена, как этот документ определяет.
Методы оскорбления
Эти методы используются для взаимодействия с уже существующей таблицей, в которой не используется модуль R * Tree.
static List<LocationInterface> getSince(SQLiteDatabase database, long millisecondsSince1970) {
if (database == null) {
return null;
}
Cursor cursor = null;
try {
cursor = database.query(TABLE_NAME, null, LocationTable.COLUMN_CREATED_AT + " > " + millisecondsSince1970,
null, null, null, LocationTable.COLUMN_CREATED_AT, QUERY_LIMIT);
if (cursor == null || cursor.isClosed()) {
return null;
}
// cursor is closed at the end of the function
return getLocations(cursor);
} finally {
if (cursor != null) {
cursor.close();
}
database.close();
}
}
static void deleteBefore(SQLiteDatabase database, long millisecondsSince1970) {
database.delete(TABLE_NAME, LocationTable.COLUMN_CREATED_AT + " <= " + millisecondsSince1970, null);
database.close();
}
private static List<LocationInterface> getLocations(Cursor cursor) {
List<LocationInterface> locations = null;
if (cursor.moveToFirst()) {
locations = new ArrayList<>();
do {
if (cursor.isClosed()) {
break;
}
// Creates a LocationInterface object, does not modify cursor
locations.add(getLocationFromCursor(cursor));
} while (cursor.moveToNext());
}
cursor.close();
return locations;
}
импорт подержанных
import android.content.ContentValues;
import android.database.Cursor;
import org.sqlite.database.sqlite.SQLiteDatabase;
import org.sqlite.database.sqlite.SQLiteStatement;
SQLiteOpenHelper
Существует специальная реализация для SQLiteOpenHelper, которая реализуется с помощью шаблона проектирования Singleton.
Мы используем этот класс, который, в свою очередь, использует контекст приложения контекста первого вызывающего, чтобы получить нашу читаемую базу данных с возможностью записи.
final class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper instance;
private static final String DATABASE_NAME = "myDatabase.db";
private static final int DATABASE_VERSION = 4;
public static synchronized DatabaseHelper getInstance(Context context) {
if (instance == null) {
instance = new DatabaseHelper(context.getApplicationContext());
}
return instance;
}
private DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
LocationTable.createIfRequired(db);
GeofenceContract.createIfRequired(db);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
LocationTable.upgrade(db, oldVersion, newVersion);
GeofenceContract.upgrade(db, oldVersion, newVersion);
}
}
проблема
База данных не может быть открыта.
StackTrace
09-05 17:45:35.575 28508-28615/com.example.android.demo E/SQLiteLog: (14) cannot open file at line 37631 of [c7ee083322]
(14) os_unix.c:37631: (2) open(//myDatabase.db) -
09-05 17:45:35.576 28508-28615/com.example.android.demo E/SQLiteDatabase: Failed to open database 'myDatabase.db'.
org.sqlite.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at org.sqlite.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:214)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
at org.sqlite.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:466)
at org.sqlite.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:188)
at org.sqlite.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:180)
at org.sqlite.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:810)
at org.sqlite.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:795)
at org.sqlite.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:698)
at org.sqlite.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:721)
at org.sqlite.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:259)
at org.sqlite.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:223)
at com.example.sdk.core.ExampleDatabase.getSince(ExampleDatabase.java:64)
at com.example.sdk.core.LocationDispatcher.postLocations(LocationDispatcher.java:41)
at com.example.sdk.core.DispatchWorker.sendLocations(DispatchWorker.java:74)
at com.example.sdk.core.DispatchWorker.doWork(DispatchWorker.java:49)
at androidx.work.Worker.onStartWork(Worker.java:70)
at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:195)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:117)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
09-05 17:45:35.625 28508-28615/com.example.android.demo E/SQLiteOpenHelper: Couldn\'t open myDatabase.db for writing (will try read-only):
org.sqlite.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at org.sqlite.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:214)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
at org.sqlite.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:466)
at org.sqlite.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:188)
at org.sqlite.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:180)
at org.sqlite.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:810)
at org.sqlite.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:795)
at org.sqlite.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:698)
at org.sqlite.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:721)
at org.sqlite.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:259)
at org.sqlite.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:223)
at com.example.sdk.core.ExampleDatabase.getSince(ExampleDatabase.java:64)
at com.example.sdk.core.LocationDispatcher.postLocations(LocationDispatcher.java:41)
at com.example.sdk.core.DispatchWorker.sendLocations(DispatchWorker.java:74)
at com.example.sdk.core.DispatchWorker.doWork(DispatchWorker.java:49)
at androidx.work.Worker.onStartWork(Worker.java:70)
at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:195)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:117)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
09-05 17:45:35.817 28508-28615/com.example.android.demo E/DispatchWorker: No locations sentserver
09-05 17:45:35.817 28508-28615/com.example.android.demo E/SQLiteLog: (14) cannot open file at line 37631 of [c7ee083322]
(14) os_unix.c:37631: (2) open(//myDatabase.db) -
09-05 17:45:35.823 28508-28615/com.example.android.demo E/SQLiteDatabase: Failed to open database 'myDatabase.db'.
org.sqlite.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at org.sqlite.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:214)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
09-05 17:45:35.824 28508-28615/com.example.android.demo E/WorkerWrapper: Work [ id=2cc7ccee-72c9-4178-a6ce-891ef3696faa, tags={ Example_dispatch_work, com.example.sdk.core.DispatchWorker } ] failed because it threw an exception/error
org.sqlite.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at org.sqlite.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:214)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
at org.sqlite.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:466)
at org.sqlite.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:188)
at org.sqlite.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:180)
at org.sqlite.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:810)
at org.sqlite.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:795)
at org.sqlite.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:698)
at org.sqlite.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:721)
at org.sqlite.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:259)
at org.sqlite.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:199)
at com.example.sdk.core.ExampleDatabase.deleteBefore(ExampleDatabase.java:73)
at com.example.sdk.core.DispatchWorker.sendLocations(DispatchWorker.java:96)
at com.example.sdk.core.DispatchWorker.doWork(DispatchWorker.java:49)
at androidx.work.Worker.onStartWork(Worker.java:70)
at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:195)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:117)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
09-05 17:45:42.069 28508-28616/com.example.android.demo E/SQLiteLog: (14) cannot open file at line 37631 of [c7ee083322]
(14) os_unix.c:37631: (2) open(//myDatabase.db) -
09-05 17:45:42.121 28508-28616/com.example.android.demo E/SQLiteDatabase: Failed to open database 'myDatabase.db'.
org.sqlite.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at org.sqlite.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:214)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
09-05 17:45:42.171 28508-28616/com.example.android.demo E/SQLiteOpenHelper: Couldn\'t open myDatabase.db for writing (will try read-only):
org.sqlite.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at org.sqlite.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:214)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
09-05 17:45:42.425 28508-28616/com.example.android.demo E/DispatchWorker: No locations sentserver
09-05 17:45:42.474 28508-28616/com.example.android.demo E/SQLiteLog: (14) cannot open file at line 37631 of [c7ee083322]
(14) os_unix.c:37631: (2) open(//myDatabase.db) -
09-05 17:45:42.475 28508-28616/com.example.android.demo E/SQLiteDatabase: Failed to open database 'myDatabase.db'.
org.sqlite.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at org.sqlite.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:214)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
09-05 17:45:42.516 28508-28616/com.example.android.demo E/WorkerWrapper: Work [ id=2c27be2a-94c9-4bca-a63a-34133bb7e7dd, tags={ Example_dispatch_work, com.example.sdk.core.DispatchWorker } ] failed because it threw an exception/error
org.sqlite.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at org.sqlite.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:214)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
09-05 17:45:43.914 28508-28616/com.example.android.demo E/SQLiteLog: (14) cannot open file at line 37631 of [c7ee083322]
(14) os_unix.c:37631: (2) open(//myDatabase.db) -
09-05 17:45:43.915 28508-28616/com.example.android.demo E/SQLiteDatabase: Failed to open database 'myDatabase.db'.
org.sqlite.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at org.sqlite.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:214)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
09-05 17:45:43.916 28508-28616/com.example.android.demo E/SQLiteOpenHelper: Couldn\'t open myDatabase.db for writing (will try read-only):
org.sqlite.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at org.sqlite.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:214)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
09-05 17:45:44.063 28508-28616/com.example.android.demo E/DispatchWorker: No locations sentserver
09-05 17:45:44.063 28508-28616/com.example.android.demo E/SQLiteLog: (14) cannot open file at line 37631 of [c7ee083322]
(14) os_unix.c:37631: (2) open(//myDatabase.db) -
09-05 17:45:44.065 28508-28616/com.example.android.demo E/SQLiteDatabase: Failed to open database 'myDatabase.db'.
org.sqlite.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at org.sqlite.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:214)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
09-05 17:45:44.066 28508-28616/com.example.android.demo E/WorkerWrapper: Work [ id=d128fc77-b562-4da8-8a28-8e74d071f168, tags={ Example_dispatch_work, com.example.sdk.core.DispatchWorker } ] failed because it threw an exception/error
org.sqlite.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at org.sqlite.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:214)
at org.sqlite.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:198)
Попытки решения
- Используется
libsqliteX
для имени библиотеки для импорта вместо sqliteX
- Закрытая база данных после каждой операции (команда
SELECT
или INPUT
). Применяется через try - finally
.
- Добавлено разрешение
WRITE_EXTERNAL_STORAGE
.
- Много «чистых сборок»
- Перекомпилирована библиотека SQLite снова.
Вопрос
Я что-то забыл? Что нужно проверить и знать при компиляции библиотеки SQLite с пользовательскими расширениями?
В чем корень моей проблемы?