AssetManager vs Internal Storage: Как я могу сохранить кроссплатформенный файл config.json в Xamarin Android, который я хочу редактировать позже? - PullRequest
0 голосов
/ 23 марта 2019

Я хочу иметь возможность предварительно настроить приложение Android для включения файла json, который доступен для чтения / записи, который также можно использовать на других платформах (iOS, UWP). Я начал смотреть на AssetManager, но обнаружил, что могу только читать файл, но не редактировать его позже.

Является ли внутреннее хранилище ответом? Если да, как мне предварительно заполнить внутреннее хранилище приложения этим файлом? Я не смог найти в Интернете никакой документации о том, как это сделать, кроме выполнения метода полной записи в коде на C #, что не позволяет использовать один и тот же файл config.json на всех платформах. Я просто хочу, чтобы мое приложение Android сохраняло этот файл config.json, и чтобы этот файл был доступен для чтения и записи.

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 23 марта 2019

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

1) Скопируйте ваш файл в папку «Ресурсы» проекта Xamarin.Android и измените действие «Сборка» на «AndroidAsset». Это обеспечит первоначальную упаковку файла с вашим Android-приложением.

2) В вашем коде на C # вы действительно хотите прочитать и записать этот файл из внутреннего хранилища вашего Android-приложения, а не из AssetManager (вы все равно не можете писать в AssetManager, только читать!). Таким образом, чтобы сделать это, вы должны сначала извлечь файл из AssetManager, а затем все последующие операции чтения / записи будут происходить из внутреннего хранилища.

    /// <summary>
    /// This method will read the application settings from internal storage.  
    /// If it can't find it, it will use the default AndroidAsset version of 
    /// the appsettings.json file from this project's Asset folder.
    /// </summary>
    /// <returns></returns>
    public async Task<DefaultSettings> GetDefaultSettingsAsync()
    {
        var path = Application.Context.FilesDir.Path;
        if (File.Exists(Path.Combine(path, "appsettings.json")))
        {
            using (var sr = Application.Context.OpenFileInput("appsettings.json"))
            {
                using (var ms = new MemoryStream())
                {
                    await sr.CopyToAsync(ms);
                    var memoryBytes = ms.ToArray();
                    var content = System.Text.Encoding.Default.GetString(memoryBytes);
                    var defaultSettings = JsonConvert.DeserializeObject<DefaultSettings>(content);
                    return defaultSettings;
                }
            }
        }
        else
        {
            var result = await GetDefaultSettingsAssetAsync();
            return result;
        }
    }

    /// <summary>
    /// This method gets the appsettings.json file from the Android AssetManager, in the case
    /// where you do not have an editable appsettings.json file yet in your Android app's internal storage.
    /// </summary>
    /// <returns></returns>
    private static async Task<DefaultSettings> GetDefaultSettingsAssetAsync()
    {
        try
        {
            var assetsManager = MainActivity.Instance.Assets;

            using (var sr = assetsManager.Open("appsettings.json"))
            {
                using (var ms = new MemoryStream())
                {
                    await sr.CopyToAsync(ms);
                    var memoryBytes = ms.ToArray();
                    var content = System.Text.Encoding.Default.GetString(memoryBytes);
                    var defaultSettings = JsonConvert.DeserializeObject<DefaultSettings>(content);

                    // This will write the Asset to Internal Storage for the first time.  All subsequent writes will occur using SaveDefaultSettingsAsync.
                    using (var stream = Application.Context.OpenFileOutput("appsettings.json", FileCreationMode.Private))
                    {
                        await stream.WriteAsync(memoryBytes, 0, memoryBytes.Length);
                    }

                    return defaultSettings;
                }
            }
        }
        catch (Exception ex)
        {
            return new DefaultSettings();
        }
    }

    /// <summary>
    /// This method will save the DefaultSettings to your appsettings.json file in your Android App's internal storage.
    /// </summary>
    /// <param name="settings"></param>
    /// <returns></returns>
    public async Task SaveDefaultSettingsAsync(DefaultSettings settings)
    {
        using (var stream = Application.Context.OpenFileOutput("appsettings.json", FileCreationMode.Private))
        {
            var content = JsonConvert.SerializeObject(settings);
            var bytes = Encoding.Default.GetBytes(content);
            await stream.WriteAsync(bytes, 0, bytes.Length);
        }
    }
...