Androidデバイスのシリアル番号を見つける方法は?


115

Androidアプリには一意のIDを使用する必要があり、デバイスのシリアル番号が適していると思いました。アプリでAndroidデバイスのシリアル番号を取得するにはどうすればよいですか?


2
マニフェストにandroid:name = "android.permission.READ_PHONE_STATE"を追加することを忘れないでください
Michael SIlveus


何も権限なしで一意のIDを取得したい場合は、使用することができ、このライブラリを持つデバイスごとに固有のIDのいずれかを生成するためにIdentity.getDeviceId(文脈)または経由でアプリのインストール用の識別子Identity.getInstallationId(コンテキスト)
2015年

回答:


105
TelephonyManager tManager = (TelephonyManager)myActivity.getSystemService(Context.TELEPHONY_SERVICE);
String uid = tManager.getDeviceId();

getSystemServiceは、Activityクラスのメソッドです。getDeviceID()は、電話が使用する無線(GSMまたはCDMA)に応じて、デバイスのMDNまたはMEIDを返します。

各デバイスは、ここで一意の値を返す必要があります(電話であると想定)。これは、SIMスロットまたはCDMA無線を備えたAndroidデバイスで機能します。あなたは自分でAndroid搭載の電子レンジを使っています;-)


@Hasemamこれは私には機能せず、「強制終了」エラーが発生します
Paresh Mayani '26

23
@Hasemamは、androidManifest.xmlファイルに<uses-permission android:name = "android.permission.READ_PHONE_STATE"> </ uses-permission>権限を追加した後、正常に動作します。
パレシュマヤニ

23
そこの識別子を使用してについて、公式のAndroid開発者のブログでいくつかのアドバイスです:android-developers.blogspot.com/2011/03/...
デヴィッドSnabel-Caunt

8
Android搭載の電子レンジを除いて、Android搭載のタブレットはどうですか?:)
ajacian81

21
この方法は避けてください。これは電話では機能しますが、電話チップのないデバイスでは機能しません(タブレットはその一例です)。2.3以降では、android.os.Build.SERIALを使用できますが、@ DavidCauntが提案した開発者ブログをチェックしてください。
John Mitchell

71

Dave Webbが言及しているように、Android開発者ブログにはこれをカバーする記事があります。

Googleの担当者と話し合って、いくつかの項目についてさらに説明を求めました。前述のブログの投稿に記載されていない、私が見つけたものは次のとおりです。

  • ANDROID_IDが推奨されるソリューションです。ANDROID_IDは、Android <= 2.1または> = 2.3のバージョンで完全に信頼できます。投稿で言及されている問題があるのは2.2だけです。
  • 複数の製造元によるいくつかのデバイスは、2.2のANDROID_IDバグの影響を受けます。
  • 私が判断できる限り、影響を受けるすべてのデバイスは同じANDROID_IDを持ってます。これは9774d56d682e549cです。これは、エミュレーターによって報告された同じデバイスIDでもあります。
  • Googleは、OEMがデバイスの多くまたはほとんどのデバイスにこの問題にパッチを適用していると考えていますが、2011年4月の初めの時点で、少なくともANDROID_IDが壊れているデバイスを見つけるのは非常に簡単であることを確認できました。

Googleの推奨事項に基づいて、必要に応じてANDROID_IDをシードとして使用し、必要に応じてTelephonyManager.getDeviceId()にフォールバックして、デバイスごとに一意のUUIDを生成するクラスを実装しました。失敗した場合は、ランダムに生成された一意のUUIDを使用しましたアプリの再起動後も保持されます(アプリの再インストールは不可)。

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 static volatile 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;
    }
}

1
アプリがこれを使用するにはどのような権限が必要ですか?
Dave L.

1
<uses-permission android:name = "android.permission.READ_PHONE_STATE"> </ uses-permission>
ガブリエル

1
@ ef2011これはダブルチェックされたロックパターンです:en.wikipedia.org/wiki/Double-checked_locking
emmby

3
投稿いただきありがとうございます。しかし、ルート化された電話を持つ誰かがdevice_id.xmlを編集して、選択した新しいUUIDを入力するのを止めるにはどうすればよいでしょうか。(つまり、「無料トライアル」チェックを回避するために)ランダムIDメソッドに頼る必要がある場合、クラスが設定ファイルに値を格納するだけの方がいいのではないでしょうか。それ以外の場合は、アプリケーションの実行間で永続化する必要はありません。再生成する方が安全です。
Carlos P

1
「ANDROID_ID」が推奨されるソリューションです。ANDROID_IDがデバイスを一意に識別しなくなったことに注意してください:stackoverflow.com/a/13465373/150016
Tom

32
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) {
}

このコードは、非表示のAndroid APIを使用してデバイスのシリアル番号を返します。


7
これにより、android.os.Build.SERIALで取得したものと同じ値が得られます
josephus

私は間違っていますか、またはこのシリアル番号は特定のカスタムROMを持つすべてのデバイスで同じですか?デバイスのシリアル番号(Eclipseデバイスランチャー内)に、カスタムromのある電話の01234567890ABCが表示されます。
Peterdk 2013年

シアン-9の両方の方法を備えた私のデバイスの@Peterdkは、両方の方法(答えのようにpre andy-9とandy-9から入手できるより簡単な方法)で正しいs / nを報告します(メーカーのステッカーと同じ)。ただし、特定のカスタムromバージョンによって異なる場合があります。使用しているrom /バージョンは何ですか?
morgwai 2013

16
String deviceId = Settings.System.getString(getContentResolver(),
                                Settings.System.ANDROID_ID);

ただし、Android IDが一意の識別子になることは保証されていません。


@Paresh Mayani、コードを見ないで問題の原因を特定するのは困難です。私の唯一の仮定は、それgetContentResolverが戻ってくることnullです。ただし、質問を開いてコードを投稿する間は価値があります。
Anthony Forloney、2010

4
このIDは、電話に関連付けられているGoogleアカウントから取得されます。通常、シミュレーターにはありません。実際の電話にもないかもしれません。また、「出荷時設定へのリセット時に変更できる」と記載されており、ルート権限を取得した携帯電話ではいつでも任意に変更できます。自己責任。良い代替手段はありません。他の仮のデバイスIDは、普遍的に利用できないか、一意ではないか、またはその両方です。この悲しい話の残りについては、他の回答を参照してください。
Seva Alekseyev、2011

14

これについては、Android開発者のブログに優れた投稿があります。

TelephonyManager.getDeviceId()タブレットなどの電話以外のAndroidデバイスではREAD_PHONE_STATE機能せず、許可が必要であり、すべての電話で確実に機能するわけではないため、使用しないことをお勧めします。

代わりに、次のいずれかを使用できます。

  • Macアドレス
  • シリアルナンバー
  • ANDROID_ID

この記事では、それぞれの長所と短所について説明しているので、読むのに最適です。


+1、ハイデーブ、説明ありがとうございます。現在、Androidデバイスの一意のIDが必要なタブレット用のアプリケーションを開発しているので、一意のAndroidタブレットデバイスを取得するには何を使用すればよいですか?
パレシマヤニ

12

デバイスに固有であり、デバイスの寿命が一定である単純な番号(工場出荷時のリセットまたはハッキングを除く)の場合は、Settings.Secure.ANDROID_IDを使用します。

String id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);

利用可能な場合にデバイスのシリアル番号(「システム設定/バージョン情報/ステータス」に表示されているもの)を使用してAndroid IDにフォールバックするには:

String serialNumber = Build.SERIAL != Build.UNKNOWN ? Build.SERIAL : Secure.getString(getContentResolver(), Secure.ANDROID_ID);

簡単な答え!!
faris faris 2017

Build.SERİALはJavaで非推奨
EyyüpAlkış

7

IMEIは優れていますが、携帯電話を備えたAndroidデバイスでのみ機能します。タブレットなど、スマートフォンを持たないAndroidデバイスのサポートも検討する必要があります。

クラスメンバー、BT MAC、WLAN MAC、またはそれ以上-これらすべての組み合わせをビルドするなど、いくつかの選択肢があります。

これらの詳細については、ブログの記事で説明しています。http//www.pocketmagic.net/?p = 1662を参照して ください。


6

以来何の答えはここに完璧に言及していない、失敗プルーフシステムアップデートを通じてPERSISTENTの両方で、すべてのデバイスに存在するID(主としてGoogleからの個別のソリューションが存在しないという事実のために)、私はある方法を掲示することにしました2つの使用可能な識別子を組み合わせることによる次善の策、および実行時にそれらの間で選択するチェック。

コードの前に、3つの事実:

  1. TelephonyManager.getDeviceId()(akaIMEI)は、非GSM、3G、LTEなどのデバイスではうまく機能しないか、まったく機能しませんが、関連するハードウェアが存在する場合、SIMが挿入されていない場合やSIMスロットが存在しない場合でも、常に一意のIDを返します(一部のOEMはこれを行っています)。

  2. Gingerbread(Android 2.3)android.os.Build.SERIAL は、IMEIを提供しない、つまりAndroidポリシーに従って前述のハードウェアが存在しないデバイスに存在する必要があるためです。

  3. 事実(2.)により、これら2つの一意の識別子の少なくとも1つは常に存在し、SERIAL IMEIと同時に存在できます。

注:事実(1.)および(2.)はGoogleの声明に基づいています

解決

上記の事実により、IMEIにバインドされたハードウェアがあるかどうかを確認することで一意の識別子を常に持つことができ、既存のSERIALが有効かどうかを確認できないため、ない場合はSERIALにフォールバックします。次の静的クラスは、そのような存在を確認し、IMEIまたはSERIALを使用するための2つのメソッドを示しています。

import java.lang.reflect.Method;

import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;

public class IDManagement {

    public static String getCleartextID_SIMCHECK (Context mContext){
        String ret = "";

        TelephonyManager telMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);

        if(isSIMAvailable(mContext,telMgr)){
            Log.i("DEVICE UNIQUE IDENTIFIER",telMgr.getDeviceId());
            return telMgr.getDeviceId();

        }
        else{
            Log.i("DEVICE UNIQUE IDENTIFIER", Settings.Secure.ANDROID_ID);

//          return Settings.Secure.ANDROID_ID;
            return android.os.Build.SERIAL;
        }
    }


    public static String getCleartextID_HARDCHECK (Context mContext){
        String ret = "";

        TelephonyManager telMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        if(telMgr != null && hasTelephony(mContext)){           
            Log.i("DEVICE UNIQUE IDENTIFIER",telMgr.getDeviceId() + "");

            return telMgr.getDeviceId();    
        }
        else{
            Log.i("DEVICE UNIQUE IDENTIFIER", Settings.Secure.ANDROID_ID);

//          return Settings.Secure.ANDROID_ID;
            return android.os.Build.SERIAL;
        }
    }


    public static boolean isSIMAvailable(Context mContext, 
            TelephonyManager telMgr){

        int simState = telMgr.getSimState();

        switch (simState) {
        case TelephonyManager.SIM_STATE_ABSENT:
            return false;
        case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
            return false;
        case TelephonyManager.SIM_STATE_PIN_REQUIRED:
            return false;
        case TelephonyManager.SIM_STATE_PUK_REQUIRED:
            return false;
        case TelephonyManager.SIM_STATE_READY:
            return true;
        case TelephonyManager.SIM_STATE_UNKNOWN:
            return false;
        default:
            return false;
        }
    }

    static public boolean hasTelephony(Context mContext)
    {
        TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        if (tm == null)
            return false;

        //devices below are phones only
        if (Build.VERSION.SDK_INT < 5)
            return true;

        PackageManager pm = mContext.getPackageManager();

        if (pm == null)
            return false;

        boolean retval = false;
        try
        {
            Class<?> [] parameters = new Class[1];
            parameters[0] = String.class;
            Method method = pm.getClass().getMethod("hasSystemFeature", parameters);
            Object [] parm = new Object[1];
            parm[0] = "android.hardware.telephony";
            Object retValue = method.invoke(pm, parm);
            if (retValue instanceof Boolean)
                retval = ((Boolean) retValue).booleanValue();
            else
                retval = false;
        }
        catch (Exception e)
        {
            retval = false;
        }

        return retval;
    }


}

の使用についてアドバイスしgetCleartextID_HARDCHECKます。反射が環境に定着しない場合は、getCleartextID_SIMCHECK代わりにメソッドを使用しますが、特定のSIM存在のニーズに適合させる必要があることを考慮してください。

PS:OEMはSERIALをGoogleのポリシー(同じSERIALの複数のデバイス)に対してなんとかバグアウトしていることに注意してください。また、Googleは大手OEMで少なくとも1つの既知のケースがある(非公開で、どのブランドかわからない)と述べています。それはどちらかです、私はサムスンを推測しています)。

免責事項:これは、一意のデバイスIDを取得するという元の質問に答えますが、OPは、APPに一意のIDが必要であると述べて、あいまいさをもたらしました。そのようなシナリオでAndroid_IDの方が優れている場合でも、たとえば、2つの異なるROMインストール(同じROMでもかまいません)を介したアプリのTitanium Backupの後では機能しません。私のソリューションは、フラッシュまたは工場出荷時のリセットに依存しない永続性を維持し、ハック/ハードウェアの改造を通じてIMEIまたはシリアルの改ざんが発生した場合にのみ失敗します。


5

上記のすべてのアプローチには問題があります。Google i / oで、Reto Meierは、インストール全体でユーザーを追跡するほとんどの開発者のニーズを満たす必要がある、これに取り組む方法に対する強力な回答をリリースしました。

このアプローチにより、匿名の安全なユーザーIDが提供されます。このユーザーIDは、さまざまなデバイス(タブレットを含む、プライマリGoogleアカウントに基づく)間、および同じデバイス上のインストール間でユーザーに対して永続的です。基本的なアプローチは、ランダムなユーザーIDを生成し、これをアプリの共有設定に保存することです。次に、Googleのバックアップエージェントを使用して、Googleアカウントにリンクされた共有設定をクラウドに保存します。

完全なアプローチを見てみましょう。最初に、Androidバックアップサービスを使用して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>

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

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の講演を参照してください。http://www.google.com/events/io/2011/sessions/android-protips-advanced-topics-for-expert-android-app-developers.html

そして、バックアップエージェントを実装する方法の詳細についてはこちらをデベロッパーサイトを参照してください。http://developer.android.com/guide/topics/data/backup.html バックアップがするように私は、特にテストに下部のセクションをお勧めします瞬間的には発生しないため、テストするにはバックアップを強制する必要があります。


2

もう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ファイルを開き、文字を読み取ります。すべてのデバイスにこのファイルがあるわけではないので、例外ハンドラでラップするようにしてください。

少なくとも次のデバイスは、このファイルを誰でも読み取り可能であることがわかっています。

  • Galaxy Nexus
  • Nexus S
  • Motorola Xoom 3g
  • 東芝AT300
  • HTC One V
  • ミニMK802
  • Samsung Galaxy S II

また、ここで私のブログの記事を見ることができます:http://insitusec.blogspot.com/2013/01/leaking-android-hardware-serial-number.html私は、他のファイルが情報のために利用可能であるかを議論するところ。


回答を投稿していただきありがとうございます。セルフプロモーションに関するFAQをよくお読みください。また、独自のサイト/製品にリンクするたびに免責事項を投稿する必要があることにも注意してください。
Andrew Barber

1

@hasermanが言うように:

TelephonyManager tManager = (TelephonyManager)myActivity.getSystemService(Context.TELEPHONY_SERVICE);
String uid = tManager.getDeviceId();

ただし、マニフェストファイルに権限を含める必要があります。

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

1

文字列としての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が提案するこの方法を強くお勧めします::

アプリのインストールの識別


1

Build.SERIAL 完全に信頼できるわけではありませんが、最も簡単な方法です 空にするか、別の値を返す場合があるため、です(証明1証明2、デバイスの設定に表示される)をです。

デバイスのメーカーとAndroidのバージョンに応じてその数を取得する方法はいくつかあるため、1つの要点で見つけられる可能性のあるすべてのソリューションをコンパイルすることにしました。これを簡略化したバージョンを次に示します。

public static String getSerialNumber() {
    String serialNumber;

    try {
        Class<?> c = Class.forName("android.os.SystemProperties");
        Method get = c.getMethod("get", String.class);

        serialNumber = (String) get.invoke(c, "gsm.sn1");
        if (serialNumber.equals(""))
            serialNumber = (String) get.invoke(c, "ril.serialnumber");
        if (serialNumber.equals(""))
            serialNumber = (String) get.invoke(c, "ro.serialno");
        if (serialNumber.equals(""))
            serialNumber = (String) get.invoke(c, "sys.serialnumber");
        if (serialNumber.equals(""))
            serialNumber = Build.SERIAL;

        // If none of the methods above worked
        if (serialNumber.equals(""))
            serialNumber = null;
    } catch (Exception e) {
        e.printStackTrace();
        serialNumber = null;
    }

    return serialNumber;
}

0

私はこの質問が古いことを知っていますが、1行のコードで行うことができます

String deviceID = Build.SERIAL;


私の知る限り、これはデバイスのOSのアップデート後に変更されます。
Den Drobiazko

-1

上記の@emmbyによって投稿されたサンプルクラスは、優れた出発点であることがわかりました。しかし、他のポスターで言及されているように、いくつかの欠点があります。主なものは、UUIDを不必要にXMLファイルに永続化し、その後常にこのファイルから取得することです。これにより、クラスは簡単にハッキングされます。ルート化された電話を持っている人は誰でもXMLファイルを編集して、自分に新しいUUIDを与えることができます。

絶対に必要な場合(つまり、ランダムに生成されたUUIDを使用する場合)のみXMLに永続化するようにコードを更新し、@ Brill Pappinの回答に従ってロジックをリファクタリングしました。

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 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) || (androidId == null) ) {
                                final String deviceId = ((TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE )).getDeviceId();

                                if (deviceId != null)
                                {
                                    uuid = UUID.nameUUIDFromBytes(deviceId.getBytes("utf8"));
                                }
                                else
                                {
                                    uuid = UUID.randomUUID();

                                    // Write the value out to the prefs file so it persists
                                    prefs.edit().putString(PREFS_DEVICE_ID, uuid.toString() ).commit();
                                }
                            }
                            else
                            {
                                uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
                            } 
                        } catch (UnsupportedEncodingException e) {
                            throw new RuntimeException(e);
                        }



                    }

                }
            }
        }

    }


    /**
     * 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;
    }

IDを共有設定に入れると、本当に一意のIDを取得するという本来の目的が損なわれます。たとえば、そのIDをいくつかの制限のキーとして使用したい場合、熟練したユーザーがデバイスをroot化して共有設定ファイルにアクセスすると、困惑します。その内容はどの手段をコピーすることがあります...
ユージン・ウェクスラー

MBの回答とあなたの回答には、もう1つのエラーがあります。randomUUIDをdeviceIDとappIDとして使用すると、電話であるかどうかに関係なく、またはgoogle expデバイスであるかどうかに関係なく、すべてのデバイスで機能します。
フレッド・グロット、2012年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.