一意のAndroidデバイスIDはありますか?



Answers

更新 :Androidの最近のバージョンでは、 ANDROID_IDに関する問題の多くが解決されており、このアプローチはもはや必要ではないと私は考えています。 アンソニーの答えを見てください。

完全開示:私のアプリは元々は以下のアプローチを使用していましたが、このアプローチを使用しませんでした。そしてemmbyの回答リンク(つまり、 UUID#randomUUID()生成と保存UUID#randomUUID()android-developers.blogspot.com/2011/03/…エントリで概説されているアプローチを使用します。

この質問には多くの答えがありますが、そのほとんどは時間の「ある程度」しか働かず、残念ながら十分ではありません。

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

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

したがって、デバイス自体に固有のものが必要な場合は、 TM.getDeviceId()で十分です。 明らかに、一部のユーザーは他のユーザーよりも編集的ですので、文字列はデバイスには依然として固有ですが、ユーザーの実際のデバイスを明示的に識別することはありません。 たとえば、 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

それは私のために十分に機能します。

Richardが以下に述べるように、 TelephonyManagerプロパティを読み取る権限が必要であることを忘れないでください。これをマニフェストに追加してください:

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

インポートライブラリ

import android.content.Context;
import android.telephony.TelephonyManager;
import android.view.View;
Question

Androidデバイスには固有のIDがありますか?その場合は、Javaを使用して簡単にアクセスできますか?




Add Below code in class file:

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);

Add in AndroidManifest.xml:

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



Google Instance ID

Released at I/O 2015; on Android requires play services 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

It seems that Google intends for this ID to be used to identify installations across Android, Chrome, and iOS.

It identifies an installation rather then a device, but then again, ANDROID_ID (which is the accepted answer) now no longer identifies devices either. With the ARC runtime a new ANDROID_ID is generated for every installation ( details here ), just like this new instance ID. Also, I think that identifying installations (not devices) is what most of us are actually looking for.

The advantages of instance ID

It appears to me that Google intends for it to be used for this purpose (identifying your installations), it is cross-platform, and can be used for a number of other purposes (see the links above).

If you use GCM, then you will eventually need to use this instance ID because you need it in order to get the GCM token (which replaces the old GCM registration ID).

The disadvantages/issues

In the current implementation (GPS 7.5) the instance ID is retrieved from a server when your app requests it. This means that the call above is a blocking call - in my unscientific testing it takes 1-3 seconds if the device is online, and 0.5 - 1.0 seconds if off-line (presumably this is how long it waits before giving up and generating a random ID). This was tested in North America on Nexus 5 with Android 5.1.1 and GPS 7.5.

If you use the ID for the purposes they intend - eg. app authentication, app identification, GCM - I think this 1-3 seconds could be a nuisance (depending on your app, of course).




Here is how I am generating the unique 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;
}



How about the IMEI . That is unique for Android or other mobile devices.




More specifically, Settings.Secure.ANDROID_ID . This is a 64-bit quantity that is generated and stored when the device first boots. It is reset when the device is wiped.

ANDROID_ID seems a good choice for a unique device identifier. There are downsides: First, it is not 100% reliable on releases of Android prior to 2.2 (“Froyo”). Also, there has been at least one widely-observed bug in a popular handset from a major manufacturer, where every instance has the same ANDROID_ID.










Using the code below, you can get the unique device ID of an Android OS device as a string.

deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID); 



One thing I'll add - I have one of those unique situations.

使用方法:

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

Turns out that even though my Viewsonic G Tablet reports a DeviceID that is not Null, every single G Tablet reports the same number.

Makes it interesting playing "Pocket Empires" which gives you instant access to someone's account based on the "unique" DeviceID.

My device does not have a cell radio.




There are 30+ answers here and some are same and some are unique. This answer is based on few of those answers. One of them being @Lenn Dolling's answer.

It combines 3 IDs and creates a 32-digit hex string. It has worked very well for me.

3 IDs are:
Pseudo-ID - It is generated based on physical device specifications
ANDROID_ID - Settings.Secure.ANDROID_ID
Bluetooth Address - Bluetooth adapter address

It will return something like this: 551F27C060712A72730B0A0F734064B1

Note: You can always add more IDs to the longId string. For example, Serial #. wifi adapter address. IMEI. This way you are making it more unique per device.

@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 "";
}



また、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




The following code returns the device serial number using a hidden Android API. But, this code don't works on Samsung Galaxy Tab because "ro.serialno" isn't set on this device.

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

}



Dave Webbが言及しているように、 Android Developer Blogにはこれをカバーする記事があります。 彼らの好ましい解決策は、デバイスではなくアプリのインストールを追跡することであり、ほとんどのユースケースでうまくいくでしょう。 ブログ投稿には、その作業を行うために必要なコードが表示されます。チェックアウトすることをお勧めします。

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

  • ANDROID_IDが優先デバイス識別子です。 ANDROID_IDは、Android <2.1または> = 2.3のバージョンでは完全に信頼できます。 このポストで言及されている問題は2.2しかありません。
  • いくつかのメーカーのいくつかのデバイスは、2.2のANDROID_IDバグの影響を受けます。
  • 私が知る限り 、影響を受けるすべてのデバイスのANDROID_IDは同じです( 9774d56d682e549c 。 これは、エミュレータbtwによって報告された同じデバイスIDでもあります。
  • Googleでは、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;
    }
}



For hardware recognition of a specific Android device you could check the MAC Addresses.

you can do it that way:

in AndroidManifest.xml

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

now in your code:

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

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

In every Android device their is at least a "wlan0" Interface witch is the WI-FI chip. This code works even when WI-FI is not turned on.

PS Their are a bunch of other Interfaces you will get from the list containing MACS But this can change between phones.




Links