Сохранение одной и той же базы данных SQLite при обновлении и Android-приложение от версии Lite до Pro

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

Я пишу свое первое приложение для Android и планирую иметь версию Lite (ограниченные возможности) и платную версию (полные функции).

В версии Lite и Pro будет использоваться одна и та же структура базы данных SQLite, и если пользователь начнет с версии Lite и обновит до версии Pro, я не хочу, чтобы они потеряли данные, которые они создали в версии Lite.

Как версии Lite и Pro (по моему мнению) должны быть в отдельных пакетах, чтобы позволить Android Market различать их, как версия Pro может видеть базу данных Lite?

Большое спасибо за ваши ответы.

Ответы

Ответ 1

То, что я сделал, и, похоже, работает для Hexaddicus, имеет обе версии Lite и Pro, которые работают как один и тот же пользователь, а затем в первый раз запускают версию Pro, скопируйте базу данных Lite. Затем сообщите пользователю копию.

Установите для параметра android:sharedUserId то же самое в обоих продуктах...

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.mycompany.package"
      android:sharedUserId="com.mycompany.package" <---- IMPORTANT
      android:versionCode="10"
      android:versionName="@string/app_version"
      android:installLocation="auto">

И затем код для копирования базы данных...

    try {
        final Context free_context = this.createPackageContext("com.mycompany.package", Context.CONTEXT_INCLUDE_CODE);
        final File    full_db      = this.getDatabasePath(GameData.DATABASE_NAME);
        final File    full_db_dir  = full_db.getParentFile();
        final File    free_db      = free_context.getDatabasePath(GameData.DATABASE_NAME);
        final File    free_db_dir  = free_db.getParentFile();

        if (free_db.exists() == false)     return;
        if (full_db_dir.exists() == false) full_db_dir.mkdir();
        if (full_db.exists() == false)     full_db.createNewFile();

        FileUtils.copyDirectory(free_db_dir, full_db_dir);
        this.gameData.getWritableDatabase();
    }
    catch (NameNotFoundException e) {
        /* do nothing here since this is an semi expected case */
        Log.w("mytag", "No Lite version found");
    } catch (IOException e) {
        Log.w("mytag", "Failed to create file");
    }
}

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

Обновление: пожалуйста, рассмотрите комментарии ChrisCashwells и ответьте, так как он поднимает действительную точку, и я не могу вспомнить, что я сделал в его примере.

Ответ 2

Возможно, вы захотите сделать больше "разблокировки", чем, если это возможно, отдельным платным приложением. Таким образом, вы используете только один пакет. Если по какой-либо другой причине вы избегаете проблемы с владением базой данных.

Использование того же android:sharedUserId будет хорошим подходом, если ваше приложение уже имеет один набор. В противном случае вы будете лишать права доступа ко всем данным своих пользователей, если вы отправляете обновление, имеющее один набор. Если вы начинаете с нуля и не имеете приложения в дикой природе, пользователи, ожидающие сохранения своих данных, определенно устанавливают sharedUserId с первого дня.

Ответ 3

Как @Chris сказал, что вы можете использовать подход "unlock", я объясню, как это сделать в таких условиях.

У вас может быть таблица типа "Особенности", которая должна иметь столбец/флаг IsAvailable. Если вы хотите ограничить некоторые функции, вы можете установить флаг IsAvailable в FALSE.

Если у вас есть изменения в структуре БД, вам необходимо обновить БД, используя:

@Override
public void onUpgrade()
{
  if (condition == true)
    // alter table
}