web-dev-qa-db-ja.com

Android 10:IMEIはAPI 29で利用できなくなりました。代わりのものを探しています

私たちのクライアントのアプリの主な機能は、クライアントのデバイスの追跡に大きく関係しており、(所有者ではなく)特定の電話にバインドされた製品を提供しています。これはデバイスimeiを使用して可能でしたが、Android 10のプライバシーの変更により、アクセスできなくなりました。( https://developer.Android.com/about/versions/ 10 /プライバシー/変更 )。

Androidには、特定のユーザーケースで使用する識別子に関するドキュメントがありますが、一意であり、デバイスにバインドされている(または少なくとも変更が難しい)必要があるため、ケースに一致しません。 https://developer.Android.com/training/articles/user-data-ids 。 Android IDは可能な解決策であるか、またはMACアドレスを使用して、100%信頼できるものではないと認識している。

何かご意見は?推奨?経験?この時点で、何かがオプションになる可能性があります

15
kvnnj.m_av

Googleのベストプラクティスの公式ブログを読んで、ユースケースが仕様と一致するかどうかを確認することをお勧めします: https://developer.Android.com/training/articles/user-data-ids.html

私にとっては、Android識別子の一意性について同じ問題が発生し、MediaDrm API( https://Android.googlesource.com/platform /frameworks/base/+/Android-cts-4.4_r1/media/Java/Android/media/MediaDrm.Java#539 )一意のデバイスIDを含み、出荷時設定にリセットしても存続できるため、必要ありませんマニフェストファイルに対する追加の権限。

Android 10で一意の識別子を取得するにはどうすればよいですか?

import Android.media.MediaDrm
import Java.security.MessageDigest
import Java.util.*

object UniqueDeviceID {

    /**
     * UUID for the Widevine DRM scheme.
     * <p>
     * Widevine is supported on Android devices running Android 4.3 (API Level 18) and up.
     */
    fun getUniqueId(): String? {

        val WIDEVINE_UUID = UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L)
        var wvDrm: MediaDrm? = null
        try {
            wvDrm = MediaDrm(WIDEVINE_UUID)
            val widevineId = wvDrm.getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID)
            val md = MessageDigest.getInstance("SHA-256")
            md.update(widevineId)
            return  md.digest().toHexString()
        } catch (e: Exception) {
            //WIDEVINE is not available
            return null
        } finally {
            if (AndroidPlatformUtils.isAndroidTargetPieAndHigher()) {
                wvDrm?.close()
            } else {
                wvDrm?.release()
            }
        }
    }


    fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) }
}

Java @Sofienによるソリューションに関心のあるユーザーの場合、私は次のようにしています。

  1. @SofienのコードをJavaに変換し、さらに簡略化しました。
  2. 対象のケースがAndroid 10(API 29)であっても、より多くのデバイスとOSバージョンで広範囲にテストされています。

1.コードとディスカッション

_@Nullable
String getUniqueID() {
   UUID wideVineUuid = new UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L);
   try {
      MediaDrm wvDrm = new MediaDrm(wideVineUuid);
      byte[] wideVineId = wvDrm.getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID);
      return Arrays.toString(wideVineId);
   } catch (Exception e) {
      // Inspect exception
      return null;
   }
   // Close resources with close() or release() depending on platform API
   // Use ARM on Android P platform or higher, where MediaDrm has the close() method
}
_

W.r.tには2つの重要な違いがあります。 @ソフィエンのコード。

  • MessageDigestを使用していないため、コードが単純になります。さらに、MessageDigest.update()メソッドは_SHA-256_ハッシュ関数を引数に適用するため、UUIDの一意性が失われる可能性が非常に低くなります。 UUIDをハッシュしない唯一の欠点は、固定長のUUIDがないことです。これは、アプリケーションでは気にしません。
  • Kotlin関数toHexString(Javaでは1行の対応物がない)の代わりに、_Arrays.toString_を使用しています。 (A)Exceptionをスローせず、(B)wideVineIdとそのString表現の間で1対1の対応を保持するため、この選択は安全です。 16進数変換に固執する場合は、 Apache Commons Codec ライブラリーが1行のソリューションを提供します。 この回答 を参照してください。

もちろん、これらの変更により別のUUIDが生成されます。言うまでもなく、他の選択も可能です。また、_Arrays.toString_で生成されたUUIDは次の形式になります。

_[92, -72, 76, -100, 26, -86, 121, -57, 81, -83, -81, -26, -26, 3, -49, 97, -24, -86, 17, -106, 25, 102, 55, 37, 47, -5, 33, -78, 34, 121, -58, 109]
_

そのため、UUIDに特殊文字が必要ない場合は、String.replaceAll()を使用してそれらを削除できます。

2.テスト

UUIDの永続性をテストしました

  • 再インストール以上
  • 再インストールして再起動

次のデバイスとOSの組み合わせ:

  • Samsung Galaxy S10/API 29
  • Samsung Galaxy S9/API 29
  • Huawei Nexus 6P/API 27(工場出荷時のリセットでもテスト済み)
  • Asus ZenFone 2/API 23
  • Samsung Galaxy J5/API 23
  • LG Nexus 5/API 23
  • LG K4/API 22
  • Samsung Galaxy J3/API 22
  • Samsung Galaxy S4/API 21

すべてのテストで、targetSdkVersionは29です。

1
  1. Android gmsサービスによってデバイスIDにアクセスできます。以下の例を参照してください。
private DeviceInfoProvider mDeviceInfo = new DeviceInfoProvider(Context)
String mDeviceId = DeviceInfoProvider.getDeviceId(Context);
Log.d("DEVICE_ID" , mDeviceId);
  1. デバイスの初回起動時に、ランダムな値が生成されて保存されます。この値は、 Settings.Secure.Android_ID。これは64ビットの数値であり、デバイスの寿命が尽きるまで一定に保つ必要があります。 Android_IDはスマートフォンやタブレットで利用できるため、一意のデバイス識別子としては適切な選択肢のようです。値を取得するには、次のコードを使用できます。
String androidId = Settings.Secure.getString(getContentResolver(),
                                             Settings.Secure.Android_ID);

ただし、デバイスで出荷時設定へのリセットが実行されると、値が変わる可能性があります。すべてのインスタンスが同じであるメーカーからの人気のあるハンドセットに既知のバグもあります Android_ID。明らかに、このソリューションは100%信頼できるものではありません。

  1. 使用する UUID。ほとんどのアプリケーションの要件は、物理デバイスではなく特定のインストールを識別することであるため、UUIDクラスを使用する場合にユーザーの一意のIDを取得するための優れたソリューションです。次のソリューションは、 レト・マイヤー Googleから Google I/O プレゼンテーション、
SharedPreferences sharedPrefs = context.getSharedPreferences(
PREF_UNIQUE_ID, Context.MODE_PRIVATE);
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
1
Kiran Maniya