Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What is going on with this article?

More than 1 year has passed since last update.

@karak

Xamarin.Authからの移行

背景

Visual Studio for Mac を 2019 にアップデートしたら Xamarin.iOS のアプリが動かなくなった。

Xamarin.Auth の AccountStore.FindAccountsForServiceAsync を呼ぶだけでエラーが起きるようになっている。

https://github.com/xamarin/Xamarin.Auth/issues/370 にissueが上がっており、対策は

  1. Xamarin.iOSのダウングレード(12.2)
  2. Xamarin.Essentials の SecureStorage への移行。

のいずれか。

前者は影響範囲が全アプリに及ぶうえに、Xamarin.Auth のこのクラスは非推奨のため、後者を選択。

やり方

Migration Guide にあるように、次のようなヘルパークラスをつくって移行すればよい。

using Newtonsoft.Json;
using Xamarin.Auth;
using Xamarin.Essentials;

public class SecureStorageAccountStore
{
    public static async Task SaveAsync(Account account, string serviceId)
    {
        // Find existing accounts for the service
        var accounts = await FindAccountsForServiceAsync(serviceId);

        // Remove existing account with Id if exists
        accounts.RemoveAny(a => a.Username == account.Username);

        // Add account we are saving
        accounts.Add(account);

        // Serialize all the accounts to javascript
        var json = JsonConvert.SerializeObject(accounts);

        // Securely save the accounts for the given service
        await SecureStorage.SetAsync(serviceId, json);
    }

    public static async Task<List<Account>> FindAccountsForServiceAsync(string serviceId)
    {
        // Get the json for accounts for the service
        var json = await SecureStorage.GetAsync(serviceId);

        try {
            // Try to return deserialized list of accounts
            return JsonConvert.DeserializeObject<List<Account>>(json);
        } catch { }

        // If this fails, return an empty list
        return new List<Account>();
    }

    public static async Task MigrateAllAccountsAsync(string serviceId, IEnumerable<Account> accountStoreAccounts)
    {
        var wasMigrated = await SecureStorage.GetAsync("XamarinAuthAccountStoreMigrated", "0");

        if (wasMigrated == "1")
            return;

        await SecureStorage.SetAsync("XamarinAuthAccountStoreMigrated", "1");

        // Just in case, look at existing 'new' accounts
        var accounts = await FindAccountsForServiceAsync(serviceId);

        foreach (var account in accountStoreAccounts) {

            // Check if the new storage already has this account
            // We don't want to overwrite it if it does
            if (accounts.Any(a => a.Username == account.Username))
                continue;   

            // Add the account we are migrating
            accounts.Add(account);
        }

        // Serialize all the accounts to javascript
        var json = JsonConvert.SerializeObject(accounts);

        // Securely save the accounts for the given service
        await SecureStorage.SetAsync(serviceId, json);
    }
}

※ 上は挙げられているコードそのままだが、実際には System.Linq などの import をたす必要あり。

問題

が、結局この前後のデータのマイグレーションにも Find... が必要なため、この事態が起きてしまうということ。許容できない場合は Xamarin.Native でキーチェーンにアクセスして取り出す処理を書く必要がある。

もう一点、iOS SDK の問題だが、シミュレータ上では Entitlements.plist の編集が必要になる。通常(実機で使う場合)は不要のため、地味にストレスになる。

2
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
2
Help us understand the problem. What is going on with this article?