Здравствуй, дорогой читатель!
В этой статье я хочу затронуть проблему хранения кириллических данных в SQLite, попробовать разобраться с Android NDK, и вообще зажить прекрасной жизнью! Однако, с этого момента, считаю важными первые два пункта. О них и поговорим.
Известная проблема SQLite состоит в том, что он не любит никаких символов, кроме латинских, поэтому выполняется такое [1]:
SELECT "ы" LIKE "Ы";
0
SELECT "s" LIKE "S";
1
Такая проблема актуальна для наших широт, и может быть решена пользовательскими функциями.
Но Android не поддерживает функций, поэтому создаются костыли.
Android NDK
Чтобы расширить твой кругозор, дорогой читатель, а так же создать годные костыли, я предлагаю использовать Android NDK [2] (скачайте и распакуйте в доступную папку)
Немного скучного
Android NDK — это иструмент для компилирования C/C++ кода в нативный код платформы Android. Кроме того, предоставляются многие библиотеки Android, так что определенные интенсивные участки программы можно написать в C/C++, а затем использовать в Java.
NDK поддерживается начиная с Android 1.5, и в данный момент поддерживаются следующие архитектуры процессоров ARMv5TE (включая инструкции Thumb-1), ARMv7-A (включая инструкции Thumb-2 и VFPv3-D16, с опциональной поддержкой NEON/VFPv3-D32)
Будущие релизы обещают поддержку x86
Короче, воспользуемся же этим инструментом!
Итак...
Что мы будем делать? Будем объединять исходный код sqlite и icu.
Дабы не нагружать процесс поиском нужных библиотек и исходников, предлагается собранный комплект для компиляции, здесь [3]. Прошу прощения, если случайно включено что-то лишнее.
Если вас не интересует процесс компиляции, вы можете скачать скомпилированную библиотеку здесь [7], и пропустить несколько пунктов
Скачав файл, распаковываем, и размещаем это драгоценное в ваш проект
project/jni
Где project здесь и далее — полный пусть до проекта
Прежде, чем перейти к шагу компиляции, хочу обратить ваше внимание на структуру некоторых файлов.
common/Android.mk
Здесь описываются все исходные файлы, подключаемые в будущую библиотеку, различные флаги и параметры сборки
common/android_sqlite...
Эти файлы осуществляют андроидоподобный доступ к базе, а так же интерфейс для взаимодействия с базой из Java.
Обратите внимание на сигнатуры функций
void Java_biz_sneg_sqlite_SQLiteDatabase_closedb()
Чтобы успешно использовать нативные функции, нужно описать их в формате
Java_имя_пакета_класс_имяФункции
Так же я включил функцию определения географического расстояния GEODISTANCE(x1, y1, x2, y2), потому что, лично мне, ее не хватало.
Теперь легко подключить свои нужные функции, будь то sin, cos или ваши экзотические
Компиляция и подключение библиотеки
Сначала опишу шаги для Windows, потому как решение в лоб не работает.
Делай раз! Скачиваем и устанавливаем Cygwin [6], при установке выбираем пакеты Devel для установки. И… временно удаляемся на сон или другие приятные дела, потому что это адски долго. Хотя, возможно, я просто выбрал неправильный сервер.
Делай два! Запускаем консоль Cygwin (просто консоль для других ОС) и переходив в директорию с проекта:
Windows:
$ cd /cygdrive/project/jni
Non-windows:
$ cd project/jni
Делай три! Запускаем NDK
Windows:
$ /cygdrive/ndk-path/ndk-build
Non-windows:
$ ndk-path/ndk-build
Где project — путь к вашему проекту, ndk-path — путь, куда вы распаковали NDK
Должен запуститься процесс компиляции:
...
Compile++ thumb : android_sqlite <= tmutfmt.cpp
Compile++ thumb : android_sqlite <= colldata.cpp
Compile++ thumb : android_sqlite <= bmsearch.cpp
Compile++ thumb : android_sqlite <= bms.cpp
Compile++ thumb : android_sqlite <= currpinf.cpp
Compile++ thumb : android_sqlite <= uspoof.cpp
Compile++ thumb : android_sqlite <= uspoof_impl.cpp
...
Если не запустился — сочувствую О_о
На выходе мы должны получить скомпилированную библиотеку, по пути project/libs/armeabi/libandroid_sqlite.so
Теперь нам нужно подключить библиотеку к проекту.
Во-первых, в главном Activity мы должны описать ее подключение
public class MainActivity extends TabActivity {
static {
System.loadLibrary("android_sqlite");
}
...
}
Далее, нам нужен код, который бы работал с нативной библиотекой, и его можно скачать здесь [4]
Как работать?
Как, как, сели и поехали!
Открываем базу
try
{
dataBase_ = new biz.sneg.sqlite.SQLiteDatabase(DB_NAME);
}
catch (Exception e) {
Log.wtf("Database", e);
}
Достаем данные как-нибудь так, или как вам нравится
try {
biz.sneg.sqlite.SQLiteCursor cursor =
dataBase_.query("SELECT * FROM tablename WHERE rus_text_field LIKE ?", new Object[]{"ура%"});
List<Map<String, String>> results = new ArrayList<Map<String,String>>();
while (cursor.next())
{
final int columnCount = cursor.count();
HashMap<String, String> currentMap;
currentMap = new HashMap<String, String>();
for (int i = 0; i < columnCount; i++)
{
currentMap.put(cursor.columnName(i), cursor.stringValue(i));
}
results.add(currentMap);
}
cursor.dispose();
}
catch (Exception e) {
Log.wtf("Database", e);
}
В общем, желаю удачи!
Автор идеи и сборки Николай Кудашов, инвайт можно прислать сюда drklo.2kb<известный_символ>gmail.com
Ссылки:
1. SQLite и полноценный UNICODE
2. Android NDK
3. Исходники для библиотеки
4. Исходники для java
5. SQLite
6. Cygwin
7. Скомпилированная библиотека