Android 기기에는 고유한 ID가 있으며, 그렇다면 Java를 사용하여 액세스하는 간단한 방법은 무엇입니까?
질문자 :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);
또한 고유 식별자에 대한 모범 사례를 읽으십시오. https://developer.android.com/training/articles/user-data-ids
Anthony Forloney
업데이트 : 최신 버전의 Android에서 ANDROID_ID
많은 문제가 해결되었으며 이 접근 방식이 더 이상 필요하지 않다고 생각합니다. Anthony의 답변을 살펴보십시오.
전체 공개: 내 앱은 원래 아래 접근 방식을 사용했지만 더 이상 이 접근 방식을 사용하지 않으며 이제 emmby의 답변이 링크되는 Android 개발자 블로그 항목에 설명된 접근 방식을 사용합니다(즉, UUID#randomUUID()
생성 및 저장).
이 질문에 대한 많은 답변이 있으며 대부분은 "일부" 시간에만 작동하며 불행히도 충분하지 않습니다.
내 장치 테스트(모든 전화기, 그 중 하나 이상은 활성화되지 않음)를 기반으로 합니다.
-
TelephonyManager.getDeviceId()
대한 값을 반환했습니다. - 모든 GSM 장치(모두 SIM으로 테스트됨)는
TelephonyManager.getSimSerialNumber()
- 모든 CDMA 장치가
getSimSerialNumber()
대해 null을 반환했습니다(예상대로). - Google 계정이 추가된 모든 기기에서
ANDROID_ID
- 모든 CDMA 장치는 모두 같은 값 (또는 같은 값의 유도를) 반환
ANDROID_ID
및TelephonyManager.getDeviceId()
- 한 Google 계정은 설치하는 동안 추가되었습니다있다. - 아직 SIM이 없는 GSM 장치, Google 계정이 추가되지 않은 GSM 장치 또는 비행기 모드의 장치를 테스트할 기회가 없었습니다.
따라서 장치 자체에 고유한 것을 TM.getDeviceId()
로 충분 해야 합니다. 분명히 일부 사용자는 다른 사용자보다 편집증이 심하므로 이러한 식별자 중 1개 이상을 해시하는 것이 유용할 수 있으므로 문자열이 여전히 장치에 대해 사실상 고유하지만 사용자의 실제 장치를 명시적으로 식별하지는 않습니다. 예를 들어 UUID와 결합된 String.hashCode()
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;
Joe
#최종 업데이트: 6/2/15
고유 ID 생성에 대한 모든 스택 오버플로 게시물, Google 개발자 블로그 및 Android 설명서를 읽은 후 'Pseudo ID'가 가장 좋은 옵션인 것처럼 느낍니다.
주요 문제: 하드웨어 대 소프트웨어
하드웨어
- 사용자는 하드웨어, Android 태블릿 또는 전화를 변경할 수 있으므로 하드웨어 기반 고유 ID는 사용자 추적에 적합하지 않습니다.
- TRACKING HARDWARE의 경우 이것은 좋은 아이디어입니다.
소프트웨어
- 사용자는 루팅된 경우 ROM을 지우거나 변경할 수 있습니다.
- 플랫폼(iOS, Android, Windows 및 웹)에서 사용자를 추적할 수 있습니다.
- 동의를 얻어 개별 사용자 를 추적하는 가장 좋은 방법은 단순히 로그인하게 하는 것입니다(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)
모든 옵션 을 게시해 주신 @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 - 하드웨어 (전화 전용,
android.permission.READ_PHONE_STATE
필요)대부분의 사용자는 권한에 "전화 통화"라고 표시되어 있다는 사실을 싫어합니다. 일부 사용자는 기기 설치를 추적하는 것만이 정말 하고 싶을 때 단순히 개인 정보를 도용한다고 생각하기 때문에 나쁜 등급을 부여합니다. 데이터를 수집하고 있는 것이 분명합니다.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Android ID - 하드웨어 (null일 수 있음, 공장 초기화 시 변경 가능, 루팅된 기기에서 변경 가능)
'null'일 수 있으므로 'null'을 확인하고 값을 변경할 수 있지만 이는 더 이상 고유하지 않음을 의미합니다.
기기를 초기화한 사용자가 있는 경우 루팅된 기기에서 값이 변경되거나 변경되었을 수 있으므로 사용자 설치를 추적하는 경우 중복 항목이 있을 수 있습니다.
WLAN MAC 주소 - 하드웨어 (
android.permission.ACCESS_WIFI_STATE
필요)이것은 차선책일 수 있지만 여전히 사용자로부터 직접 오는 고유 식별자를 수집하고 저장하고 있습니다. 이것은 당신이 데이터를 수집하고 있다는 것이 분명합니다.
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE "/>
Bluetooth MAC 주소 - 하드웨어 (Bluetooth가 있는 장치,
android.permission.BLUETOOTH
필요)시중에 나와 있는 대부분의 응용 프로그램은 Bluetooth를 사용하지 않으므로 응용 프로그램이 Bluetooth를 사용하지 않고 이를 포함하면 사용자가 의심을 받을 수 있습니다.
<uses-permission android:name="android.permission.BLUETOOTH "/>
Pseudo-Unique ID - 소프트웨어 (모든 Android 기기용)
매우 가능하며 충돌이 포함될 수 있습니다. 아래에 게시된 방법을 참조하십시오!
이를 통해 비공개 항목을 취하지 않고 사용자로부터 '거의 고유한' ID를 가질 수 있습니다. 장치 정보에서 자신의 익명 ID를 만들 수 있습니다.
권한을 사용하지 않고 고유 ID를 얻는 '완벽한' 방법은 없다는 것을 알고 있습니다. 그러나 때로는 장치 설치를 추적하기만 하면 됩니다. 고유 ID를 생성할 때 별도의 권한 없이 Android API가 제공하는 정보만으로 'pseudo unique id'를 생성할 수 있습니다. 이렇게 하면 사용자를 존중하고 좋은 사용자 경험을 제공할 수 있습니다.
유사 고유 ID를 사용하면 유사한 장치가 있다는 사실에 근거하여 중복이 있을 수 있다는 사실에 부딪히게 됩니다. 결합된 방법을 조정하여 더 독특하게 만들 수 있습니다. 그러나 일부 개발자는 장치 설치를 추적해야 하며 이는 유사한 장치를 기반으로 트릭 또는 성능을 수행합니다.
##API >= 9:
Android 기기가 API 9 이상인 경우 'Build.SERIAL' 필드로 인해 고유한 것이 보장됩니다.
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 기기 정보를 기반으로 합니다. . 여기에서 충돌이 발생할 수 있습니다.
변경 사항:
- 공장 초기화로 인해 값이 변경될 수 있으므로 '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 (eg, // 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는 Google Play 서비스를 사용할 수 있을 때 광고 목적으로 다른 식별자의 기존 사용(예: Settings.Secure에서 ANDROID_ID 사용)을 완전히 대체하기 위한 것입니다. Google Play 서비스를 사용할 수 없는 경우는 getAdvertisingIdInfo()에서 발생하는 GooglePlayServicesNotAvailableException으로 표시됩니다.
##경고, 사용자는 다음을 재설정할 수 있습니다.
http://en.kioskea.net/faq/34732-android-reset-your-advertising-id
정보를 가져온 모든 링크를 참조하려고 했습니다. 누락되어 포함해야 하는 경우 댓글을 남겨주세요!
Google 플레이어 서비스 인스턴스 ID
Jared Burrows
Dave Webb가 언급했듯이 Android 개발자 블로그에는 이에 대한 기사 가 있습니다. 그들이 선호하는 솔루션은 기기가 아닌 앱 설치를 추적하는 것이며 대부분의 사용 사례에서 잘 작동합니다. 블로그 게시물은 해당 작업을 수행하는 데 필요한 코드를 보여주므로 확인하는 것이 좋습니다.
그러나 블로그 게시물에서는 앱 설치 식별자가 아닌 기기 식별자가 필요한 경우 솔루션에 대해 설명합니다. 필요한 경우 몇 가지 항목에 대한 추가 설명을 얻기 위해 Google 직원과 통화했습니다. 다음은 앞서 언급한 블로그 게시물에 언급되지 않은 기기 식별자에 대해 발견한 내용입니다.
- ANDROID_ID는 기본 장치 식별자입니다. ANDROID_ID는 Android <=2.1 또는 >=2.3 버전에서 완벽하게 신뢰할 수 있습니다. 2.2에만 게시물에 언급된 문제가 있습니다.
- 여러 제조업체의 여러 장치가 2.2의 ANDROID_ID 버그의 영향을 받습니다.
- 내가 결정할 수 있는 한, 영향을 받는 모든 장치는 9774d56d682e549c 인 동일한 ANDROID_ID 를 갖습니다. 이는 에뮬레이터 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; } }
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's talk 에서도 설명됨) 사용자와 연결되고 장치가 지워지거나 교체된 후에도 계속 유지되는 ID가 있어야 합니다. 저는 이것을 사용할 계획입니다. 앞으로 분석에서 (즉, 나는 아직 그 비트를 수행하지 않았습니다 :).
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
Seva Alekseyev
여기에 오히려 유용한 정보가 있습니다 .
5가지 ID 유형을 다룹니다.
- IMEI (전화를 사용하는 Android 기기에만 해당,
android.permission.READ_PHONE_STATE
필요) - 의사 고유 ID (모든 Android 장치용)
- Android ID (null일 수 있음, 공장 초기화 시 변경 가능, 루팅된 전화에서 변경 가능)
- WLAN MAC 주소 문자열(
android.permission.ACCESS_WIFI_STATE
필요) - BT MAC 주소 문자열(Bluetooth가 있는 장치,
android.permission.BLUETOOTH
필요)
stansult
간단한 답이 없는 간단한 질문입니다.
게다가 여기에 있는 모든 기존 답변은 구식이거나 신뢰할 수 없습니다.
따라서 2020년에 솔루션을 찾고 있다면 .
다음은 염두에 두어야 할 몇 가지 사항입니다.
모든 하드웨어 기반 식별자(SSAID, IMEI, MAC 등)는 전 세계 활성 기기의 50% 이상을 차지하는 타사 기기(Pixel 및 Nexus를 제외한 모든 기기)에 대해 신뢰할 수 없습니다. 따라서 공식 Android 식별자 모범 사례는 다음과 같이 명확하게 명시되어 있습니다.
SSAID(Android ID), IMEI, MAC 주소 등과 같은 하드웨어 식별자를 사용하지 마십시오.
그것은 위의 답변 대부분을 무효로 만듭니다. 또한 다른 Android 보안 업데이트로 인해 일부 업데이트에는 더 새롭고 더 엄격한 런타임 권한이 필요하며 이는 사용자가 거부할 수 있습니다.
위에서 언급한 모든 WIFI 기반 기술에 영향을 미치는 CVE-2018-9489
예입니다.
따라서 이러한 식별자는 신뢰할 수 없을 뿐만 아니라 많은 경우에 액세스할 수 없습니다.
따라서 간단히 말해서 이러한 기술을 사용하지 마십시오 .
여기에 있는 다른 많은 답변은 설계상 광고 프로파일링에만 사용해야 하므로 호환되지 않는 AdvertisingIdClient
공식 참조 에도 명시되어 있습니다.
사용자 프로파일링 또는 광고 사용 사례에만 광고 ID를 사용하십시오.
장치 식별에 대해 신뢰할 수 없을 뿐만 아니라 사용자가 언제든지 재설정하거나 차단할 수 있다고 명시한 광고 추적 정책과 관련하여 사용자 개인 정보를 준수해야 합니다.
따라서 사용하지 마십시오 .
원하는 정적 전역 고유하고 안정적인 장치 식별자를 가질 수 없기 때문입니다. Android의 공식 참조는 다음을 제안합니다.
결제 사기 방지 및 전화 통신을 제외한 다른 모든 사용 사례에는 가능할 때마다 FirebaseInstanceId 또는 비공개로 저장된 GUID를 사용합니다.
장치에 응용 프로그램을 설치할 때마다 고유하므로 사용자가 응용 프로그램을 제거하면 - 지워지므로 100% 신뢰할 수는 없지만 차선책입니다.
FirebaseInstanceId
를 사용하려면 최신 Firebase 메시징 종속성 을 gradle에 추가하십시오.
implementation 'com.google.firebase:firebase-messaging:20.2.4'
백그라운드 스레드에서 아래 코드를 사용합니다.
String reliableIdentifier = FirebaseInstanceId.getInstance().getId();
원격 서버에 장치 ID를 저장해야 하는 경우 그대로(일반 텍스트) 저장하지 말고 소금을 사용 하여 해시하십시오.
오늘날 이는 모범 사례일 뿐만 아니라 실제로 GDPR(식별자 및 유사한 규정)에 따라 법에 따라 수행해야 합니다.
Nikita Kurtin
공식 Android 개발자 블로그에는 이제 바로 이 주제에 대한 전체 기사인 앱 설치 식별 이 있습니다.
BoD
Google I/O에서 Reto Meier는 설치 전반에 걸쳐 사용자를 추적해야 하는 대부분의 개발자 요구 사항을 충족해야 하는 접근 방법에 대한 강력한 답변을 발표했습니다. Anthony Nolan은 그의 대답에서 방향을 보여주지만, 나는 다른 사람들이 그것을 수행하는 방법을 쉽게 볼 수 있도록 전체 접근 방식을 작성해야 한다고 생각했습니다(자세한 내용을 파악하는 데 시간이 걸렸습니다).
이 접근 방식을 사용하면 여러 기기(기본 Google 계정 기반) 및 설치 전반에 걸쳐 사용자에게 영구적인 익명의 보안 사용자 ID가 제공됩니다. 기본 접근 방식은 임의의 사용자 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의 이야기를 참조하십시오.
백업 에이전트를 구현하는 방법에 대한 자세한 내용은 데이터 백업을 참조하십시오. 저는 특히 하단의 테스트 부분을 추천합니다. 백업은 순간적으로 이루어지지 않기 때문에 테스트를 하기 위해서는 백업을 강제로 해야 하기 때문입니다.
TechnoTony
이것은 고유 ID를 위한 스켈레톤을 구축하는 확실한 방법이라고 생각합니다. 확인하십시오.
모든 Android 장치에서 작동하는 Pseudo-Unique ID 일부 장치에는 전화가 없거나(예: 태블릿) 어떤 이유로 READ_PHONE_STATE 권한을 포함하고 싶지 않습니다. ROM 버전, 제조업체 이름, CPU 유형 및 기타 하드웨어 세부 정보와 같은 세부 정보는 계속 읽을 수 있으며, 이는 직렬 키 검사 또는 기타 일반적인 목적에 ID를 사용하려는 경우에 적합합니다. 이 방법으로 계산된 ID는 고유하지 않습니다. 동일한 ID(동일한 하드웨어 및 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 멤버는 문자열입니다. 여기서 우리가 하는 것은 길이를 가져와 모듈로를 통해 숫자로 변환하는 것입니다. 이러한 숫자가 13개 있고 IMEI(15자리)와 동일한 크기 ID를 갖도록 앞에 2개(35)를 추가합니다. 여기에 다른 가능성이 있습니다. 이 문자열을 살펴보십시오. 355715565309247 과 같은 355715565309247
반환합니다. 특별한 권한이 필요하지 않으므로 이 접근 방식이 매우 편리합니다.
(추가 정보: 위에 제공된 기술은 Pocket Magic 의 기사에서 복사했습니다.)
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) { }
Roman SL
아래 코드를 사용하여 Android OS 장치의 고유한 장치 ID를 문자열로 가져올 수 있습니다.
deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
Mohit Kanada
API 레벨 9(Android 2.3 - Gingerbread) Build
클래스에 Serial 필드가 추가되었습니다. 설명서에 따르면 하드웨어 일련 번호를 나타냅니다. 따라서 장치에 존재하는 경우 고유해야 합니다.
API 레벨 >= 9인 모든 장치에서 실제로 지원되는지 여부는 알 수 없습니다(= null 아님).
rony l
한 가지 덧붙이자면 저에게는 그런 독특한 상황이 있습니다.
사용:
deviceId = Secure.getString(this.getContext().getContentResolver(), Secure.ANDROID_ID);
내 Viewsonic G 태블릿이 Null이 아닌 DeviceID를 보고하더라도 모든 단일 G 태블릿이 동일한 번호를 보고하는 것으로 나타났습니다.
"고유한" DeviceID를 기반으로 다른 사람의 계정에 즉시 액세스할 수 있는 "Pocket Empires"를 플레이하는 것을 흥미롭게 만듭니다.
내 장치에는 셀 라디오가 없습니다.
Tony Maro
애플리케이션이 설치된 각 Android 기기의 고유 식별자를 얻는 방법에 대한 자세한 지침은 공식 Android 개발자 블로그 게시물 식별 앱 설치를 참조하세요.
가장 좋은 방법은 설치 시 직접 생성한 다음 응용 프로그램을 다시 시작할 때 읽는 것입니다.
나는 개인적으로 이것이 허용되지만 이상적이지는 않다고 생각합니다. Android에서 제공하는 하나의 식별자는 대부분 휴대전화의 무선 상태(Wi-Fi 켜기/끄기, 셀룰러 켜기/끄기, Bluetooth 켜기/끄기)에 따라 달라지므로 모든 경우에 작동하지 않습니다. 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(); } }
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" />
Android
ANDROID_ID
문제( null
일 수 있거나 특정 모델의 장치는 항상 동일한 ID를 반환함)를 해결하기 위한 다양한 접근 방식이 있습니다.
- 사용자 지정 ID 생성 알고리즘 구현(정적이어야 하고 변경되지 않는 장치 속성 기반 -> 누가 알겠습니까)
- IMEI , 일련 번호, Wi-Fi/Bluetooth-MAC 주소와 같은 다른 ID를 남용하는 경우(일부 기기에 존재하지 않거나 추가 권한이 필요한 경우)
저는 Android용 기존 OpenUDID 구현( https://github.com/ylechelle/OpenUDID 참조 )을 사용하는 것을 선호합니다 ( https://github.com/vieux/OpenUDID 참조 ). 통합하기 쉽고 위에서 언급한 문제에 대한 ANDROID_ID
Andreas Klöber
TelephonyManager
및 ANDROID_ID
사용하여 Android OS 장치의 고유한 장치 ID를 String으로 가져오는 방법은 다음과 같습니다.
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에서 제안한 방법을 적극 권장합니다( 앱 설치 식별 참조).
Jorgesys
여기에 30개 이상의 답변이 있으며 일부는 동일하고 일부는 고유합니다. 이 답변은 이러한 답변 중 일부를 기반으로 합니다. 그 중 하나는 @Lenn Dolling의 답변입니다.
3개의 ID를 결합하여 32자리 16진수 문자열을 생성합니다. 그것은 나를 위해 아주 잘 작동했습니다.
3개의 ID는 다음과 같습니다.
Pseudo-ID - 물리적 장치 사양을 기반으로 생성됩니다.
ANDROID_ID - Settings.Secure.ANDROID_ID
블루투스 주소 - 블루투스 어댑터 주소
다음과 같이 반환됩니다. 551F27C060712A72730B0A0F734064B1
longId
문자열에 더 많은 ID를 추가할 수 있습니다. 예를 들어 일련 번호. 와이파이 어댑터 주소. 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 또는 기타 모바일 장치에 고유합니다.
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 (ie Wi-Fi MAC, Bluetooth MAC, etc.) return null; }
Eng.Fouad
내 2센트 - NB 이것은 장치(오류) 고유 ID 용입니다. Android 개발자 블로그 에서 논의한 설치 ID가 아닙니다.
@emmby에서 제공하는 솔루션 은 SharedPreferences가 프로세스 간에 동기화되지 않기 때문에 애플리케이션 ID별로 대체됩니다( 여기 및 여기 참조). 그래서 나는 이것을 완전히 피했습니다.
대신 열거형에서 (장치) ID를 가져오기 위한 다양한 전략을 캡슐화했습니다. 열거형 상수의 순서를 변경하면 ID를 가져오는 다양한 방법의 우선 순위에 영향을 줍니다. null이 아닌 첫 번째 ID가 반환되거나 예외가 발생합니다(null 의미를 부여하지 않는 좋은 Java 관행에 따라). 예를 들어 TELEPHONY를 먼저 사용하지만 기본적으로 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); } } }
Mr_and_Mrs_D
또 다른 방법은 /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 원 V
- 미니 MK802
- 삼성 갤럭시 S II
또한 내 블로그 게시물 Leaking Android 하드웨어 일련 번호를 권한이 없는 앱에 표시 하여 다른 파일에서 정보를 얻을 수 있는지 논의할 수도 있습니다.
insitusec
TelephonyManger.getDeviceId() 고유한 장치 ID를 반환합니다(예: GSM의 경우 IMEI, CDMA 전화의 경우 MEID 또는 ESN).
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); String myAndroidDeviceId = mTelephony.getDeviceId();
그러나 다음을 사용하는 것이 좋습니다.
Android ID를 고유한 64비트 16진수 문자열로 반환하는 Settings.Secure.ANDROID_ID입니다.
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; }
Jorgesys
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 토큰(이전 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초가 귀찮을 수 있다고 생각합니다(물론 앱에 따라 다름).
Tom
특정 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가 포함된 목록에서 얻을 수 있는 다른 인터페이스가 많이 있습니다. 그러나 이것은 전화 간에 변경될 수 있습니다.
Ilan.b
다음 코드를 IMEI
를 얻거나 보안을 사용합니다. 기기에 전화 기능이 없을 때 대안으로 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);
Asaf Pinhassi
Android 기기에서 사용 가능한 고유 ID를 이해합니다. 이 공식 가이드를 사용하십시오.
고유 식별자에 대한 모범 사례:
IMEI, Mac 주소, 인스턴스 ID, GUID, SSAID, 광고 ID, 장치 확인을 위한 안전망 API.
https://developer.android.com/training/articles/user-data-ids
Waheed Nazir
1. 고유 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
가 필요하며, 이는 귀하가 만든 애플리케이션 유형을 따르는 것을 정당화하기 어려울 수 있습니다.
태블릿과 같은 전화 통신 서비스가 없는 기기는 Android 2.3 Gingerbread부터
android.os.Build.SERIAL
통해 사용할 수 있는 고유한 기기 ID를 보고해야 합니다. 전화 통신 서비스를 제공하는 일부 전화기는 일련 번호를 정의할 수도 있습니다. 모든 Android 기기에 일련 번호가 있는 것은 아니므로 이 솔루션은 신뢰할 수 없습니다.장치를 처음 부팅할 때 임의의 값이 생성되어 저장됩니다.
Settings.Secure.ANDROID_ID
를 통해 사용할 수 있습니다. 장치의 수명 동안 일정하게 유지되어야 하는 64비트 숫자입니다.ANDROID_ID
는 스마트폰과 태블릿에서 사용할 수 있기 때문에 고유한 기기 식별자로 좋은 선택인 것 같습니다. 값을 검색하려면 다음 코드를 사용할 수 있습니다.문자열 androidId = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
그러나 장치에서 공장 초기화를 수행하면 값이 변경될 수 있습니다. ANDROID_ID
가 있는 제조업체의 인기 있는 핸드셋에 알려진 버그가 있습니다. 분명히 솔루션은 100% 신뢰할 수 없습니다.
- UUID를 사용합니다. 대부분의 응용 프로그램에 대한 요구 사항은 물리적 장치가 아닌 특정 설치를 식별하는 것이므로 UUID 클래스를 사용하는 경우 사용자의 고유 ID를 얻는 좋은 솔루션입니다. 다음 솔루션은 Google I/O 프레젠테이션에서 Google의 Reto Meier가 발표한 것입니다.
SharedPreferences sharedPrefs = context.getSharedPreferences( PREF_UNIQUE_ID, Context.MODE_PRIVATE); uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
업데이트 : 옵션 #1 및 #2 는 Google의 개인 정보 업데이트로 Android 10 이후 더 이상 사용할 수 없습니다. 옵션 2와 3에는 중요한 권한이 필요합니다.
Kiran Maniya
출처 : http:www.stackoverflow.com/questions/2785485/is-there-a-unique-android-device-id
'etc. > StackOverFlow' 카테고리의 다른 글
한 줄에 여러 예외 잡기(블록 제외) (0) | 2021.11.05 |
---|---|
대소문자를 구분하지 않는 'Contains(string)' (0) | 2021.11.05 |
사전에 새 키를 추가하려면 어떻게 해야 합니까? (0) | 2021.10.27 |
SQLite의 초당 INSERT 성능 향상 (0) | 2021.10.27 |
403 금지됨 대 401 승인되지 않은 HTTP 응답 (0) | 2021.10.27 |