Xamarin.Forms, как сделать резервную копию базы данных SQLite на SD-карте - PullRequest
0 голосов
/ 04 июня 2018

У меня есть база данных SQLite в моем проекте, и я хотел бы добавить функцию резервного копирования для сохранения этой базы данных на SD-карте.Есть ли простой способ сделать это для Android и IOS, используя Xamarin.Forms?Я искал среди старых (некоторые из них очень старые) вопросы, но не смог найти четкого ответа.

1 Ответ

0 голосов
/ 04 июня 2018

iOS:

На iOS нет «sdcard», но вы можете скопировать (File.Copy) базу данных в каталог Documents приложения, чтобы он был доступен через приложение iTunes, чтобы вы могли скопироватьна ваш ПК / Mac:

Используйте этот каталог для хранения пользовательского контента.Содержимое этого каталога может быть сделано доступным для пользователя через общий доступ к файлам;поэтому его каталог должен содержать только те файлы, которые вы, возможно, пожелаете предоставить пользователю.Резервное копирование содержимого этого каталога осуществляется iTunes и iCloud.

При условии, что вы используете каталог поддержки приложений для своей БД, который должен быть:

public string GetDBPath(string dbFileName)
{
    // If you are not using App Support directory for your DBs you are doing it wrong on iOS ;-)
    var supportDir = NSSearchPath.GetDirectories(NSSearchPathDirectory.ApplicationSupportDirectory, NSSearchPathDomain.User, true)[0];
    var dbDir = Path.Combine(supportDir, "database");
    if (!Directory.Exists(dbDir))
         Directory.CreateDirectory(dbDir);
    return Path.Combine(supportDir, dbDir, dbFileName);
}

Копирование вКаталог документации вашего приложения так же прост:

public void CopyDBToDocs(string dbFileName)
{
    var docDir = NSSearchPath.GetDirectories(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User)[0];
    File.Copy(GetDBPath(dbFileName), Path.Combine(docDir, dbFileName));
}

Android:

На Android это может быть очень просто или неприятно, в зависимости от API устройства и того, что ваш AndroidЦель API приложения, которое вы разрабатываете.

Столь же просто, как:

public void CopyDBToSdCard(string dbName)
{
    File.Copy(GetDBPath(dbName), Path.Combine(Android.OS.Environment.DirectoryDownloads, dbName);
}

GetDBPath в этом случае фактически используется «истинный» каталог базы данных, который является подкаталогом вашегоРасположение «FileDir» в изолированной программной папке приложения:

public string GetDBPath(string dbFileName)
{
    // FYI: GetDatabasePath("") fails on some APIs &| devices &|emulators so hack it... (Some API 23 devices, but not API 21, 27, 28, ...)
    var dbPath = context.GetDatabasePath("ZZZ").AbsolutePath.Replace("/ZZZ", "");
    if (!Directory.Exists(dbPath))
        Directory.CreateDirectory(dbPath);
    return context.GetDatabasePath(dbFileName).AbsolutePath;
}

Теперь, чтобы фактически выполнить копирование этого файла во «внешнее» местоположение из приложения, требуется разрешение манифеста приложения:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

Также, если ваше приложение имеет «таргетинг» и работает на API-23 (Android 6.0) или выше, вам необходимо получить согласие пользователя на это разрешение во время выполнения.

Использование Android.Support.Compat - этоСамый простой способ.В основном вам нужно проверить, было ли разрешение уже предоставлено, если не показывать пользователю, почему вам нужно разрешение, а затем позволить ОС попросить пользователя принять / отклонить запрос.Затем вы получите уведомление об этих результатах.

Примечание. Для не выделенных жирным шрифтом существует плагин Forms 'Perm от JamesM ;-) PermissionsPlugin

void GetExternalPerms()
{
    const string writePermission = Manifest.Permission.WriteExternalStorage;
    const string readPermission = Manifest.Permission.ReadExternalStorage;
    string[] PermissionsLocation =
     {
        writePermission, readPermission
     };
    if ((ContextCompat.CheckSelfPermission(this, writePermission) == Permission.Granted) && (ContextCompat.CheckSelfPermission(this, readPermission) == Permission.Granted))
    {
        return;
    }
    if (ActivityCompat.ShouldShowRequestPermissionRationale(this, writePermission))
        // Displaying a dialog would make sense at this point...
    }
    ActivityCompat.RequestPermissions(this, PermissionsLocation, 999);
}

Тогда результаты, которые пользователь принимает или отклоняет, будут возвращены через OnRequestPermissionsResult:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
    switch (requestCode)
    {
        case 999: //  This is the code that we supply via RequestPermissions
            if (grantResults[0] == Permission.Granted)
            {
                // you have permission, so defer to your DB copy routine now
            }
            break;
        default:
            break;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...