Отладка базы данных sqlite на устройстве

78

В настоящее время я работаю над приложением WiFi для Android. У меня возникли проблемы с попыткой доступа к базе данных на устройстве. Отладка в эмуляторе не работает для меня, потому что в эмуляторе нет поддержки WiFi. Я попытался вытащить файл базы данных из устройства с помощью

adb pull data/data/package-name/databases/database-name

Но я получаю сообщение об ошибке "Permission denied.". В этом ответе Android: Где хранятся файлы базы данных?, Commonsware предложила вытащить файл базы данных, запустив его в режиме отладки. Но это тоже не работает. Любая помощь в том, как отлаживать базу данных без укоренения устройства, будет очень признательна.

Теги:
adb

13 ответов

124
Лучший ответ

Повторюсь из другого ответа:

Начиная с уровня API 8 (Android 2.2), если вы создаете приложение как отладочное, вы можете использовать команду shell run-as для запуска команды или исполняемого файла в качестве конкретного пользователя/приложения или просто переключиться на UID вашего приложения, чтобы вы могли получить доступ к его каталогу данных.

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

run-as com.yourpackage sh -c "cat ~/databases/db-file" > /sdcard/db-file.sqlite

Это скопирует ваш db-file в корень вашей SD-карты/внешнего хранилища. Теперь вы можете легко получить его оттуда с помощью файлового менеджера adb pull или всего, что вам нравится. Обратите внимание, что при таком подходе нет необходимости в вашем приложении иметь разрешение WRITE_EXTERNAL_STORAGE, так как копирование выполняется пользователем оболочки, который всегда может писать во внешнюю память.

В системах Linux/Mac есть возможность скопировать базу данных непосредственно на ваш компьютер с помощью следующей команды, которую можно использовать без ввода оболочки adb:

adb shell 'run-as com.yourpackage sh -c "cat ~/databases/db-file"' > db-file.sqlite

Это, однако, не будет корректно работать в Windows из-за преобразования символов CR/LF. Используйте там прежний метод.

  • 0
    @ Идолон, я попробовал этот ответ и смог загрузить базу данных, но теперь, когда я пытаюсь открыть ее с помощью sqlite, выдается ошибка «Ошибка: файл зашифрован или не является базой данных». Любые идеи, как я могу это исправить и доступ через sqlite?
  • 1
    @MikeIsrael На всякий случай, вы не используете SQLCipher в своем приложении, не так ли? Если нет, то для грубой проверки, была ли загружена база данных правильно, откройте файл DB в программе просмотра (предпочтительно hex-viewer) и убедитесь, что он начинается со строки SQLite format 3 . Также убедитесь, что у вас правильная версия sqlite (т.е. вы не пытаетесь открыть базу данных sqlite3 с помощью исполняемого файла sqlite2). И вы также можете попробовать другие клиенты SQLite (например, SQLiteStudio ). Надеюсь, поможет.
Показать ещё 22 комментария
20

Я использую эту оболочку script на моем MAC-адресе, которая копирует базу данных непосредственно в мою домашнюю папку. Простое решение одним кликом, просто измените имя пакета (com.example.app) и имя базы данных (database.sqlite)

Простой Script

#!/bin/bash
adb -d shell 'run-as com.example.app cat /data/data/com.example.app/databases/database.sqlite > /sdcard/database.sqlite'
adb pull /sdcard/database.sqlite ~/

Script, который принимает аргументы [имя_пакета] [база данных]

#!/bin/bash

REQUIRED_ARGS=2
ADB_PATH=/Users/Tadas/Library/sdk/platform-tools/adb
PULL_DIR="~/"

if [ $# -ne $REQUIRED_ARGS ]
    then
        echo ""
        echo "Usage:"
        echo "android_db_move.sh [package_name] [db_name]"
        echo "eg. android_db_move.sh lt.appcamp.impuls impuls.db"
        echo ""
    exit 1
fi;


echo""

cmd1="$ADB_PATH -d shell 'run-as $1 cat /data/data/$1/databases/$2 > /sdcard/$2' "
cmd2="$ADB_PATH pull /sdcard/$2 $PULL_DIR"

echo $cmd1
eval $cmd1
if [ $? -eq 0 ]
    then
    echo ".........OK"
fi;

echo $cmd2
eval $cmd2

if [ $? -eq 0 ]
    then
    echo ".........OK"
fi;

exit 0
  • 0
    Обновленный пост - Добавлен универсальный скрипт bash, который принимает аргументы [имя_пакета] [имя_базы_данных]
  • 0
    Gist создан: gist.github.com/jromero/8939416
Показать ещё 1 комментарий
12

Лучший способ просмотра и управления вашей базой данных приложений Android - использовать эту библиотеку https://github.com/sanathp/DatabaseManager_For_Android

С помощью этой библиотеки вы можете управлять своей базой данных SQLite приложения непосредственно из своего приложения. вы можете просматривать таблицы в своей базе данных приложений, обновлять, удалять, вставлять строки в свои таблицы. Все, что из вашего приложения.

Его единственный файл активности java, просто добавьте java файл в исходную папку. После завершения разработки удалите java файл из вашей папки src.

Это очень помогло мне. Надеюсь, это тоже поможет.

Вы можете посмотреть 1-минутную демонстрацию здесь: http://youtu.be/P5vpaGoBlBY

  • 2
    Очень похож на человека, его очень полезно увидеть в нашем DbEntry. Его модификация является бонусом.
  • 1
    Невероятно! Лучшее решение.
Показать ещё 1 комментарий
5

Если вы получаете

The system cannot find the path specified.

попробовать

adb -d shell "run-as com.yourpackage cat /data/data/com.yourpackage/databases/dbname.sqlite > /sdcard/dbname.sqlite"

Обратите внимание на двойную кавычку!

5

В моем приложении я экспортирую базу данных на SD-карту. После того, как база данных находится на SD-карте, ее можно получить, подключив устройство к компьютеру.

Посмотрите на это сообщение: Создание резервной копии базы данных на SDCard на Android

  • 0
    Это похоже на единственный обходной путь. Какой-нибудь конкретный урок, который тебе помог?
  • 0
    Я посмотрел на несколько разных уроков. Тот, который я перечислил выше, был самым полезным. Пожалуйста, отметьте этот ответ как правильный, если он вам помог. Я был бы рад предложить дополнительную поддержку в случае необходимости.
3

Я просто сделал:

$ adb shell
shell@android:/ $ run-as myapp.package.name sh
shell@android:/data/data/myapp.package.name $

Затем я могу отлаживать базу данных sqlite или все, что я хочу сделать из оболочки с правильными разрешениями.

2

Вот пошаговые инструкции - в основном, взятые из комбинации других ответов. Это работает с устройствами, которые не разблокированы.

  • Подключите устройство и запустите приложение в режиме отладки.

  • Скопируйте файл базы данных из папки вашего приложения на вашу SD-карту: выполните:

    ./adb -d shell 'run-as com.yourpackge.name cat/data/data/com.yourpackge.name/databases/filename.sqlite > /sdcard/filename.sqlite'

  • Потяните файлы базы данных на свой компьютер: выполните:

    ./adb pull/sdcard/execute:./adb

  • Установите Firefox SQLLite Manager: https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/

  • Откройте Firefox SQLLite Manager и откройте файл базы данных с шага 3 выше.

  • Наслаждайтесь!

2

Существует способ, если apk отлаживается для использования программы, называемой run-as из оболочки (non-root) adb, для копирования закрытого файла приложения.

1

У моего устройства не было sdcard

, поэтому первое решение не сработало для меня.

Если у вас такая же проблема, попробуйте вот так:

  adb shell "run-as package chmod 777 /data/data/package/databases/yourdb.sqlite";
  adb pull /data/data/package/databases/yourdb.sqlite
  • 0
    /sdcard не обязательно SD-карта. На моем телефоне он указывает на внутреннюю память, когда нет физической SD-карты.
1

Ни один из решений run-as -and-cat-to-sdcard не работал на Android 4.4.2. Я не уверен, но я подозреваю, что это может быть из-за того, что инструмент run-as неправильно обрабатывает новые разрешения sdcard_r и sdcard_rw.

Сначала мне пришлось скопировать файл базы данных в /files в мое личное хранилище приложений:

shell@hammerhead:/ $ run-as com.example.myapp   
shell@hammerhead:/data/data/com.example.myapp $ cp databases/mydb files/mydb

Затем я скопировал в /sdcard/Android/data/com.example.myapp/files в Javaland (для этого требуется разрешение WRITE_EXTERNAL_STORAGE):

public class MainActivity extends BaseActivity {

    @Override
     protected void onCreate(Bundle savedInstanceState) {
         ...

         if (isExternalStorageWritable()) {
             final FileInputStream input;
             try {
                 input = openFileInput("mydb");

                 File output = new File(getExternalFilesDir(null), "mydb");

                 copy(input, output);
             } catch (FileNotFoundException e) {
                 e.printStackTrace();
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }

     public void copy(FileInputStream in, File dst) throws IOException {
         OutputStream out = new FileOutputStream(dst);

         // Transfer bytes from in to out
         byte[] buf = new byte[1024];
         int len;
         while ((len = in.read(buf)) > 0) {
             out.write(buf, 0, len);
         }
         in.close();
         out.close();
     }

     public boolean isExternalStorageWritable() {
         String state = Environment.getExternalStorageState();
         return Environment.MEDIA_MOUNTED.equals(state);
     }
 }

Наконец, я скопировал файл на свой ноутбук:

$ adb pull /sdcard/Android/data/com.example.myapp/files/mydb
  • 1
    Есть более простое решение. Если вы выполните chmod 777 для вашего sqlite-файла, а затем выйдите из run-as, он позволит вам скопировать его в / sdcard как обычный пользователь.
1

Вам нужно запустить adb как root или использовать его на корневом телефоне.

Чтобы запустить adb с правами root, используйте adb root

Смотрите также: Почему я получаю доступ к папке с данными при использовании adb?

  • 0
    Я попробовал это. Но это дает мне "ADB не может работать как root в производственных сборках"
  • 0
    Вам нужно будет запустить его в режиме отладки.
Показать ещё 3 комментария
0

В OSX, используя @Tadas ответ с помощью automator и sqllitebrowser (https://github.com/sqlitebrowser/sqlitebrowser):

  • откройте Automator и создайте новый рабочий процесс.

  • добавить действие "Run Shell Script".

  • Вставьте это:

    источник ~/.bash_profile adb shell 'run-as cat/data/data/your_app_uid/databases/db.name > /tmp/db.name' adb pull/tmp/db.name ~/ open -a sqlitebrowser ~/db.name

  • нажмите, чтобы обновить базу данных на sqlitebrowser.

0

Попробуйте это приложение: SQLiteWeb (https://play.google.com/store/apps/details?id=br.com.cm.sqliteweb). Он обеспечивает удаленный доступ к вашей базе данных, не вытаскивая его.

В платной версии он имеет корневой доступ для частной базы данных (/data/data/package-name...) или реализует Content Provider для подключения с помощью SQLiteWeb (инструкции внутри приложения)

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

database = SQLiteDatabase.openDatabase(Environment.getExternalStorageDirectory()
        + "/" + DATABASE_NAME, null, DATABASE_VERSION);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню