programing

고유한 Android 장치 ID가 있습니까?

showcode 2023. 6. 4. 10:43
반응형

고유한 Android 장치 ID가 있습니까?

Android 장치에는 고유한 ID가 있습니까? 만약 그렇다면 Java를 사용하여 쉽게 액세스할 수 있는 방법은 무엇입니까?

Settings.Secure#ANDROID_ID Android ID를 사용자의 64비트 16진수 문자열에 대한 고유한 값으로 반환합니다.

import android.provider.Settings.Secure;

private String android_id = Secure.getString(getContext().getContentResolver(),
                                                        Secure.ANDROID_ID);

고유 식별자에 대한 모범 사례도 읽어 보십시오. https://developer.android.com/training/articles/user-data-ids

업데이트: Android의 최근 버전과 관련하여 많은 문제가 있습니다.ANDROID_ID해결되었고, 저는 이 접근법이 더 이상 필요하지 않다고 생각합니다.앤서니의 답변을 봐주세요.

전체 공개: 내 앱은 원래 아래의 접근 방식을 사용했지만 더 이상 이 접근 방식을 사용하지 않으며, 이제는 emby의 답변이 링크되는(, 생성 및 저장) Android Developer Blog 항목에 요약된 접근 방식을 사용합니다.


이 질문에 대한 대답은 여러 가지가 있는데, 대부분은 "일부"만 작동할 것이며, 안타깝게도 그것만으로는 충분하지 않습니다.

장치 테스트(모든 전화기 중 하나 이상이 활성화되지 않음)에 따라:

  1. 에서 테트한모장다값반을환습니다했음치가든스에 대한 값을 했습니다.TelephonyManager.getDeviceId()
  2. 장치는 "GSM 치장가(SIM 로테됨트스)"에 대한 했습니다.TelephonyManager.getSimSerialNumber()
  3. 가 "" "CDMA" "" "" "null"에 대해 했습니다.getSimSerialNumber() (예상로대)
  4. Google 계정이 추가된 모든 장치에서 다음 값을 반환했습니다.ANDROID_ID
  5. 모든 CDMA 장치가 두 장치 모두에 대해 동일한 값(또는 동일한 값의 파생)을 반환했습니다.ANDROID_ID그리고.TelephonyManager.getDeviceId()설정 중에 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;

#마지막 업데이트: 2015년 6월 2일


고유 ID 생성에 대한 스택 오버플로 게시물, 구글 개발자 블로그, 안드로이드 문서를 모두 읽고 나니 'Pseudo ID'가 최선의 선택인 것 같습니다.

주요 문제: 하드웨어 대 소프트웨어

하드웨어

  • 사용자는 하드웨어, Android 태블릿 또는 전화기를 변경할 수 있으므로 하드웨어에 기반한 고유 ID는 사용자 추적에 적합하지 않습니다.
  • TRACKING HARDERGY의 경우, 이것은 좋은 생각입니다.

소프트웨어

  • 사용자가 ROM을 삭제/변경할 수 있습니다(루트된 경우).
  • 여러 플랫폼(iOS, Android, Windows 및 웹)에서 사용자를 추적할 수 있습니다.
  • 개인 사용자의 동의 하에 개인 사용자를 추적하는 가장 좋은 방법은 사용자가 로그인하도록 하는 것입니다(Outh를 사용하여 원활하게 로그인).

#Android에 대한 전반적인 분석

API에 대한 고유성 보장(루티드 디바이스) > = 9/10 (Android 디바이스의 99.5%) ##- 추가 권한 없음

Psueo 코드:

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)

(이 스택 오버플로 질문에) 모든 옵션을 게시해 주신 @stansult님께 감사드립니다.

##옵션 목록 - 옵션을 사용해야 하는 이유/사용하지 않는 이유:

  • 사용자 전자 메일 - 소프트웨어

  • 사용자가 전자 메일을 변경할 수 있음 - 가능성이 매우 낮음

  • 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 기기의 기본 전자 메일 주소를 가져오는 방법)

  • 사용자 전화 번호 - 소프트웨어

  • 사용자가 전화 번호를 변경할 수 있음 - 가능성이 매우 낮음

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

  • IMEI - 하드웨어(전화기만, 필요)

  • 대부분의 사용자는 권한에 "전화 통화"라고 표시되어 있다는 사실을 싫어합니다.일부 사용자는 장치 설치를 추적하기만 하면 개인 정보를 훔치는 것이라고 생각하기 때문에 나쁜 등급을 부여합니다.데이터를 수집하고 있는 것은 분명합니다.

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

  • Android ID - 하드웨어(null일 수 있음, 출고 시 재설정 시 변경 가능, 루트 장치에서 변경 가능)

  • 'null'일 수 있으므로 'null'을 확인하고 값을 변경할 수 있지만, 이는 더 이상 고유하지 않음을 의미합니다.

  • 공장 초기화 장치를 사용하는 사용자가 있는 경우 루트 장치에서 값이 변경되거나 변경되어 사용자 설치를 추적하는 경우 중복 항목이 있을 수 있습니다.

  • WLAN MAC 주소 - 하드웨어(니즈)

  • 이것이 차선의 옵션이 될 수 있지만 사용자가 직접 제공하는 고유 식별자를 수집하고 저장하는 중입니다.이것은 당신이 데이터를 수집하고 있는 것이 분명합니다.

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

  • Bluetooth MAC 주소 - 하드웨어(Bluetooth가 있는 장치, 필요)

  • 시중에 나와 있는 대부분의 애플리케이션은 블루투스를 사용하지 않기 때문에 애플리케이션이 블루투스를 사용하지 않고 이를 포함하고 있다면 사용자가 의심할 수 있습니다.

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

  • 유사 고유 ID - 소프트웨어(모든 Android 장치용)

  • 매우 가능성이 있으며 충돌이 포함될 수 있습니다 - 아래에 게시된 내 방법을 참조하십시오!

  • 이렇게 하면 개인 정보를 가져오지 않고도 사용자로부터 '거의 고유한' ID를 얻을 수 있습니다.장치 정보에서 익명 ID를 만들 수 있습니다.


권한을 사용하지 않고 고유 ID를 얻을 수 있는 '완벽한' 방법은 없다는 것을 알고 있습니다. 하지만 때로는 장치 설치를 추적하기만 하면 됩니다.고유 ID를 생성할 때는 별도의 권한 없이 Android API에서 제공하는 정보만으로 '의사 고유 ID'를 생성할 수 있습니다.이러한 방식으로 사용자를 존중하고 좋은 사용자 경험을 제공하도록 노력할 수 있습니다.

유사 고유 ID를 사용하면 유사한 장치가 있다는 사실에 근거하여 중복이 있을 수 있다는 사실만 실제로 마주치게 됩니다.결합된 방법을 조정하여 더 고유하게 만들 수 있지만, 일부 개발자는 장치 설치를 추적해야 하며 이는 유사한 장치를 기반으로 한 트릭 또는 성능을 수행합니다.

##API >= 9:

Android 기기가 API 9 이상인 경우 'Build'로 인해 고유한 기능을 제공합니다.시리얼' 필드입니다.

기억하세요, 당신은 기술적으로 API < 9를 가진 약 0.5%의 사용자들만 놓치고 있습니다.나머지 부분에 집중할 수 있습니다.이것은 사용자의 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 기기 정보만을 기반으로 합니다.여기서 충돌이 일어날 수 있습니다.

변경 사항:

  • '안드로이드'를 제거했습니다.출고 시 재설정으로 인해 값이 변경될 수 있으므로 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();
}

#New(광고가 있는 앱 및 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.html http://developer.android.com/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.html

##중요:

광고 ID는 광고 목적(설정에서 Android_ID 사용 등)으로 기존에 사용하던 다른 식별자의 사용을 완전히 대체하는 것을 의미합니다.보안)은 Google Play 서비스를 사용할 수 있는 경우에 제공됩니다.Google Play 서비스를 사용할 수 없는 경우 Google Play 서비스를 사용할 수 없음으로 표시됩니다.getAdvertisingIdInfo()에 의해 느려지는 예외입니다.

##경고, 사용자가 재설정할 수 있습니다.

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

정보를 가져온 모든 링크를 참조하려고 했습니다.누락되어 포함해야 하는 경우 댓글을 달아주세요!

Google 플레이어 서비스 인스턴스아이디

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

Dave Webb가 언급했듯이 Android Developer Blog에는 이를 다루는 기사가 있습니다.그들이 선호하는 솔루션은 기기가 아닌 앱 설치를 추적하는 것이며, 이는 대부분의 사용 사례에서 잘 작동할 것입니다.블로그 게시물에 해당 작업에 필요한 코드가 표시될 것이며, 확인해 보시기 바랍니다.

그러나 앱 설치 식별자가 아닌 장치 식별자가 필요한 경우 블로그 게시물에서 해결책에 대해 논의합니다.저는 당신이 그렇게 해야 할 필요가 있는 경우 몇 가지 항목에 대해 추가적인 설명을 듣기 위해 구글의 누군가와 이야기했습니다.다음은 앞서 언급한 블로그 게시물에 언급되지 않은 장치 식별자에 대한 내용입니다.

  • Android_ID는 기본 장치 식별자입니다. Android_ID는 Android <=2.1 또는 >=2.3 버전에서 완벽하게 신뢰할 수 있습니다.게시물에 언급된 문제가 있는 것은 2.2 뿐입니다.
  • 여러 제조업체의 여러 장치가 2.2의 Android_ID 버그의 영향을 받습니다.
  • 제가 확인한 바로는, 영향을 받는 모든 기기는 동일한 Android_ID(9774d56d682e549c)를 가지고 있습니다.이것은 또한 에뮬레이터에 의해 보고된 것과 동일한 장치 ID, btw입니다.
  • Google은 OEM이 대부분 또는 대부분의 장치에 대해 문제를 해결했다고 생각하지만, 적어도 2011년 4월 초에는 여전히 Android_ID가 손상된 장치를 쉽게 찾을 수 있다는 것을 확인할 수 있었습니다.

Google의 권장 사항에 따라 각 장치에 대해 고유 UUID를 생성하는 클래스를 구현했습니다. 적절한 경우 시드로 Android_ID를 사용하여 TelephonyManager.getDeviceId()를 다시 사용하고, 실패할 경우 앱을 다시 시작할 때까지 지속되는 임의로 생성된 고유 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;
    }
}

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의 설명에도 설명되어 있음), 사용자와 연결되고 장치가 삭제되거나 교체된 후에도 계속 유지되는 ID가 있어야 합니다.향후 분석에 사용할 계획입니다(즉, 아직 그 부분을 수행하지 않았습니다).

간단한 질문이지, 간단한 대답은 없습니다.

게다가, 여기에 있는 모든 기존 답변은 구식이거나 신뢰할 수 없습니다.

2020년 이후에 해결책을 찾고 있다면,

다음은 주의해야 할 몇 가지 사항입니다.

모든 하드웨어 기반 식별자(IMEI, MAC, 일련 번호 등)는 통계적으로 전 세계 대부분의 안드로이드 활성 장치인 비구글 장치(픽셀 및 Nexus 제외)에 대해 신뢰할 수 없습니다.따라서 공식 Android 식별자 모범 사례는 다음과 같이 명확하게 명시합니다.

IMEI, MAC 주소 등과 같은 하드웨어 식별자를 사용하지 않도록 합니다.

그래서 대부분의 답은 무효입니다.또한 다른 안드로이드 보안 업데이트로 인해 일부는 더 새롭고 엄격한 런타임 권한을 요구하며, 이는 사용자에 의해 단순히 거부될 수 있습니다.

를 들어 를들면입니다.CVE-2018-9489위에서 언급한 모든 WIFI 기반 기술에 영향을 미칩니다.

따라서 이러한 식별자는 신뢰할 수 없을 뿐만 아니라 많은 경우에 액세스할 수 없게 됩니다.

더 간단한 말로 하면, 그런 기술을 사용하지 마세요.

여기에 있는 많은 다른 답변들은 다음을 사용할 것을 제안합니다.AdvertisingIdClient또한 이는 광고 프로파일링 전용이므로 호환되지 않습니다.공식적인 참고문헌에도 나와 있습니다.

사용자 프로파일링 또는 광고 사용 사례에만 광고 ID 사용

장치 식별에 신뢰할 수 없을 뿐만 아니라 사용자가 언제든지 재설정하거나 차단할 수 있다는 것을 명확히 명시한 광고 추적 정책에 대한 사용자 개인 정보를 따라야 합니다.

그러니 그것도 사용하지 마세요.

원하는 정적 전역적으로 고유하고 신뢰할 수 있는 장치 식별자를 가질 수 없기 때문입니다.Android의 공식적인 언급은 다음과 같습니다.

결제 부정 방지 및 전화를 제외한 다른 모든 사용 사례에 대해서는 가능한 한 Firebase 설치 ID(FID) 또는 개인 저장 GUID를 사용하십시오.

이것은 기기에 애플리케이션을 설치하는 데 고유하기 때문에 사용자가 앱을 제거하면 삭제되므로 100% 신뢰할 수는 없지만 차선책입니다.

참고: 오늘 현재.FirebaseInstanceId. 를 .FirebaseInstallations대신.

사용하기FirebaseInstallations최신 소방 기지-장비 종속성을 Gradle에 추가합니다.

implementation 'com.google.firebase:firebase-messaging:23.0.0'

그리고 아래 코드를 사용하여 Firebase ID를 가져옵니다.

FirebaseInstallations.getInstance().getId().addOnCompleteListener(task -> {
     if (task.isSuccessful()) {
        String firebaseIdentifier = task.getResult();
        // Do what you need with firebaseIdentifier
     }
});

원격 서버에 장치 ID를 저장해야 하는 경우 그대로(일반 텍스트) 저장하지 않고 소금이 들어간 해시를 사용합니다.

오늘날 이것은 모범 사례일 뿐만 아니라 실제로 GDPR 및 유사한 규정에 따라 법적으로 수행해야 합니다.

또한 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

여기에 유용한 정보가 있습니다.

다음과 같은 다섯 가지 다른 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)

공식 Android Developers Blog에는 이제 앱 설치 식별이라는 바로 이 주제에 대한 전체 기사가 있습니다.

Google I/O Reto Meier에서는 대부분의 개발자가 설치 전반에 걸쳐 사용자를 추적해야 하는 필요를 충족시킬 수 있는 이 문제에 대한 강력한 답변을 발표했습니다.앤서니 놀란은 답변에서 방향성을 보여주지만, 다른 사람들이 쉽게 할 수 있도록 전체적인 접근법을 적어야겠다고 생각했습니다(자세한 내용을 파악하는 데 시간이 좀 걸렸습니다).

이 접근 방식은 사용자가 서로 다른 장치(기본 Google 계정 기반)와 설치 간에 지속적으로 사용할 수 있는 익명의 안전한 사용자 ID를 제공합니다.기본 접근 방식은 임의의 사용자 ID를 생성하고 이를 앱의 공유 기본 설정에 저장하는 것입니다.그런 다음 Google의 백업 에이전트를 사용하여 Google 계정에 연결된 공유 기본 설정을 클라우드에 저장합니다.

전체적인 접근법을 살펴보도록 하겠습니다.먼저 Android Backup Service를 사용하여 Shared Preferences에 대한 백업을 만들어야 합니다.다음을 통해 앱을 등록하는 것으로 시작합니다.http://developer.android.com/google/backup/signup.html.

Google은 매니페스트에 추가해야 하는 백업 서비스 키를 제공합니다.또한 다음과 같이 백업 에이전트를 사용하도록 응용 프로그램에 지시해야 합니다.

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

백업을 완료하려면 기본 활동에 Backup Manager 인스턴스를 생성해야 합니다.

BackupManager backupManager = new BackupManager(context);

마지막으로 사용자 ID가 아직 존재하지 않는 경우 해당 사용자 ID를 생성하여 공유 환경설정에 저장합니다.

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

이 사용자_이제 사용자가 장치를 이동하더라도 ID는 설치 전반에 걸쳐 유지됩니다.

이 접근 방식에 대한 자세한 내용은 Reto의 강연을 참조하십시오.

백업 에이전트를 구현하는 방법에 대한 자세한 내용은 데이터 백업을 참조하십시오.백업이 즉시 수행되는 것이 아니므로 테스트를 위해 백업을 강제로 수행해야 하므로 테스트 하단의 섹션을 특히 권장합니다.

이것이 독특한 신분증을 위한 골격을 만드는 확실한 방법이라고 생각합니다.이것을 확인해 보세요.

모든 Android 장치에서 작동하는 유사 고유 ID 일부 장치에는 전화기가 없습니다(예:태블릿) 또는 어떤 이유로 READ_PHONE_STATE 권한을 포함하지 않으려는 경우.ROM 버전, 제조업체 이름, CPU 유형 및 기타 하드웨어 세부 정보와 같은 ID를 직렬 키 검사 또는 기타 일반적인 용도로 사용하려는 경우에 적합한 세부 정보를 읽을 수 있습니다.이렇게 계산된 ID는 고유하지 않습니다. 동일한 ID(하드웨어 및 ROM 이미지 기반)를 가진 두 장치를 찾을 수 있지만 실제 응용 프로그램의 변경은 무시할 수 있습니다.이를 위해 빌드 클래스를 사용할 수 있습니다.

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

빌드 멤버의 대부분은 문자열입니다. 여기서 우리가 하는 일은 길이를 재서 숫자의 모듈로를 통해 변환하는 것입니다.우리는 13개의 숫자를 가지고 있으며 IMEI(15개의 숫자)와 동일한 크기의 ID를 갖기 위해 앞에 2개(35개)를 더 추가하고 있습니다.여기에는 다른 가능성이 있습니다. 이 끈들을 보세요.▁like와 같은 것을 합니다.355715565309247특별한 권한이 필요하지 않으므로 이 접근 방식이 매우 편리합니다.


(추가 정보:위에 주어진 기술은 포켓 매직에 관한 기사에서 복사한 것입니다.)

다음 코드는 숨겨진 Android API를 사용하여 장치 일련 번호를 반환합니다.하지만 삼성 갤럭시 탭에는 "ro.serialno"가 설정되어 있지 않기 때문에 이 코드는 작동하지 않습니다.

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 OS 기기의 고유 기기 ID를 문자열로 얻을 수 있습니다.

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

한 가지 덧붙이자면, 저는 그런 독특한 상황들 중 하나를 가지고 있습니다.

사용:

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

Viewsonic G 태블릿이 장치를 보고하더라도Null이 아닌 ID로, 모든 G Tablet은 동일한 번호를 보고합니다.

"독특한" 장치를 기반으로 누군가의 계정에 즉시 액세스할 수 있는 "Pocket Empires"를 플레이하는 것이 흥미롭습니다.신분증.

단말기에 셀 라디오가 없습니다.

일련 번호 필드가 에 추가되었습니다.Build클스는 API 레벨 9 (Android 2.3 - Gingerbread)번호가 되어 있습니다.설명서에 하드웨어 일련 번호가 나와 있습니다.따라서 장치에 존재하는 경우 고유해야 합니다.

하지만 API 레벨 >= 9인 모든 기기에서 실제로 지원(=null이 아님)되는지는 모르겠습니다.

응용 프로그램이 설치된 각 Android 장치에 대한 고유 식별자를 가져오는 방법에 대한 자세한 내용은 Android Developers 블로그 공식 게시물 앱 설치 식별을 참조하십시오.

가장 좋은 방법은 설치 시 직접 생성한 후 응용 프로그램을 다시 시작할 때 읽어보는 것입니다.

저는 개인적으로 이것이 수용 가능하지만 이상적이지는 않다고 생각합니다.대부분이 전화기의 무선 상태(Wi-Fi 켜짐/꺼짐, 셀룰러 켜짐/꺼짐, Bluetooth 켜짐/꺼짐)에 따라 다르기 때문에 Android에서 제공하는 하나의 식별자도 모든 경우에 작동하지 않습니다.다른 사람들은, 예를 들면.Settings.Secure.ANDROID_ID제조업체가 구현해야 하며 고유성이 보장되지 않습니다.

다음은 응용프로그램이 로컬로 저장하는 다른 데이터와 함께 저장되는 설치 파일에 데이터를 쓰는 예입니다.

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

클래스 파일에 아래 코드 추가:

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" />

것들을 는 여러 .ANDROID_ID 문일수있음제일▁be)▁()일 수 있습니다.null때때로 또는 특정 모델의 장치는 항상 동일한 ID를 반환합니다). 장점과 단점:

  • 사용자 지정 ID 생성 알고리즘 구현(정적이어야 하고 변경되지 않는 장치 속성 기반 -> 누가 알겠는가)
  • IMEI, 일련 번호, Wi-Fi/Bluetooth-MAC 주소와 같은 다른 ID 남용(모든 장치에 존재하지 않거나 추가 권한이 필요함)

저 자신도 기존 OpenUDID 구현을 사용하는 것을 선호합니다(Android는 https://github.com/ylechelle/OpenUDID) 참조).통합이 용이하며 다음을 활용합니다.ANDROID_ID위에서 언급한 문제들에 대한 예비비가 있습니다.

제 2센트 - 엔비는 안드로이드 개발자 블로그에서 논의된 설치 ID가 아닌 장치(err) 고유 ID에 대한 것입니다.

@emby에서 제공하는 솔루션은 Shared Preferences가 프로세스 간에 동기화되지 않기 때문에 애플리케이션 ID별로 다시 적용됩니다(여기 및 여기 참조).그래서 저는 이것을 완전히 피했습니다.

대신, 저는 열거형에서 (장치) ID를 얻기 위한 다양한 전략을 캡슐화했습니다. 열거형 상수의 순서를 변경하면 ID를 얻는 다양한 방법의 우선순위에 영향을 미칩니다.null이 아닌 첫 번째 ID가 반환되거나 예외가 느려집니다(null에 의미를 부여하지 않는 Java의 모범 사례에 따라).그래서 예를 들어, 저는 먼저 전화를 가지고 있지만, 좋은 기본 선택은 Android_ID 베타입니다.

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

여기에는 30개 이상의 답이 있으며 일부는 동일하고 일부는 고유합니다.이 답변은 이러한 답변 중 몇 가지를 기반으로 합니다.그 중 하나는 @Lenn Dolling의 대답입니다.

3개의 ID를 결합하여 32자리 16진수 문자열을 만듭니다.그것은 저에게 매우 효과가 있었습니다.

의 ID 3개의 ID:
Pseudo-ID - 물리적 장치 사양을 기반으로 생성됩니다.
Android_ID -Settings.Secure.ANDROID_ID
블루투스 주소 - 블루투스 어댑터 주소

다음과 같은 것을 반환할 입니다: 551F27C060712A72730B0A0F734064B1

든지 더 많은 할 수 .longId들어 일련 번호. 주소예: 일련 번호. wifi 어댑터 주소.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 "";
}

IMEI는 어떻습니까?그것은 Android 또는 다른 모바일 장치에 고유합니다.

Android OS를 String으로 합니다.TelephonyManager그리고.ANDROID_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에서 제안한 방법을 적극 추천합니다. 앱 설치 식별을 참조하십시오.

고유 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;
}

다른 방법은 사용하는 것입니다./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
  • 모토로라 줌 3G
  • 도시바 AT300
  • HTC 원브이
  • 미니 MK802
  • 삼성 갤럭시 S II

또한 제 블로그 게시물 Android 하드웨어 일련 번호를 권한 없는 앱에 유출하는 을 볼 수 있습니다. 여기서 정보로 사용할 수 있는 다른 파일에 대해 설명합니다.

특정 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 칩입니다.이 코드는 Wi-Fi가 켜져 있지 않은 경우에도 작동합니다.

추신. 이 인터페이스는 MACS가 포함된 목록에서 얻을 수 있는 많은 다른 인터페이스이지만 전화기 간에 변경될 수 있습니다.

나는 다음 코드를 사용하여 다음을 얻습니다.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);

TelephonyManager.getDeviceId() GSM의 경우 IMEI, CDMA 전화의 경우 MEID 또는 ESN과 같이 고유한 장치 ID를 반환합니다.

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

그러나 다음을 사용하는 것이 좋습니다.

설정.시큐어.안드로이드_Android ID를 고유한 64비트 16진수 문자열로 반환하는 ID입니다.

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

때때로 TelephonyManager.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;
}

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

Google은 이 ID를 Android, Chrome 및 iOS에서 설치를 식별하는 데 사용할 계획인 것 같습니다.

장치가 아닌 설치를 식별하지만 Android_ID(승인된 답변)는 더 이상 장치를 식별하지 않습니다.ARC 런타임을 사용하면 이 새 인스턴스 ID와 마찬가지로 모든 설치(자세한 내용은 여기)에 대해 새 Android_ID가 생성됩니다.또한 장치가 아닌 설치를 식별하는 것이 우리 대부분이 실제로 찾고 있는 것이라고 생각합니다.

인스턴스 ID의 장점

Google은 이 목적(설치 식별)을 위해 사용하고, 교차 플랫폼이며, 여러 가지 다른 목적(위 링크 참조)으로 사용할 수 있습니다.

GCM을 사용하는 경우, 이전 GCM 등록 ID를 대체하는 GCM 토큰을 얻기 위해 이 인스턴스 ID가 필요하기 때문에 결국 이 인스턴스 ID를 사용해야 합니다.

단점/문제

현재 구현(GPS 7.5)에서 인스턴스 ID는 앱이 요청할 때 서버에서 검색됩니다.이는 위의 통화가 차단 통화임을 의미합니다. 제 비과학적 테스트에서는 장치가 온라인 상태일 경우 1-3초, 오프라인 상태일 경우 0.5-1.0초가 소요됩니다(이는 임의의 ID를 생성하기 전에 대기하는 시간입니다).Android 5.1.1 및 GPS 7.5가 설치된 Nexus 5에서 북미에서 테스트되었습니다.

앱 인증, 앱 식별, GCM 등 그들이 의도하는 목적으로 아이디를 사용한다면 이 1~3초는 (물론 앱에 따라 다르지만) 성가신 시간이 될 수 있다고 생각합니다.

이제 Google에 광고 ID가 있습니다.
이 기능도 사용할 수 있지만 다음 사항에 유의하십시오.

광고 ID는 사용자 고유의 재설정 가능한 ID입니다.

그리고.

사용자는 자신의 식별자를 재설정하거나 Google Play 앱 내의 관심 기반 광고를 선택할 수 있습니다.

따라서 이 ID가 변경될 수도 있지만, 곧 이 ID의 목적에 따라 선택의 여지가 없을 수도 있습니다.

더 보기 info @ develper.an droid

코드를 복사하여 여기에 붙여넣기

HTH

Android 장치에서 사용할 수 있는 고유 ID를 이해합니다.이 공식 안내서를 사용하십시오.

고유 식별자에 대한 모범 사례:

IMEI, Mac 주소, 인스턴스 ID, GUID, SSAID, Advertising ID, SafetyNet API를 통해 디바이스를 확인할 수 있습니다.

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

언급URL : https://stackoverflow.com/questions/2785485/is-there-a-unique-android-device-id

반응형