AccountManager実装したときのメモ
AbstractAccountAuthenticator#addAccountが呼ばれるタイミング
AbstractAccountAuthenticator#getAuthTokenが呼ばれるタイミング
Authenticatorを持つ自アプリから AccountManager#getAuthToken
を呼び出しても AbstractAccountAuthenticator#getAuthToken
は呼ばれない
他アプリから AccountManager#getAuthToken
が呼ばれた際に呼ばれる
他アプリ(違うkeystoreでBuild)からAccountManagerへのアクセス
Android5.xでは AccountManager#getAuthToken
アカウントへのアクセスリクエスト画面が強制的に表示される
-> 許可をクリック後AuthTokenを取得できる
Android7.xでは AccountManager#getAuthToken
何も表示されず何も取得できない
他アプリ(同じkeystoreでBuild)からAccountManagerへのアクセス
Android5.xでは AccountManager#getAuthToken
何もなくAuthTokenが取得できる
Android7.xでは AccountManager#getAuthToken
何もなくAuthTokenが取得できる
同じauthenticatorを2つのアプリに入れた際の挙動
先にインストールした authenticator
が優先される
- アプリAインストール -> アプリBインストール -> アプリAアンインストール
- アプリAのアカウントが削除され、アプリBからアカウントへのアクセスができなくなる
- アプリAインストール -> アプリBインストール -> アプリAアンインストール -> アプリAインストール
- アプリAのアカウントが削除され、アプリBからアカウントへのアクセスができなくなる
- アプリBで作成されたアカウントにアプリAはアクセスできる
Permisssion関連
様々なサイトで android.permission.GET_ACCOUNTS
が AccountManager#getAccountsByType
を呼ぶ際などに必要と書かれている。
Permission Requestが必要と思うが android.permission.GET_ACCOUNTS
が必要なのはAPI22まででAPI23以降は必要ではない。
そのため以下のように
<uses-permission android:name="android.permission.GET_ACCOUNTS" android:maxSdkVersion="22" />
と書くのが正しい。
https://developer.android.com/reference/android/Manifest.permission.html#GET_ACCOUNTS
if an app shares the signature of the authenticator that manages an account, it does not need "GET_ACCOUNTS" permission to read information about that account. On Android 5.1 and lower, all apps need "GET_ACCOUNTS" permission to read information about any account.
ココらへんのPermission関連はAccountManagerを使用する際に必要とするPermissionにも同じことが言えると思うが調べながら行ったほうが良い。
セキュリティ周り
先にインストールアされたアプリの authenticator
が優先されるため、疑似アプリをインストール後、本物をインストールすると、疑似アプリの authenticator
が有効になってしまう。
そのため、証明書のチェックを行うと良い。
private fun isCorrectCertificate(): Boolean {
val packageNames = accountManager.authenticatorTypes.filter { it.type == accountType }.map { it.packageName }
if (packageNames.isEmpty()) {
return true
}
val packageInfoList = packageNames.map { packageManager.getPackageInfo(it, PackageManager.GET_SIGNATURES) }
val md = MessageDigest.getInstance("SHA1")
return packageInfoList.all {
md.update(it.signatures.first().toByteArray())
myHashKey == Base64.encodeToString(md.digest(), Base64.DEFAULT)
}
}
こんなんがいるかも。
authenticator.xmlまわりについて
accountType
はR.stringを参照するとダメ
-> http://qiita.com/KeithYokoma/items/c1975f616123475e9cbc
label
は逆にR.stringを参照しないと表示されなくなる(Android7で確認)
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="jp.hoge.hoge.develop"
android:icon="@mipmap/ic_launcher"
android:label="hoge"
android:smallIcon="@mipmap/ic_launcher" />
例えば、 label
に hoge
を指定した場合
こんな感じになり、この状態でアカウント追加が正常終了すると
アカウントは追加していて、AccountManagerからアクセスできるがアカウント一覧には何も表示されない状況になる。
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="jp.hoge.hoge.develop"
android:icon="@mipmap/ic_launcher"
android:label="@string/hoge"
android:smallIcon="@mipmap/ic_launcher" />