вторник, 28 июня 2016 г.

SQLite3. Как собрать бинарник под Android?

В этой небольшой заметке я расскажу вам как собрать бинарник консольной утилиты SQLite3 под Android из исходников на ПК с Windows. Зачем это вообще может понадобиться обычному человеку? Ну например ... как вы знаете приложения под Android используют в своей работе SQLite базы данных, так, например, настройки каждого приложения хранятся в папке приложения в разделе /data в соответствующем .db файле и иногда хочется иметь консольное средство для редактирования подобных баз данных. Например, для случая когда нам нужно изменить что-то в БД, а под рукой только сам телефон с Android и т.п., или же, например, для автоматизации выполнения каких-то действий (например, ну первый условный пример, который мне только что пришел в голову, для переключения режимов 2G/3G из консоли или любой другой подобной задачи, в которой требуется непосредственное изменение данных в таблицах SQLite базы данных ... ) Более простой пример, например, изменение настроек графического ключа (его отключение), непосредственно из кастомного recovery.

Если вы периодически читали мой блог, то наверняка видели статью, в которой мы собирали Hello World в виде бинарника под Anroid используя только Android NDK. Т.е. это было простое приложение в формате исполняемого ELF-файла, которое выводило на экран строку Hello, World! Если вы не читали этот пост, то ознакомиться с ним можно здесь - ANDROID HELLO WORLD. Так вот, сборка SQLite практически ничем не отличается от того что там описано, единственное, вам придется сделать свой Android.mk для сборки, ну или взять его здесь.

Итак, по шагам ... что мы делаем. Проекты для NDK у меня лежат в папке D:\ARM. Создаем еще одну папку sqlite в папке ARM. В ней создаем папку build, куда качаем исходники SQLite - sqlite-snapshot-201606031859.tar.gz c официального сайта. Т.е. в папке Build у нас получается примерно следующее:

Затем в папке Sqlite создаем папку Jni и в ней два файла, Application.mk с содержимым:

APP_ABI := armeabi

И Android.mk с содержимым:

LOCAL_PATH := $(call my-dir)

#
# Statically Linked
#

include $(CLEAR_VARS)
LOCAL_MODULE            := sqlite3-a
LOCAL_MODULE_FILENAME   := libsqlite3
LOCAL_SRC_FILES         := ../build/sqlite3.c
LOCAL_C_INCLUDES        := ../build
LOCAL_EXPORT_C_INCLUDES := ../build
LOCAL_CFLAGS            := -DSQLITE_THREADSAFE=1
include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE            := sqlite3-static-cli
LOCAL_MODULE_FILENAME   := sqlite3-static
LOCAL_STATIC_LIBRARIES  := libsqlite3-a
LOCAL_SRC_FILES         := ../build/shell.c ../build/sqlite3.c
LOCAL_C_INCLUDES        := ../build
LOCAL_EXPORT_C_INCLUDES := ../build
LOCAL_CFLAGS            := -DSQLITE_THREADSAFE=1 -fPIE
LOCAL_LDFLAGS           := -fPIE -pie
include $(BUILD_EXECUTABLE)

#
# Dynamically Linked
#

include $(CLEAR_VARS)
LOCAL_MODULE            := sqlite3-so
LOCAL_MODULE_FILENAME   := libsqlite3
LOCAL_SRC_FILES         := ../build/sqlite3.c
LOCAL_C_INCLUDES        := ../build
LOCAL_EXPORT_C_INCLUDES := ../build
LOCAL_CFLAGS            := -DSQLITE_THREADSAFE=1
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE            := sqlite3-dynamic-cli
LOCAL_MODULE_FILENAME   := sqlite3-dynamic
LOCAL_SHARED_LIBRARIES  := libsqlite3-so
LOCAL_SRC_FILES         := ../build/shell.c ../build/sqlite3.c
LOCAL_C_INCLUDES        := ../build
LOCAL_EXPORT_C_INCLUDES := ../build
LOCAL_CFLAGS            := -DSQLITE_THREADSAFE=1 -fPIE
LOCAL_LDFLAGS           := -fPIE -pie
include $(BUILD_EXECUTABLE)

Далее в папке Sqlite создаем сценарий для сборки compile.cmd :

set NDK_PROJECT_PATH=%~dp0 
cd D:\ARM\android-ndk-r10d\
call ndk-build.cmd 
cd "%NDK_PROJECT_PATH%"

Где android-ndk-r10d - это папка с установленным NDK. После чего запускаем его. Если вы все сделали верно, то в папке D:\ARM\sqlite\libs\armeabi\ у вас появятся три собранные файла:

  • libsqlite3.so
  • sqlite3-dynamic
  • sqlite3-static
Далее берем sqlite3-static и копируем его через ADB на телефон. Я проводил опыты со своим Alcatel Idol 3 с Android 6.0.1 с установленным root:

adb push sqlite3-static /data/local/tmp - копируем файл в /data/local/tmp
adb shell chmod 777 /data/local/tmp/sqlite3-static - присваиваем ему необходимые права

Далее набираем adb shell и уже там в консоли:

su
/data/local/tmp/sqlite3-static
.open /data/data/com.tct.launcher/databases/launcher.db (здесь данный файл взят просто ради примера, вы же можете открыть любой существующий db файл в вашем аппарате)
.tables (для просмотра таблиц этой БД)
select * from sqlite_master where type = 'table'; (ну или например так, для просмотра списка таблиц через SQL запрос)

Таким образом мы рассмотрели как собрать SQLite из исходников и простейший пример как работать с ним. Более подробную информацию о командах SQLite вы можете найти здесь - Command Line Shell For SQLite.

Ниже вы можете найти как статически, так и динамически собранные бинарники для следующих архитектур (все бинарники собраны с поддержкой PIE):
  • armeabi
  • armeabi-v7a
  • arm64-v8a
  • mips
  • mips64
  • x86
  • x86_64

Полезные ссылки (больше в качестве заметок для себя же)

2 комментария :

  1. Т.е. как я понял из статьи, то можно при помощи данного метода, слить с телефона db файл отвечающий за графический ключ, отключить его, и опять залить в телефон. Объясню вопрос принесли htc one touch заблокированный, жена пыталась попасть в телефон мужа и вуаля)))). factory reset - потеря всех контактов и фото на телефоне.

    ОтветитьУдалить
  2. Спасибо за статью. Очень полезно.
    Можешь подсказать, что необходимо поменять, чтобы получить so файл под x86 процессор на android?

    ОтветитьУдалить