web-dev-qa-db-ja.com

固有のAndroidデバイスIDはありますか?

Androidデバイスには固有のIDがありますか?その場合、Javaを使用してそれにアクセスするための簡単な方法は何ですか?

2525
Tyler

Settings.Secure#Android_ID はAndroid IDをとして返します 各ユーザーに固有64 -ビットの16進文字列。

import Android.provider.Settings.Secure;

private String Android_id = Secure.getString(getContext().getContentResolver(),
                                                        Secure.Android_ID); 
1890

UPDATE:最近のAndroidバージョンでは、Android_IDの問題の多くは解決されており、このアプローチは長く必要です。 Anthonyの答え をご覧ください。

完全な開示:私のアプリはもともと以下のアプローチを使用していましたが、このアプローチは使用しなくなり、現在では Android Developer Blog エントリ emmby's answer リンク(つまり、 UUID#randomUUID() )を生成して保存します。


この質問には多くの回答がありますが、そのほとんどは「一部」の時間でしか機能しませんが、残念ながらそれでは十分ではありません。

デバイスのテスト(すべての電話、少なくとも1つがアクティブ化されていない)に基づく:

  1. テストしたすべてのデバイスがTelephonyManager.getDeviceId()の値を返しました
  2. すべてのGSMデバイス(すべてSIMでテスト済み)は、TelephonyManager.getSimSerialNumber()の値を返しました
  3. すべてのCDMAデバイスがgetSimSerialNumber()に対してnullを返しました(予想どおり)
  4. Googleアカウントが追加されたすべてのデバイスは、Android_IDの値を返しました
  5. すべてのCDMAデバイスは、Android_IDTelephonyManager.getDeviceId()の両方に対して同じ値(または同じ値の派生)を返しました-限りセットアップ中にGoogleアカウントが追加されました。
  6. SIMのないGSMデバイス、Googleアカウントが追加されていないGSMデバイス、または機内モードのデバイスをテストする機会はまだありませんでした。

したがって、デバイス自体に固有の何かが必要な場合は、TM.getDeviceId()shouldで十分です。明らかに、一部のユーザーは他のユーザーよりも妄想的であるため、これらの識別子の1つ以上をハッシュすると、文字列がデバイスに対して実質的に一意であるが、ユーザーの実際のデバイスを明示的に識別しないために役立ちます。たとえば、String.hashCode()をUUIDと組み合わせて使用​​します。

final TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);

final String tmDevice, tmSerial, androidId;
tmDevice = "" + tm.getDeviceId();
tmSerial = "" + tm.getSimSerialNumber();
androidId = "" + Android.provider.Settings.Secure.getString(getContentResolver(), Android.provider.Settings.Secure.Android_ID);

UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode());
String deviceId = deviceUuid.toString();

次のような結果になる可能性があります:00000000-54b3-e7c7-0000-000046bffd97

それは私にとって十分に機能します。

リチャードが以下で言及するように、TelephonyManagerプロパティを読み取るための許可が必要であることを忘れないでください。したがって、これをマニフェストに追加します。

<uses-permission Android:name="Android.permission.READ_PHONE_STATE" />

インポートライブラリ

import Android.content.Context;
import Android.telephony.TelephonyManager;
import Android.view.View;
1114
Joe

最終更新日:6/2/15


固有のIDの作成に関するすべてのStack Overflowの投稿、Googleの開発者ブログ、およびAndroidのドキュメントを読んだ後、 'Pseudo ID'が可能な限り最良の選択肢であるように感じます。

主な問題:ハードウェアとソフトウェア

ハードウェア

  • ユーザーは自分のハードウェア、Androidタブレット、または電話を変更できるため、ハードウェアに基づく一意のIDは TRACKING USERS には適していません。
  • トラッキングハードウェア の場合、これは素晴らしいアイデアです。

ソフトウェア

  • 自分が根ざしている場合、ユーザーは自分のROMを消去/変更できます。
  • プラットフォーム(iOS、Android、Windows、Web)にわたってユーザーを追跡できます。
  • 個人ユーザーを追跡する 同意 を付けることは、単にログインさせることです(OAuthを使用してこれをシームレスにする)。

Androidの全体的な内訳

- API> = 9/10(Androidデバイスの99.5%)に対する一意性の保証(根ざしたデバイスを含む)

- 追加の権限なし

疑似コード:

if API >= 9/10: (99.5% of devices)

return unique ID containing serial id (rooted devices may be different)

else

return the unique ID of build information (may overlap data - API < 9)

(このStack Overflowの質問に)すべてのオプションを投稿してくれた@stansultに感謝します。

オプションのリスト - それらを使用しない理由/理由:

  • ユーザーの電子メールアドレス - ソフトウェア

    • ユーザーがEメールを変更する可能性があります - ほとんどあり得ません
    • API 5+ <uses-permission Android:name="Android.permission.GET_ACCOUNTS" />または
    • API 14+ <uses-permission Android:name="Android.permission.READ_PROFILE" /><uses-permission Android:name="Android.permission.READ_CONTACTS" />AndroidデバイスのメインのEメールアドレスを取得する方法
  • ユーザーの電話番号 - ソフトウェア

    • ユーザーが電話番号を変更する可能性があります - ほとんどあり得ません
    • <uses-permission Android:name="Android.permission.READ_PHONE_STATE" />
  • IMEI - ハードウェア (電話のみ、Android.permission.READ_PHONE_STATEが必要)

    • ほとんどのユーザーはそれが許可で "電話をかける"と言う事実を嫌います。何人かのユーザーは悪い評価を与えます、なぜなら彼らがあなたが本当にしたいのはあなたが単にデバイスのインストールを追跡することであるときあなたの個人情報を盗んでいると信じているからです。データを収集しているのは明らかです。
    • <uses-permission Android:name="Android.permission.READ_PHONE_STATE" />
  • Android ID - ハードウェア (nullにすることも、出荷時設定にリセットすることによって変更することも、根付くデバイスで変更することもできます)

    • Nullになる可能性があるので、nullを確認してその値を変更できますが、これは一意ではなくなることを意味します。
    • 工場出荷時の状態にリセットされたデバイスを使用しているユーザーがいる場合、その値がルートデバイスで変更または変更されている可能性があるため、ユーザーインストールを追跡している場合はエントリが重複する可能性があります。
  • WLAN MACアドレス - ハードウェア (needsAndroid.permission.ACCESS_WIFI_STATE

    • これは2番目に良い選択肢かもしれませんが、あなたはまだユーザーから直接来るユニークな識別子を集めて保存しています。これはあなたがデータを収集していることは明らかです。
    • <uses-permission Android:name="Android.permission.ACCESS_WIFI_STATE "/>
  • Bluetooth MACアドレス - ハードウェア (Bluetooth搭載デバイス、Android.permission.BLUETOOTH

    • 市販されているほとんどのアプリケーションはBluetoothを使用していません。そのため、Bluetoothを使用していないアプリケーションにBluetoothが含まれていると、ユーザーが不審になる可能性があります。
    • <uses-permission Android:name="Android.permission.BLUETOOTH "/>
  • 疑似固有ID - ソフトウェア (すべてのAndroidデバイス用)

    • 非常に可能性があります、衝突を含むかもしれません - 下記に掲載された私の方法を見てください!
    • これにより、プライベートなものを何も使わなくても、ユーザーから「ほぼ一意の」IDを取得できます。あなたは、デバイス情報からあなた自身の匿名IDを作成することができます。

パーミッションを使用せずに一意のIDを取得するための「完璧な」方法がないことを私は知っています。しかし、時には私たちは本当にデバイスのインストールを追跡する必要があるだけです。一意のIDを作成する際には、追加の権限を使用せずにAndroid APIから提供される情報のみに基づいて「疑似一意ID」を作成できます。このようにして、私たちはユーザーの尊敬を示し、同様に優れたユーザーエクスペリエンスを提供しようとすることができます。

疑似一意IDを使用すると、類似したデバイスがあるという事実に基づいて重複がある可能性があるという事実に遭遇するだけです。あなたはそれをよりユニークにするために組み合わせた方法を微調整することができます。ただし、一部の開発者はデバイスのインストールを追跡する必要があり、これにより類似のデバイスに基づいたトリックまたはパフォーマンスが得られます。

API> = 9:

彼らのAndroidデバイスがAPI 9以上の場合、これは 'Build.SERIAL'フィールドのためにユニークであることが保証されています。

_記憶_ 、技術的に見逃しているのはユーザーの約0.5%だけです APIが9未満の場合 。だからあなたは残りに集中することができます:これはユーザーの99.5%です!

API <9:

ユーザーのAndroidデバイスがAPI 9より低い場合うまくいけば、彼らは工場出荷時設定へのリセットをしておらず、彼らの 'Secure.Android_ID'は保存されるか 'null'ではないでしょう。 ( http://developer.Android.com/about/dashboards/index.html を参照)

他のすべてが失敗した場合:

ユーザーがAPI 9より低い(Gingerbreadより低い)場合、デバイスがリセットされているか、または 'Secure.Android_ID'が 'null'を返す場合、それ以外のすべてが失敗した場合、返されるIDは単にAndroidデバイス情報に基づいています。これが衝突が起こる可能性がある場所です。

変更点

  • 工場出荷時の状態にリセットされたため、「Android.SECURE_ID」が削除されたため、値が変更される可能性があります。
  • APIを変更するようにコードを編集しました
  • 擬似を変更した

以下の方法を見てください。

/**
 * Return pseudo unique ID
 * @return ID
 */
public static String getUniquePsuedoID() {
    // If all else fails, if the user does have lower than API 9 (lower
    // than Gingerbread), has reset their device or 'Secure.Android_ID'
    // returns 'null', then simply the ID returned will be solely based
    // off their Android device information. This is where the collisions
    // can happen.
    // Thanks http://www.pocketmagic.net/?p=1662!
    // Try not to use DISPLAY, Host or ID - these items could change.
    // If there are collisions, there will be overlapping data
    String m_szDevIDShort = "35" + (Build.BOARD.length() % 10) + (Build.BRAND.length() % 10) + (Build.CPU_ABI.length() % 10) + (Build.DEVICE.length() % 10) + (Build.MANUFACTURER.length() % 10) + (Build.MODEL.length() % 10) + (Build.PRODUCT.length() % 10);

    // Thanks to @Roman SL!
    // https://stackoverflow.com/a/4789483/950427
    // Only devices with API >= 9 have Android.os.Build.SERIAL
    // http://developer.Android.com/reference/Android/os/Build.html#SERIAL
    // If a user upgrades software or roots their device, there will be a duplicate entry
    String serial = null;
    try {
        serial = Android.os.Build.class.getField("SERIAL").get(null).toString();

        // Go ahead and return the serial for api => 9
        return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
    } catch (Exception exception) {
        // String needs to be initialized
        serial = "serial"; // some value
    }

    // Thanks @Joe!
    // https://stackoverflow.com/a/2853253/950427
    // Finally, combine the values we have found by using the UUID class to create a unique identifier
    return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
}

新機能(広告付きアプリおよびGoogle Playサービス用):

Google Play開発者コンソールから:

2014年8月1日以降、Google Playデベロッパープログラムポリシーでは、すべての新しいアプリのアップロードおよびアップデートで、広告目的のために他の永続的な識別子の代わりにの広告IDを使用する必要があります。 ] もっと詳しく知る

実装

許可:

<uses-permission Android:name="Android.permission.INTERNET" />

コード:

import com.google.Android.gms.ads.identifier.AdvertisingIdClient;
import com.google.Android.gms.ads.identifier.AdvertisingIdClient.Info;
import com.google.Android.gms.common.GooglePlayServicesAvailabilityException;
import com.google.Android.gms.common.GooglePlayServicesNotAvailableException;
import Java.io.IOException;
...

// Do not call this function from the main thread. Otherwise, 
// an IllegalStateException will be thrown.
public void getIdThread() {

  Info adInfo = null;
  try {
    adInfo = AdvertisingIdClient.getAdvertisingIdInfo(mContext);

  } catch (IOException exception) {
    // Unrecoverable error connecting to Google Play services (e.g.,
    // the old version of the service doesn't support getting AdvertisingId).

  } catch (GooglePlayServicesAvailabilityException exception) {
    // Encountered a recoverable error connecting to Google Play services. 

  } catch (GooglePlayServicesNotAvailableException exception) {
    // Google Play services is not available entirely.
  }
  final String id = adInfo.getId();
  final boolean isLAT = adInfo.isLimitAdTrackingEnabled();
}

出典/文書:

http://developer.Android.com/google/play-services/id.htmlhttp://developer.Android.com/reference/com/google/Android/gms/ ads/identifier/AdvertisingIdClient.html

重要:

Google Play Servicesが利用可能な場合、広告IDは広告目的での他の識別子の既存の使用法(Settings.SecureでのAndroid_ID の使用など)を完全に置き換えることを目的としています。 Google Playサービスを利用できないケースは、 getAdvertisingIdInfo()によってスローされる GooglePlayServicesNotAvailableExceptionによって示されます。

警告、ユーザーはリセットできます。

http://en.kioskea.net/faq/34732-Android-reset-your-advertising-id

私は情報を得たすべてのリンクを参照しようとしました。あなたが行方不明で含まれる必要があるならば、コメントしてください!

GoogleプレーヤーサービスのInstanceID

https://developers.google.com/instance-id/

395
Jared Burrows

Dave Webbが述べているように、 Android Developer Blogはこれをカバーする記事 を持っています。彼らの推奨する解決策はデバイスではなくアプリのインストールを追跡することで、ほとんどのユースケースでうまくいくでしょう。それを機能させるためのコードです。ぜひチェックしてください。

ただし、ブログの投稿では、アプリのインストール識別子ではなくデバイス識別子が必要な場合の解決策について説明しています。あなたがそうする必要がある場合に備えて、私はグーグルの誰かと話をしていくつかの項目についてさらに説明を加えた。前述のブログ記事に記載されていないデバイス識別子について私が発見したのは次のとおりです。

  • Android_IDは優先デバイスIDです。 Android_IDは、Androidのバージョン<= 2.1または> = 2.3で完全に信頼できます。この記事で言及している問題は2.2だけです。
  • いくつかの製造元によるいくつかのデバイスが2.2のAndroid_IDバグの影響を受けています。
  • 私が判断できた限りでは、影響を受けるすべてのデバイスに 同じAndroid_ID 、つまり 9774d56d682e549c があります。これもエミュレータによって報告されたのと同じデバイスIDです。
  • グーグルは、OEMがそのデバイスの多くまたは大部分の問題にパッチを当てたと信じているが、私は2011年4月の初めの時点で、少なくとも壊れたAndroid_IDを持つデバイスを見つけることはまだかなり簡単であることを確認できた。

Googleの推奨に基づいて、必要に応じてAndroid_IDをシードとして使用し、必要に応じてTelephonyManager.getDeviceId()にフォールバックし、ランダムに生成された一意のUUIDを使用して各デバイスに一意のUUIDを生成するクラスを実装これはアプリの再起動後も持続します(ただしアプリの再インストールはしません)。

デバイスIDにフォールバックする必要があるデバイスの場合、一意のID _は_ に設定されていても工場出荷時の設定にリセットされます。これは知っておくべきことです。出荷時設定へのリセットによって一意のIDが確実にリセットされるようにする必要がある場合は、デバイスIDではなくランダムなUUIDに直接フォールバックすることを検討してください。

繰り返しますが、このコードはデバイスID用であり、アプリインストールID用ではありません。ほとんどの場合、アプリのインストールIDがおそらくあなたが探しているものです。しかし、デバイスIDが必要な場合は、おそらく以下のコードが役に立ちます。

import Android.content.Context;
import Android.content.SharedPreferences;
import Android.provider.Settings.Secure;
import Android.telephony.TelephonyManager;

import Java.io.UnsupportedEncodingException;
import Java.util.UUID;

public class DeviceUuidFactory {

    protected static final String PREFS_FILE = "device_id.xml";
    protected static final String PREFS_DEVICE_ID = "device_id";
    protected volatile static UUID uuid;

    public DeviceUuidFactory(Context context) {
        if (uuid == null) {
            synchronized (DeviceUuidFactory.class) {
                if (uuid == null) {
                    final SharedPreferences prefs = context
                            .getSharedPreferences(PREFS_FILE, 0);
                    final String id = prefs.getString(PREFS_DEVICE_ID, null);
                    if (id != null) {
                        // Use the ids previously computed and stored in the
                        // prefs file
                        uuid = UUID.fromString(id);
                    } else {
                        final String androidId = Secure.getString(
                            context.getContentResolver(), Secure.Android_ID);
                        // Use the Android ID unless it's broken, in which case
                        // fallback on deviceId,
                        // unless it's not available, then fallback on a random
                        // number which we store to a prefs file
                        try {
                            if (!"9774d56d682e549c".equals(androidId)) {
                                uuid = UUID.nameUUIDFromBytes(androidId
                                        .getBytes("utf8"));
                            } else {
                                final String deviceId = (
                                    (TelephonyManager) context
                                    .getSystemService(Context.TELEPHONY_SERVICE))
                                    .getDeviceId();
                                uuid = deviceId != null ? UUID
                                    .nameUUIDFromBytes(deviceId
                                            .getBytes("utf8")) : UUID
                                    .randomUUID();
                            }
                        } catch (UnsupportedEncodingException e) {
                            throw new RuntimeException(e);
                        }
                        // Write the value out to the prefs file
                        prefs.edit()
                                .putString(PREFS_DEVICE_ID, uuid.toString())
                                .commit();
                    }
                }
            }
        }
    }

    /**
     * Returns a unique UUID for the current Android device. As with all UUIDs,
     * this unique ID is "very highly likely" to be unique across all Android
     * devices. Much more so than Android_ID is.
     * 
     * The UUID is generated by using Android_ID as the base key if appropriate,
     * falling back on TelephonyManager.getDeviceID() if Android_ID is known to
     * be incorrect, and finally falling back on a random UUID that's persisted
     * to SharedPreferences if getDeviceID() does not return a usable value.
     * 
     * In some rare circumstances, this ID may change. In particular, if the
     * device is factory reset a new device ID may be generated. In addition, if
     * a user upgrades their phone from certain buggy implementations of Android
     * 2.2 to a newer, non-buggy version of Android, the device ID may change.
     * Or, if a user uninstalls your app on a device that has neither a proper
     * Android ID nor a Device ID, this ID may change on reinstallation.
     * 
     * Note that if the code falls back on using TelephonyManager.getDeviceId(),
     * the resulting ID will NOT change after a factory reset. Something to be
     * aware of.
     * 
     * Works around a bug in Android 2.2 for many devices when using Android_ID
     * directly.
     * 
     * @see http://code.google.com/p/Android/issues/detail?id=10603
     * 
     * @return a UUID that may be used to uniquely identify your device for most
     *         purposes.
     */
    public UUID getDeviceUuid() {
        return uuid;
    }
}
322
emmby

これがReto Meierが今年の Google I/O プレゼンテーションでユーザーのための一意のIDを取得するために使用したコードです。

private static String uniqueID = null;
private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";

public synchronized static String id(Context context) {
    if (uniqueID == null) {
        SharedPreferences sharedPrefs = context.getSharedPreferences(
                PREF_UNIQUE_ID, Context.MODE_PRIVATE);
        uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
        if (uniqueID == null) {
            uniqueID = UUID.randomUUID().toString();
            Editor editor = sharedPrefs.edit();
            editor.putString(PREF_UNIQUE_ID, uniqueID);
            editor.commit();
        }
    }
    return uniqueID;
}

これをクラウドにプリファレンスを送信するためのバックアップ戦略(Retoの talk でも説明されています)と組み合わせると、ユーザーが自分に縛られ、デバイスが消去された後、または交換された後でも使用できます。今後の分析でこれを使用することを計画しています(言い換えれば、私はまだその部分をやっていません:)。

171
Anthony Nolan

また、Wi-FiアダプターのMACアドレスを考慮することもできます。このようにして取得:

WifiManager wm = (WifiManager)Ctxt.getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getMacAddress();

マニフェストにAndroid.permission.ACCESS_WIFI_STATE権限が必要です。

Wi-Fiが接続されていない場合でも利用可能と報告されています。上記の回答のJoeがこれを彼の多くのデバイスで試してみたら、それは素晴らしいことです。

一部のデバイスでは、Wi-Fiがオフになっていると使用できません。

注: Android 6.xから、一貫した偽のMACアドレスを返します:02:00:00:00:00:00

101
Seva Alekseyev

ここにという便利な情報があります。

それは5つの異なるIDタイプをカバーします:

  1. _ imei _ (電話を使用するAndroidデバイスの場合のみ。Android.permission.READ_PHONE_STATEが必要)
  2. 擬似固有ID (すべてのAndroidデバイス用)
  3. Android ID (nullにすることも、出荷時設定にリセットすると変更することも、根ざした電話で変更することもできます)
  4. WLAN MACアドレス 文字列(Android.permission.ACCESS_WIFI_STATEが必要)
  5. BT MACアドレス 文字列(Bluetooth搭載デバイス、Android.permission.BLUETOOTHが必要)
81
stansult

公式のAndroid Developers Blogには、まさにこのテーマに関する記事、App Installationの識別があります。

47
BoD

Google I/O Reto Meierは、これをどのようにアプローチするかについての強力な回答を発表しました。 Anthony Nolanが彼の答えの中で方向性を示しています、しかし、私は他の人がそれをする方法を容易に見ることができるように私は完全なアプローチを書きたいと思いました。

この方法では、匿名で安全なユーザーIDが与えられます。これは、さまざまなデバイス間(Googleのプライマリアカウントに基づく)およびインストール間で永続的に使用されます。基本的な方法は、ランダムなユーザーIDを生成し、それをアプリの共有設定に保存することです。その後、Googleのバックアップエージェントを使用して、Googleアカウントにリンクされている共有設定をクラウドに保存します。

フルアプローチを見ていきましょう。まず、Android Backup Serviceを使用してSharedPreferencesのバックアップを作成する必要があります。 http://developer.Android.com/google/backup/signup.html経由であなたのアプリを登録することから始めましょう。

Googleは、マニフェストに追加する必要があるバックアップサービスキーを提供します。次のようにBackupAgentを使用するようにアプリケーションに指示する必要もあります。

<application Android:label="MyApplication"
         Android:backupAgent="MyBackupAgent">
    ...
    <meta-data Android:name="com.google.Android.backup.api_key"
        Android:value="your_backup_service_key" />
</application>

次に、バックアップエージェントを作成し、共有設定にヘルパーエージェントを使用するように指示する必要があります。

public class MyBackupAgent extends BackupAgentHelper {
    // The name of the SharedPreferences file
    static final String PREFS = "user_preferences";

    // A key to uniquely identify the set of backup data
    static final String PREFS_BACKUP_KEY = "prefs";

    // Allocate a helper and add it to the backup agent
    @Override
    public void onCreate() {
        SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this,          PREFS);
        addHelper(PREFS_BACKUP_KEY, helper);
    }
}

バックアップを完了するには、メインのアクティビティにBackupManagerのインスタンスを作成する必要があります。

BackupManager backupManager = new BackupManager(context);

最後に、まだ存在しない場合はユーザーIDを作成し、それをSharedPreferencesに保管します。

  public static String getUserID(Context context) {
            private static String uniqueID = null;
        private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";
    if (uniqueID == null) {
        SharedPreferences sharedPrefs = context.getSharedPreferences(
                MyBackupAgent.PREFS, Context.MODE_PRIVATE);
        uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
        if (uniqueID == null) {
            uniqueID = UUID.randomUUID().toString();
            Editor editor = sharedPrefs.edit();
            editor.putString(PREF_UNIQUE_ID, uniqueID);
            editor.commit();

            //backup the changes
            BackupManager mBackupManager = new BackupManager(context);
            mBackupManager.dataChanged();
        }
    }

    return uniqueID;
}

ユーザーがデバイスを移動した場合でも、このUser_IDはインストール後も保持されます。

このアプローチの詳細については Reto's talk を参照してください。

バックアップエージェントの実装方法の詳細については、Data Backupを参照してください。バックアップは瞬時には行われないため、テストの一番下にあるセクションを特にお勧めします。そのため、テストするにはバックアップを強制する必要があります。

38
TechnoTony

私はこれがユニークなIDのためのスケルトンを構築する確実な方法であると思います...それをチェックしてください。

すべてのAndroidデバイスで機能する疑似固有ID 一部のデバイスには電話がない(タブレットなど)、または何らかの理由でREAD_PHONE_STATE権限を含めたくない場合があります。 ROMバージョン、製造元名、CPUの種類、およびその他のハードウェアの詳細など、シリアルキーの確認やその他の一般的な目的にIDを使用する場合に適しています。この方法で計算されたIDは一意ではありません。同じIDを持つ2つのデバイス(同じハードウェアとROMイメージに基づく)を見つけることは可能ですが、実際のアプリケーションにおける変更は無視できます。この目的のためにBuildクラスを使うことができます。

String m_szDevIDShort = "35" + //we make this look like a valid IMEI
            Build.BOARD.length()%10+ Build.BRAND.length()%10 +
            Build.CPU_ABI.length()%10 + Build.DEVICE.length()%10 +
            Build.DISPLAY.length()%10 + Build.Host.length()%10 +
            Build.ID.length()%10 + Build.MANUFACTURER.length()%10 +
            Build.MODEL.length()%10 + Build.PRODUCT.length()%10 +
            Build.TAGS.length()%10 + Build.TYPE.length()%10 +
            Build.USER.length()%10 ; //13 digits

Buildメンバーの大部分は文字列です。ここで行っているのは、長さを取り、それを1桁のモジュロで変換することです。私たちは13のそのような数字を持っています、そして私たちはIMEIと同じサイズID(15の数字)を持つために前にもう2つを加えています(35)。これらの文字列を見てください。 355715565309247のようなものを返します。特別な許可は必要ないため、この方法は非常に便利です。


(追加情報:上記のテクニックは Pocket Magic の記事からコピーされたものです。)

34
Lenn Dolling

次のコードは、非表示のAndroid APIを使用してデバイスのシリアル番号を返します。しかし、 "ro.serialno"がこのデバイスに設定されていないため、このコードはSamsung Galaxy Tabでは機能しません。

String serial = null;

try {
    Class<?> c = Class.forName("Android.os.SystemProperties");
    Method get = c.getMethod("get", String.class);
    serial = (String) get.invoke(c, "ro.serialno");
}
catch (Exception ignored) {

}
34
Roman SL

以下のコードを使用すると、Android OSデバイスの一意のデバイスIDを文字列として取得できます。

deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.Android_ID); 
22
Mohit Kanada

シリアル フィールドは、APIレベル9(Android 2.3 - Gingerbread)のBuildクラスに追加されました。ドキュメンテーションはそれがハードウェアシリアル番号を表すと言います。したがって、それがデバイス上に存在する場合、それは一意であるべきです。 

APIレベルが9以上のすべてのデバイスで実際にサポートされている(= nullでない)かどうかはわかりません。

18
rony l

私が追加する1つのこと - 私はそれらのユニークな状況のうちの1つを持っています。

使用方法

deviceId = Secure.getString(this.getContext().getContentResolver(), Secure.Android_ID);

私のViewsonic G TabletがNullではないDeviceIDを報告しても、全てのG Tabletが同じ番号を報告しているのです。

「ユニークな」DeviceIDに基づいて誰かのアカウントに瞬時にアクセスできるようにする「Pocket Empires」をプレイするのは面白いことです。

私のデバイスは携帯無線機を持っていません。

15
Tony Maro

アプリケーションのインストール元のAndroidデバイスごとに一意の識別子を取得する方法の詳細については、公式のAndroid Developers Blogの投稿アプリのインストールの識別を参照してください。

インストール時に自分で生成し、その後アプリケーションを再起動したときにそれを読むのが最善の方法のようです。

私は個人的にこれは許容できるが理想的ではないと思います。ほとんどの場合、携帯の無線状態(Wi-Fiのオン/オフ、携帯のオン/オフ、Bluetoothのオン/オフ)に依存しているため、Androidが提供する1つの識別子がすべての場合に機能することはありません。 Settings.Secure.Android_IDのような他のものは製造元によって実装されなければならず、ユニークであることが保証されません。

以下は、アプリケーションがローカルに保存する他のデータと一緒に保管される installation ファイルにデータを書き込む例です。

public class Installation {
    private static String sID = null;
    private static final String INSTALLATION = "INSTALLATION";

    public synchronized static String id(Context context) {
        if (sID == null) {
            File installation = new File(context.getFilesDir(), INSTALLATION);
            try {
                if (!installation.exists())
                    writeInstallationFile(installation);
                sID = readInstallationFile(installation);
            } 
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return sID;
    }

    private static String readInstallationFile(File installation) throws IOException {
        RandomAccessFile f = new RandomAccessFile(installation, "r");
        byte[] bytes = new byte[(int) f.length()];
        f.readFully(bytes);
        f.close();
        return new String(bytes);
    }

    private static void writeInstallationFile(File installation) throws IOException {
        FileOutputStream out = new FileOutputStream(installation);
        String id = UUID.randomUUID().toString();
        out.write(id.getBytes());
        out.close();
    }
}
14
Kevin Parker

クラスファイルに以下のコードを追加します。

final TelephonyManager tm = (TelephonyManager) getBaseContext()
            .getSystemService(SplashActivity.TELEPHONY_SERVICE);
    final String tmDevice, tmSerial, androidId;
    tmDevice = "" + tm.getDeviceId();
    Log.v("DeviceIMEI", "" + tmDevice);
    tmSerial = "" + tm.getSimSerialNumber();
    Log.v("GSM devices Serial Number[simcard] ", "" + tmSerial);
    androidId = "" + Android.provider.Settings.Secure.getString(getContentResolver(),
            Android.provider.Settings.Secure.Android_ID);
    Log.v("androidId CDMA devices", "" + androidId);
    UUID deviceUuid = new UUID(androidId.hashCode(),
            ((long) tmDevice.hashCode() << 32) | tmSerial.hashCode());
    String deviceId = deviceUuid.toString();
    Log.v("deviceIdUUID universally unique identifier", "" + deviceId);
    String deviceModelName = Android.os.Build.MODEL;
    Log.v("Model Name", "" + deviceModelName);
    String deviceUSER = Android.os.Build.USER;
    Log.v("Name USER", "" + deviceUSER);
    String devicePRODUCT = Android.os.Build.PRODUCT;
    Log.v("PRODUCT", "" + devicePRODUCT);
    String deviceHARDWARE = Android.os.Build.HARDWARE;
    Log.v("HARDWARE", "" + deviceHARDWARE);
    String deviceBRAND = Android.os.Build.BRAND;
    Log.v("BRAND", "" + deviceBRAND);
    String myVersion = Android.os.Build.VERSION.RELEASE;
    Log.v("VERSION.RELEASE", "" + myVersion);
    int sdkVersion = Android.os.Build.VERSION.SDK_INT;
    Log.v("VERSION.SDK_INT", "" + sdkVersion);

AndroidManifest.xmlに追加します。

<uses-permission Android:name="Android.permission.READ_PHONE_STATE" />
10
Android

TelephonyManagerAndroid_IDを使用した、StringとしてのAndroid OSデバイスの一意のデバイスIDは、次の方法で取得されます。

String deviceId;
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephony.getDeviceId() != null) {
    deviceId = mTelephony.getDeviceId();
}
else {
    deviceId = Secure.getString(
                   getApplicationContext().getContentResolver(),
                   Secure.Android_ID);
}

しかし、私はGoogleが提案した方法を強くお勧めします。アプリのインストールの識別を参照してください。

9
Elenasys

長所と短所があるこれらのAndroid_IDの問題(時にはnullでも、特定のモデルのデバイスでも常に同じIDが返される場合があります)を回避するには、さまざまな方法があります。

  • カスタムID生成アルゴリズムを実装する(静的で、変更されないはずのデバイスプロパティに基づく - >知っている人)
  • _ imei _ などの他のID、シリアル番号、Wi-Fi/Bluetooth-MACアドレスを悪用する(それらはすべてのデバイスに存在するわけではない、または追加の権限が必要になる)

私は自分でAndroid用の既存のOpenUDID実装( https://github.com/ylechelle/OpenUDID を参照)を使用することを好む( https://github.com/vieux/OpenUDID を参照)。統合するのは簡単で、上記の問題のためのフォールバックでAndroid_IDを利用します。

8
Andreas Klöber

私の2セント - NBこれはdevice(err)unique IDのためのものです - Android開発者のブログで議論されたようなインストールのものではありません

SharedPreferencesはプロセス間で同期されないため、@ emmbyによって提供される solution はアプリケーションIDごとに分類されることに注意してください( here および here を参照)。だから私はこれを完全に避けました。

代わりに、私は列挙型の中で(デバイス)IDを取得するためのさまざまな戦略をカプセル化しました - 列挙型定数の順序を変更することはIDを取得するさまざまな方法の優先順位に影響します。最初のnull以外のIDが返されるか、例外がスローされます(nullを意味しないというJavaの優良な慣例に従って)。それで例えば私は最初にTELEPHONYを持っています - しかしデフォルトの良い選択はAndroid_ID betaでしょう:

import Android.Manifest.permission;
import Android.bluetooth.BluetoothAdapter;
import Android.content.Context;
import Android.content.pm.PackageManager;
import Android.net.wifi.WifiManager;
import Android.provider.Settings.Secure;
import Android.telephony.TelephonyManager;
import Android.util.Log;

// TODO : hash
public final class DeviceIdentifier {

    private DeviceIdentifier() {}

    /** @see http://code.google.com/p/Android/issues/detail?id=10603 */
    private static final String Android_ID_BUG_MSG = "The device suffers from "
        + "the Android ID bug - its ID is the emulator ID : "
        + IDs.BUGGY_Android_ID;
    private static volatile String uuid; // volatile needed - see EJ item 71
    // need lazy initialization to get a context

    /**
     * Returns a unique identifier for this device. The first (in the order the
     * enums constants as defined in the IDs enum) non null identifier is
     * returned or a DeviceIDException is thrown. A DeviceIDException is also
     * thrown if ignoreBuggyAndroidID is false and the device has the Android ID
     * bug
     *
     * @param ctx
     *            an Android constant (to retrieve system services)
     * @param ignoreBuggyAndroidID
     *            if false, on a device with the Android ID bug, the buggy
     *            Android ID is not returned instead a DeviceIDException is
     *            thrown
     * @return a *device* ID - null is never returned, instead a
     *         DeviceIDException is thrown
     * @throws DeviceIDException
     *             if none of the enum methods manages to return a device ID
     */
    public static String getDeviceIdentifier(Context ctx,
            boolean ignoreBuggyAndroidID) throws DeviceIDException {
        String result = uuid;
        if (result == null) {
            synchronized (DeviceIdentifier.class) {
                result = uuid;
                if (result == null) {
                    for (IDs id : IDs.values()) {
                        try {
                            result = uuid = id.getId(ctx);
                        } catch (DeviceIDNotUniqueException e) {
                            if (!ignoreBuggyAndroidID)
                                throw new DeviceIDException(e);
                        }
                        if (result != null) return result;
                    }
                    throw new DeviceIDException();
                }
            }
        }
        return result;
    }

    private static enum IDs {
        TELEPHONY_ID {

            @Override
            String getId(Context ctx) {
                // TODO : add a SIM based mechanism ? tm.getSimSerialNumber();
                final TelephonyManager tm = (TelephonyManager) ctx
                        .getSystemService(Context.TELEPHONY_SERVICE);
                if (tm == null) {
                    w("Telephony Manager not available");
                    return null;
                }
                assertPermission(ctx, permission.READ_PHONE_STATE);
                return tm.getDeviceId();
            }
        },
        Android_ID {

            @Override
            String getId(Context ctx) throws DeviceIDException {
                // no permission needed !
                final String andoidId = Secure.getString(
                    ctx.getContentResolver(),
                    Android.provider.Settings.Secure.Android_ID);
                if (BUGGY_Android_ID.equals(andoidId)) {
                    e(Android_ID_BUG_MSG);
                    throw new DeviceIDNotUniqueException();
                }
                return andoidId;
            }
        },
        WIFI_MAC {

            @Override
            String getId(Context ctx) {
                WifiManager wm = (WifiManager) ctx
                        .getSystemService(Context.WIFI_SERVICE);
                if (wm == null) {
                    w("Wifi Manager not available");
                    return null;
                }
                assertPermission(ctx, permission.ACCESS_WIFI_STATE); // I guess
                // getMacAddress() has no Java doc !!!
                return wm.getConnectionInfo().getMacAddress();
            }
        },
        BLUETOOTH_MAC {

            @Override
            String getId(Context ctx) {
                BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
                if (ba == null) {
                    w("Bluetooth Adapter not available");
                    return null;
                }
                assertPermission(ctx, permission.BLUETOOTH);
                return ba.getAddress();
            }
        }
        // TODO PSEUDO_ID
        // http://www.pocketmagic.net/2011/02/Android-unique-device-id/
        ;

        static final String BUGGY_Android_ID = "9774d56d682e549c";
        private final static String TAG = IDs.class.getSimpleName();

        abstract String getId(Context ctx) throws DeviceIDException;

        private static void w(String msg) {
            Log.w(TAG, msg);
        }

        private static void e(String msg) {
            Log.e(TAG, msg);
        }
    }

    private static void assertPermission(Context ctx, String perm) {
        final int checkPermission = ctx.getPackageManager().checkPermission(
            perm, ctx.getPackageName());
        if (checkPermission != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Permission " + perm + " is required");
        }
    }

    // =========================================================================
    // Exceptions
    // =========================================================================
    public static class DeviceIDException extends Exception {

        private static final long serialVersionUID = -8083699995384519417L;
        private static final String NO_Android_ID = "Could not retrieve a "
            + "device ID";

        public DeviceIDException(Throwable throwable) {
            super(NO_Android_ID, throwable);
        }

        public DeviceIDException(String detailMessage) {
            super(detailMessage);
        }

        public DeviceIDException() {
            super(NO_Android_ID);
        }
    }

    public static final class DeviceIDNotUniqueException extends
            DeviceIDException {

        private static final long serialVersionUID = -8940090896069484955L;

        public DeviceIDNotUniqueException() {
            super(Android_ID_BUG_MSG);
        }
    }
}
7
Mr_and_Mrs_D

_ imei _ はどうですか。それはAndroidや他のモバイル機器に特有です。

7
Elzo Valugi

これが私がどのようにしてユニークなIDを生成しているかです:

public static String getDeviceId(Context ctx)
{
    TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);

    String tmDevice = tm.getDeviceId();
    String androidId = Secure.getString(ctx.getContentResolver(), Secure.Android_ID);
    String serial = null;
    if(Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) serial = Build.SERIAL;

    if(tmDevice != null) return "01" + tmDevice;
    if(androidId != null) return "02" + androidId;
    if(serial != null) return "03" + serial;
    // other alternatives (i.e. Wi-Fi MAC, Bluetooth MAC, etc.)

    return null;
}
7
Eng.Fouad

もう1つの方法は、パーミッションなしでアプリで/sys/class/Android_usb/Android0/iSerialを使用することです。

user@creep:~$ adb Shell ls -l /sys/class/Android_usb/Android0/iSerial
-rw-r--r-- root     root         4096 2013-01-10 21:08 iSerial
user@creep:~$ adb Shell cat /sys/class/Android_usb/Android0/iSerial
0A3CXXXXXXXXXX5

Javaでこれを行うには、FileInputStreamを使用してiSerialファイルを開き、文字を読み取るだけです。すべてのデバイスにこのファイルがあるわけではないので、必ず例外ハンドラでラップしてください。 

少なくとも以下のデバイスがこのファイルを世界的に読み取り可能にすることが知られています。

  • ギャラクシーネクサス
  • ネクサスS
  • モトローラXoom 3G
  • 東芝AT300
  • HTC One V
  • ミニMK802
  • サムスンギャラクシーS II

あなたは私のブログ記事を見ることもできます特権のないアプリにAndroidのハードウェアのシリアル番号を漏らしているここで私は他のどのようなファイルが情報として利用できるかを議論します。

6
insitusec

具体的には、Settings.Secure.Android_IDです。これは、デバイスが最初に起動したときに生成および保存される64ビットの量です。デバイスが消去されるとリセットされます。

Android_IDは、一意のデバイス識別子に適しています。欠点:まず、2.2 (“Froyo”).より前のAndroidのリリースでは100%信頼できるわけではありません。また、すべてのインスタンスが同じAndroid_IDを持つ大手メーカーの広く知られた携帯電話に、少なくとも1つの広く見られるバグがあります。

6
mumu123

私は次のコードを使用してIMEIを取得するか、デバイスに電話機能がない場合はSecure .Android_IDを代わりに使用します。

String identifier = null;
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE));
if (tm != null)
      identifier = tm.getDeviceId();
if (identifier == null || identifier .length() == 0)
      identifier = Secure.getString(activity.getContentResolver(),Secure.Android_ID);
6
Asaf Pinhassi

ここに30以上の答えがあります、そしていくつかは同じですそしていくつかはユニークです。この答えはそれらの答えのいくつかに基づいています。そのうちの1人が@Lenn Dollingの答えです。

これは3つのIDを組み合わせて32桁の16進数ストリングを作成します。それは私にとってとてもうまくいった。 

3つのIDは以下のとおりです。
擬似ID - 物理デバイスの仕様に基づいて生成されます。
Android_ID - Settings.Secure.Android_ID
Bluetoothアドレス - Bluetoothアダプタアドレス

それはこのような何かを返すでしょう: 551F27C060712A72730B0A0F734064B1

注:longId文字列には、いつでもIDを追加できます。たとえば、シリアル番号です。無線LANアダプタのアドレス。 IMEIこのように、あなたはそれをデバイスごとにもっとユニークにしています。

@SuppressWarnings("deprecation")
@SuppressLint("HardwareIds")
public static String generateDeviceIdentifier(Context context) {

        String pseudoId = "35" +
                Build.BOARD.length() % 10 +
                Build.BRAND.length() % 10 +
                Build.CPU_ABI.length() % 10 +
                Build.DEVICE.length() % 10 +
                Build.DISPLAY.length() % 10 +
                Build.Host.length() % 10 +
                Build.ID.length() % 10 +
                Build.MANUFACTURER.length() % 10 +
                Build.MODEL.length() % 10 +
                Build.PRODUCT.length() % 10 +
                Build.TAGS.length() % 10 +
                Build.TYPE.length() % 10 +
                Build.USER.length() % 10;

        String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.Android_ID);

        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        String btId = "";

        if (bluetoothAdapter != null) {
            btId = bluetoothAdapter.getAddress();
        }

        String longId = pseudoId + androidId + btId;

        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.update(longId.getBytes(), 0, longId.length());

            // get md5 bytes
            byte md5Bytes[] = messageDigest.digest();

            // creating a hex string
            String identifier = "";

            for (byte md5Byte : md5Bytes) {
                int b = (0xFF & md5Byte);

                // if it is a single digit, make sure it have 0 in front (proper padding)
                if (b <= 0xF) {
                    identifier += "0";
                }

                // add number to string
                identifier += Integer.toHexString(b);
            }

            // hex string to uppercase
            identifier = identifier.toUpperCase();
            return identifier;
        } catch (Exception e) {
            Log.e("TAG", e.toString());
        }
        return "";
}

特定のAndroidデバイスをハードウェアで認識するために、MACアドレスを確認することができます。

そうすることができます:

androidManifest.xmlの中の

<uses-permission Android:name="Android.permission.INTERNET" />

今すぐあなたのコードで:

List<NetworkInterface> interfacesList = Collections.list(NetworkInterface.getNetworkInterfaces());

for (NetworkInterface interface : interfacesList) {
   // This will give you the interface MAC ADDRESS
   interface.getHardwareAddress();
}

すべてのAndroidデバイスで、それらは少なくとも "wlan0"インターフェースの魔女がWI-FIチップです。

P.S。それらはあなたがMACSを含むリストから得るであろう他のインターフェースの束ですしかし、これは電話の間で変わることができます。

6
Ilan.b

GoogleインスタンスID

I/O 2015でリリースされました。 Android上でプレイサービス7.5が必要です。

https://developers.google.com/instance-id/
https://developers.google.com/instance-id/guides/Android-implementation

InstanceID iid = InstanceID.getInstance( context );   // Google docs are wrong - this requires context
String id = iid.getId();  // blocking call

グーグルは、このIDがAndroid、Chrome、そしてiOSのインストールを識別するために使われることを意図しているようです。

これはデバイスではなくインストールを識別しますが、Android_ID(これは受け入れられた回答です)はデバイスを識別しなくなりました。 ARCランタイムでは、この新しいインスタンスIDのように、インストールごとに新しいAndroid_IDが生成されます( 詳細はここ )。また、私たちのほとんどが実際に探しているのは、(デバイスではなく)インストールを識別することです。

インスタンスIDの利点

グーグルはそれをこの目的のために(あなたのインストールを識別するために)使うことを意図している、それはクロスプラットフォームであり、そして他の多くの目的のために使うことができるように思う.

GCMを使用している場合は、GCMトークン(古いGCM登録IDを置き換えるもの)を取得するために必要なので、このインスタンスIDを使用する必要があります。

不利な点/問題

現在の実装(GPS 7.5)では、アプリが要求したときにインスタンスIDがサーバーから取得されます。これは、上記の呼び出しがブロッキング呼び出しであることを意味します。私の科学的でないテストでは、デバイスがオンラインの場合は1〜3秒、オフラインの場合は0.5〜1.0秒かかります。ランダムID)。これは、Android 5.1.1とGPS 7.5を搭載したNexus 5の北米でテストされています。

あなたが彼らが意図する目的のためにIDを使うならば - 例えば。アプリの認証、アプリの識別、GCM - この1〜3秒は迷惑になる可能性があると思います(もちろん、アプリによって異なります)。

5
Tom

AndroidデバイスのMac IDも一意のIDです。MacIDを取得するには次のコードを使用してデバイス自体をフォーマットしても変わりません

WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = manager.getConnectionInfo();
String address = info.getMacAddress();

また、適切な permissions をあなたの AndroidManifest.xmlに追加することを忘れないでください。

<uses-permission Android:name="Android.permission.ACCESS_WIFI_STATE"/>

TelephonyManger.getDeviceId() GSMの場合はIMEI、CDMA電話の場合はMEIDまたはESNなどの一意のデバイスIDを返します。

final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);            
String myAndroidDeviceId = mTelephony.getDeviceId(); 

しかし、私は使用することをお勧めします:

Settings.Secure.Android_ID これは、Android IDを一意の64ビットの16進数文字列として返します。

    String   myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.Android_ID); 

TelephonyManger.getDeviceId() がnullを返すことがあるので、一意のIDを保証するためにこのメソッドを使用します。

public String getUniqueID(){    
    String myAndroidDeviceId = "";
    TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    if (mTelephony.getDeviceId() != null){
        myAndroidDeviceId = mTelephony.getDeviceId(); 
    }else{
         myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.Android_ID); 
    }
    return myAndroidDeviceId;
}
5
Elenasys

Googleは Advertising ID を持っています。
これも使用できますが、以下の点に注意してください。

広告IDは、ユーザー固有の一意のリセット可能なIDです。 

そして

ユーザーが自分の識別子をリセットしたり、Google Playアプリ内のインタレストベース広告をオプトアウトしたりできるようにします。

したがって、このIDは変更される可能性がありますが、間もなく 選択できない可能性があります 、このIDの目的によって異なります。

詳細情報@ develper.Android

ここにコードをコピーして貼り付けてください

HTH

4

1.GmsサービスでAndroidデバイスIDにアクセスできます。下記の例を参照してください。

private DeviceInfoProvider mDeviceInfo = new DeviceInfoProvider(Context)
String mDeviceId = DeviceInfoProvider.getDeviceId(Context);
Log.d("DEVICE_ID" , mDeviceId);

固有のID(すなわちIMEI)を提供するテレフォニーマネージャを使用する。例を見てください。

import Android.telephony.TelephonyManager;
import Android.content.Context;
// ...
TelephonyManager telephonyManager;
telephonyManager = (TelephonyManager) getSystemService(Context.
                TELEPHONY_SERVICE);
/*
* getDeviceId() returns the unique device ID.
* For example,the IMEI for GSM and the MEID or ESN for CDMA phones.
*/
String deviceId = telephonyManager.getDeviceId();
/*
* getSubscriberId() returns the unique subscriber ID,
*/
String subscriberId = telephonyManager.getSubscriberId();

これにはあなたのユーザーにAndroid.permission.READ_PHONE_STATEが必要ですが、あなたが作ったアプリケーションの種類に従うことを正当化するのは難しいかもしれません。

  1. タブレットのようなテレフォニーサービスを持たないデバイスは、Android 2.3 Gingerbread以降、Android.os.Build.SERIALを介して利用可能な固有のデバイスIDを報告する必要があります。テレフォニーサービスを持つ電話の中には、シリアル番号を定義するものもあります。すべてのAndroidデバイスにシリアル番号が付いているわけではないので、この解決策は信頼できません。

  2. デバイスの初回起動時に、ランダムな値が生成されて保存されます。この値はSettings.Secure.Android_IDから入手できます。これは64ビットの数値なので、デバイスの寿命まで一定に保たれるはずです。 Android_IDは、スマートフォンやタブレットで使用できるため、一意のデバイス識別子として適しています。値を取得するには、次のコードを使用できます。

    文字列androidId = Settings.Secure.getString(getContentResolver()、 Settings.Secure.Android_ID);

ただし、デバイスで出荷時設定へのリセットが実行されると、値が変わる可能性があります。すべてのインスタンスが同じAndroid_IDを持つ製造元からの人気のあるハンドセットには既知のバグもあります。明らかに、解決策は100%信頼できません。

  1. UUIDを使用してください。ほとんどのアプリケーションの要件は、物理デバイスではなく特定のインストールを識別することであるため、UUIDクラスを使用する場合はユーザーの固有のIDを取得するための優れた解決策です。次のソリューションは、GoogleのReto MeierによってGoogle I/Oプレゼンテーションで発表されました。

SharedPreferences sharedPrefs = context.getSharedPreferences( PREF_UNIQUE_ID, Context.MODE_PRIVATE); uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);

4
Kiran Maniya

DeviceIdはサードパーティの手による追跡として使用できるので推奨されませんが、これは別の方法です。

@SuppressLint("HardwareIds")
private String getDeviceID() {
    deviceId = Settings.Secure.getString(getApplicationContext().getContentResolver(),
                    Settings.Secure.Android_ID);
    return deviceId;
}
3

私は数年前にこの問題に出会い、さまざまな答えに基づいて一般化されたソリューションを実装することを学びました。

私は実世界の製品で、一般化されたソリューションを数年間使用してきました。それは今のところ非常にうまくいっています。これは、提供されたさまざまな回答に基づいたコードスニペットです。

明示的に許可を求めなかったので、getEmailはほとんどの場合nullを返します。

private static UniqueId getUniqueId() {
    MyApplication app = MyApplication.instance();

    // Our prefered method of obtaining unique id in the following order.
    // (1) Advertising id
    // (2) Email
    // (2) Android_ID
    // (3) Instance ID - new id value, when reinstall the app.

    ////////////////////////////////////////////////////////////////////////////////////////////
    // ADVERTISING ID
    ////////////////////////////////////////////////////////////////////////////////////////////
    AdvertisingIdClient.Info adInfo = null;
    try {
        adInfo = AdvertisingIdClient.getAdvertisingIdInfo(app);
    } catch (IOException e) {
        Log.e(TAG, "", e);
    } catch (GooglePlayServicesNotAvailableException e) {
        Log.e(TAG, "", e);
    } catch (GooglePlayServicesRepairableException e) {
        Log.e(TAG, "", e);
    }

    if (adInfo != null) {
        String aid = adInfo.getId();
        if (!Utils.isNullOrEmpty(aid)) {
            return UniqueId.newInstance(aid, UniqueId.Type.aid);
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////
    // EMAIL
    ////////////////////////////////////////////////////////////////////////////////////////////
    final String email = Utils.getEmail();
    if (!Utils.isNullOrEmpty(email)) {
        return UniqueId.newInstance(email, UniqueId.Type.eid);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////
    // Android ID
    ////////////////////////////////////////////////////////////////////////////////////////////
    final String sid = Settings.Secure.getString(app.getContentResolver(), Settings.Secure.Android_ID);
    if (!Utils.isNullOrEmpty(sid)) {
        return UniqueId.newInstance(sid, UniqueId.Type.sid);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////
    // INSTANCE ID
    ////////////////////////////////////////////////////////////////////////////////////////////
    final String iid = com.google.Android.gms.iid.InstanceID.getInstance(MyApplication.instance()).getId();
    if (!Utils.isNullOrEmpty(iid)) {
        return UniqueId.newInstance(iid, UniqueId.Type.iid);
    }

    return null;
}

public final class UniqueId implements Parcelable {
    public enum Type implements Parcelable {
        aid,
        sid,
        iid,
        eid;

        ////////////////////////////////////////////////////////////////////////////
        // Handling Parcelable nicely.

        public static final Parcelable.Creator<Type> CREATOR = new Parcelable.Creator<Type>() {
            public Type createFromParcel(Parcel in) {
                return Type.valueOf(in.readString());
            }

            public Type[] newArray(int size) {
                return new Type[size];
            }
        };

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel parcel, int flags) {
            parcel.writeString(this.name());
        }

        // Handling Parcelable nicely.
        ////////////////////////////////////////////////////////////////////////////
    }

    public static boolean isValid(UniqueId uniqueId) {
        if (uniqueId == null) {
            return false;
        }
        return uniqueId.isValid();
    }

    private boolean isValid() {
        return !org.yccheok.jstock.gui.Utils.isNullOrEmpty(id) && type != null;
    }

    private UniqueId(String id, Type type) {
        if (org.yccheok.jstock.gui.Utils.isNullOrEmpty(id) || type == null) {
            throw new Java.lang.IllegalArgumentException();
        }
        this.id = id;
        this.type = type;
    }

    public static UniqueId newInstance(String id, Type type) {
        return new UniqueId(id, type);
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + id.hashCode();
        result = 31 * result + type.hashCode();
        return result;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }

        if (!(o instanceof UniqueId)) {
            return false;
        }

        UniqueId uniqueId = (UniqueId)o;
        return this.id.equals(uniqueId.id) && this.type == uniqueId.type;
    }

    @Override
    public String toString() {
        return type + ":" + id;
    }

    ////////////////////////////////////////////////////////////////////////////
    // Handling Parcelable nicely.

    public static final Parcelable.Creator<UniqueId> CREATOR = new Parcelable.Creator<UniqueId>() {
        public UniqueId createFromParcel(Parcel in) {
            return new UniqueId(in);
        }

        public UniqueId[] newArray(int size) {
            return new UniqueId[size];
        }
    };

    private UniqueId(Parcel in) {
        this.id = in.readString();
        this.type = in.readParcelable(Type.class.getClassLoader());
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeString(this.id);
        parcel.writeParcelable(this.type, 0);
    }

    // Handling Parcelable nicely.
    ////////////////////////////////////////////////////////////////////////////

    public final String id;
    public final Type type;
}

public static String getEmail() {
    Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
    AccountManager accountManager = AccountManager.get(MyApplication.instance());
    Account[] accounts = accountManager.getAccountsByType("com.google");
    for (Account account : accounts) {
        if (emailPattern.matcher(account.name).matches()) {
            String possibleEmail = account.name;
            return possibleEmail;
        }
    }

    accounts = accountManager.getAccounts();
    for (Account account : accounts) {
        if (emailPattern.matcher(account.name).matches()) {
            String possibleEmail = account.name;
            return possibleEmail;
        }
    }

    return null;
} 
2
Cheok Yan Cheng

これは、AAIDを取得するための簡単な答えです。2019年6月に正常に動作することをテスト済みです

 AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
        @Override
        protected String doInBackground(Void... params) {
            String token = null;
            Info adInfo = null;
            try {
                adInfo = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext());
            } catch (IOException e) {
                // ...
            } catch ( GooglePlayServicesRepairableException e) {
                // ...
            } catch (GooglePlayServicesNotAvailableException e) {
                // ...
            }
            String Android_id = adInfo.getId();
            Log.d("DEVICE_ID",Android_id);

            return Android_id;
        }

        @Override
        protected void onPostExecute(String token) {
            Log.i(TAG, "DEVICE_ID Access token retrieved:" + token);
        }

    };
    task.execute();

完全な回答を詳細に読む here

2
Raj

Androidデバイスで利用可能なユニークIDを理解する。この公式ガイドを使ってください。

一意の識別子のベストプラクティス:

IMEI、Macアドレス、インスタンスID、GUID、SSAID、アドバタイズID、デバイスを検証するためのSafety Net API。

https://developer.Android.com/training/articles/user-data -ids

2
Waheed Nazir

最新の情報をもっと探している人全員が読むことに向かいます。 Android Oでは、システムがこれらのIDを管理する方法にいくつかの変更があります。 

https://Android-developers.googleblog.com/2017/04/changes-to-device-identifiers-in.html

tl; dr SerialはPHONE許可を必要とし、Android IDはそれらのパッケージ名と署名に基づいて異なるアプリごとに変わります。

また、Googleは、ハードウェアIDとソフトウェアIDをいつ使用するかについての提案を提供するNice文書をまとめました。

https://developer.Android.com/training/articles/user-data -ids.html

1
wrecker

通常、アプリにはデバイス固有のIDを使用します。しかしいつか私はIMEIを使います。どちらも固有の番号です。

_ imei _ 国際携帯機器識別子 )を取得します。

public String getIMEI(Activity activity) {
    TelephonyManager telephonyManager = (TelephonyManager) activity
            .getSystemService(Context.TELEPHONY_SERVICE);
    return telephonyManager.getDeviceId();
}

デバイス固有のIDを取得する

public String getDeviceUniqueID(Activity activity){
    String device_unique_id = Secure.getString(activity.getContentResolver(),
            Secure.Android_ID);
    return device_unique_id;
}
1
Zin Win Htet

シリアル番号は、Android.os.Build.SERIALから入手できる固有のデバイスIDです。

public static String getSerial() {
    String serial = "";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
        serial = Build.getSerial();
    }else{ 
        serial = Build.SERIAL;    
    }
    return serial;
}

GetSerial()を呼び出す前に、READ_PHONE_STATE権限があることを確認してください。

NOTE: - それは電話のないデバイスでは利用できません(wifi専用タブレットのように)です。

1
Shivam Agrawal

ユーザーIDを取得するには、Google Playライセンスライブラリを使用できます。

このライブラリをダウンロードするには、SDK Manager => SDK Toolsを開きます。ダウンロードしたライブラリファイルへのパスは次のとおりです。

path_to_Android_sdk_on_your_pc/extras/google/market_licensing/library

ライブラリをプロジェクトに含めます(ファイルを単にコピーできます)。

次に、Policyインターフェースの実装が必要です(ライブラリーからの2つのファイルのいずれかを使用できます:ServerManagedPolicyまたはStrictPolicy)。

ユーザーIDはprocessServerResponse()関数内で提供されます:

public void processServerResponse(int response, ResponseData rawData) {
    if(rawData != null) {
        String userId = rawData.userId
        // use/save the value
    }
    // ...
}

次に、ポリシーを使用してLicenseCheckerを構築し、checkAccess()関数を呼び出す必要があります。方法の例としてMainActivity.Javaを使用します。 MainActivity.Javaはこのフォルダー内にあります。

path_to_Android_sdk_on_your_pc/extras/google/market_licensing/sample/src/com/example/Android/market/licensing

AndroidManifest.xmlにCHECK_LICENSE権限を追加することを忘れないでください。

ライセンスライブラリの詳細: https://developer.Android.com/google/play/licensing

0
String SERIAL_NUMER = Build.SERIAL;

SERIAL NUMBERを各デバイスで一意の文字列として返します。 

0
Jeffy

Android 9 を含めるために/私はまだうまくいく可能性のあるアイデアを1つだけ持っています。 

指紋認証 サーバーを使用することで、デバイスを一意に識別できるようにする必要があります。 最初のインストール時間は、アプリをアンインストールしてから再インストールしない限り変わりません。しかし、これは、デバイスを識別できないようにするために(つまり、工場出荷時設定へのリセット後に)デバイス上のすべてのアプリに対して実行する必要があります。 

これは私がそれに取り組む方法です:

  1. ハードウェア情報、アプリケーションパッケージ名、初回インストール時間を抽出します。 

これは、Androidからすべてのアプリケーションを抽出する方法です(権限は必要ありません)。

final PackageManager pm = application.getPackageManager();
List<ApplicationInfo> packages = 
pm.getInstalledApplications(PackageManager.GET_META_DATA);

for (ApplicationInfo packageInfo : packages) {
    try {
        Log.d(TAG, "Installed package :" + packageInfo.packageName);
        Log.d(TAG, "Installed :" + pm.getPackageInfo(packageInfo.packageName, 0).firstInstallTime);
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
}
  1. サーバーに送信する前に、各パッケージ名とインストールタイムスタンプの組み合わせのハッシュを作成することをお勧めします。これは、ユーザーがデバイスにインストールしたものと関係ない場合があるためです。
  2. 一部のアプリ(実際にはたくさんのアプリ)はシステムアプリです。これらは、工場出荷時設定へのリセット後の最新のシステムアップデートと一致する、同じインストールタイムスタンプを持つ可能性があります。それらは同じインストールタイムスタンプを持っているので、それらはユーザによってインストールされることができず、除外されることができます。
  3. 情報をサーバーに送信し、以前に保存した情報の中で最も近いものを探すようにします。アプリのインストールおよびアンインストール時に、以前に保存したデバイス情報と比較するときには、しきい値を設定する必要があります。ただし、パッケージ名と初回インストールのタイムスタンプの組み合わせだけでもデバイスごとに固有のものになり、アプリのインストールやアンインストールが頻繁に行われるわけではないため、このしきい値は非常に低くなります。複数のアプリを持つことは、ユニークである可能性を高めるだけです。 
  4. 一致に対して生成された一意のIDを返すか、一意のIDを生成し、デバイス情報を格納してこの新しいIDを返します。

NB: これはテストされていない証明されていない方法です!私はそれがうまくいくと確信しています、しかしこれがつかまえれば、彼らはそれが何らかの形でそれを閉鎖するであろうこともかなり確かです。 

0
Jens Vesti

デバイスIDを1回だけ取得してから、データベースまたはファイルに保存します。この場合、アプリの初回起動時にIDを生成して保存します。次回は、ファイルに格納されているIDのみを取ります。

0
El Jazouli

追加する場合:

Settings.Secure.getString(context.contentResolver,
    Settings.Secure.Android_ID)

Android Lintは次の警告を表示します。

GetStringを使用してデバイス識別子を取得することはお勧めしません。検査情報:これらのデバイス識別子の使用は、価値の高い不正防止と高度な電話の使用例以外には推奨されません。広告のユースケースにはAdvertisingIdClient $ Info#getIdを使用し、分析にはInstanceId#getIdを使用します。

だから、これを使うことは避けるべきだ。

Android Developer documentation で述べたように:

1:ハードウェア識別子の使用を避けます。

ほとんどのユースケースでは、必要な機能を制限することなく、SSAID(Android ID)やIMEIなどのハードウェア識別子の使用を回避できます。

2:ユーザープロファイリングまたは広告のユースケースにのみ広告IDを使用します。

広告IDを使用するときは、広告追跡に関するユーザーの選択を常に尊重してください。また、IDを個人を特定できる情報(PII)に接続できないようにし、広告IDのリセットの橋渡しを避けます。

3:支払い詐欺防止と電話を除く他のすべてのユースケースでは、可能な限りインスタンスIDまたはプライベートに保存されたGUIDを使用します。

広告以外のユースケースの大半では、インスタンスIDまたはGUIDで十分です。

4:プライバシーリスクを最小限に抑えるために、ユースケースに適したAPIを使用します。

価値の高いコンテンツ保護にはDRM APIを使用し、不正行為保護にはSafetyNet APIを使用します。 SafetyNet APIは、プライバシーリスクを招くことなく、デバイスが本物かどうかを判断する最も簡単な方法です。

0
Malwinder Singh

完全を期すために、Xamarin.AndroidとC#でIdを取得する方法を次に示します。

var id = Settings.Secure.GetString(ContentResolver, Settings.Secure.AndroidId);

あるいはあなたがActivityの中にいないのなら:

var id = Settings.Secure.GetString(context.ContentResolver, Settings.Secure.AndroidId);

contextは渡されたコンテキストです。

0
Martin Zikmund