독특한 안드로이드 장치 ID가 있습니까?
질문
Android 기기에는 고유 한 ID가 있고 그렇다면 Java를 사용하여 액세스 할 간단한 방법은 무엇입니까?
답변
SENTINGS.SECURE # ANDROID_ID 각 사용자 64 비트 HEX 문자열마다 고유 한 Android ID를 반환합니다.
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의 많은 문제가 해결 되었으며이 접근 방식이 더 이상 필요하지 않습니다.Anthony의 답변을 살펴보십시오.
전체 공개 : 내 앱은 원래 아래의 접근 방식을 사용했지만 더 이상이 접근 방식을 사용하지 않으며, 이제 EMMBY의 응답 (즉, UUID # randomuuid ()을 생성하고 저장하고 저장합니다).
이 질문에 대한 많은 답변이 있으며, 대부분의 시간은 "어떤 시간"과 불행히도 충분하지 않습니다.
장치의 테스트 (모든 전화기, 적어도 하나는 활성화되지 않은 모든 전화)를 기반으로합니다.
- All devices tested returned a value for
TelephonyManager.getDeviceId()
- All GSM devices (all tested with a SIM) returned a value for
TelephonyManager.getSimSerialNumber()
- All CDMA devices returned null for
getSimSerialNumber()
(as expected) - All devices with a Google account added returned a value for
ANDROID_ID
- All CDMA devices returned the same value (or derivation of the same value) for both
ANDROID_ID
andTelephonyManager.getDeviceId()
-- as long as a Google account has been added during setup. - I did not yet have a chance to test GSM devices with no SIM, a GSM device with no Google account added, or any of the devices in airplane mode.
따라서 장치 자체에 고유 한 것을 원한다면 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과 같은 것을 초래할 수 있습니다
그것은 나를 위해 충분히 잘 작동합니다.
Richard는 아래에 언급하므로 TelephonyManager 속성을 읽을 수있는 권한이 필요하다는 것을 잊지 마십시오.이를 매니페스트에 추가하십시오.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
라이브러리 가져 오기
import android.content.Context;
import android.telephony.TelephonyManager;
import android.view.View;
답변
#last 업데이트 됨 : 6/2/15.
고유 ID, Google 개발자 블로그 및 Android 문서를 만드는 모든 스택 오버플로 게시물을 읽은 후에는 '의사 ID'가 최상의 옵션이라는 것처럼 느껴집니다.
주요 문제 : 하드웨어 대 소프트웨어
하드웨어
사용자는 하드웨어, Android 태블릿 또는 전화를 변경할 수 있으므로 하드웨어를 기반으로하는 고유 한 ID가 사용자를 추적하는 데 좋은 아이디어가 아닙니다. 하드웨어 추적을 위해 이것은 훌륭한 아이디어입니다
소프트웨어
사용자가 뿌리를 내리면 rom을 삭제 / 변경할 수 있습니다. 플랫폼간에 사용자를 추적 할 수 있습니다 (iOS, Android, Windows 및 Web) 동의를 가진 개별 사용자를 추적하고자하는 것이 가장 좋습니다.
# 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 + <사용 권한 Android : name = "android.permission.get_accounts"/> 또는 API 14 + <사용 권한 Android : name = "android.permission.read_profile"/> <사용 권한 Android : name = "android.permission.read_contacts"/> (Android 기기의 기본 전자 메일 주소를 얻는 방법) 사용자 전화 번호 - 소프트웨어 사용자는 전화 번호를 변경할 수 있습니다 <사용 권한 Android : name = "android.permission.read_phone_state"/> IMEI - 하드웨어 (휴대폰 만 android.permission.read_phone_state가 필요함) 대부분의 사용자는 허가에서 "전화 통화"라는 사실을 싫어합니다. 일부 사용자는 실제로 수행하려는 모든 일이 실제로 원하는 모든 일이 실제로 수행 할 때 개인 정보를 훔치는 것이 좋습니다. 그것은 당신이 데이터를 수집하는 것이 분명합니다. <사용 권한 Android : name = "android.permission.read_phone_state"/> Android ID - 하드웨어 (NULL 일 수 있으며 공장 초기화시 변경할 수 있으며 루팅 된 장치에서 변경할 수 있습니다) 'null'일 수 있으므로 'null'을 확인하고 그 값을 변경할 수 있지만 더 이상 더 이상 고유하지는 않습니다. 팩토리 리셋 장치가있는 사용자가있는 경우 루팅 장치에서 값이 변경되거나 변경되었을 수 있으므로 사용자 설치를 추적하는 경우 항목이 복제됩니다. WLAN MAC 주소 - 하드웨어 (Android.permission.access_wifi_state 필요) 이는 두 번째로 가장 좋은 옵션 일 수 있지만 사용자에게 직접 제공되는 고유 식별자를 수집하고 저장하는 것입니다. 이것은 당신이 데이터를 수집하는 것이 분명합니다. <사용 권한 Android : name = "android.permission.access_wifi_state"/> 블루투스 MAC 주소 - 하드웨어 (블루투스가있는 장치, Android.Permission.Bluetooth가 필요함) 시장에서 대부분의 응용 프로그램은 Bluetooth를 사용하지 않으므로 응용 프로그램이 Bluetooth를 사용하지 않으면 사용자가 의심 스러울 수 있습니다. <사용 권한 Android : 이름 = "android.permission.bluetooth"/> 의사 고유 ID - 소프트웨어 (모든 Android 기기의 경우) 매우 가능합니다. 충돌이 포함될 수 있습니다 - 아래에 게시 된 내 방법을 참조하십시오! 이렇게하면 비공개 인 것을 취소하지 않고도 사용자에게 '거의 독특한'이드를 가질 수 있습니다. 장치 정보에서 자신의 익명의 ID를 만들 수 있습니다.
권한을 사용하지 않고 고유 한 ID를 얻는 '완벽한'방법이 없다는 것을 알고 있습니다.그러나 때로는 장치 설치를 추적 할 필요가 있습니다.고유 한 ID를 만드는 경우 Android API가 추가 사용 권한을 사용하지 않고도 우리에게 제공하는 정보에만 해당하는 '의사 고유 ID'를 만들 수 있습니다.이렇게하면 사용자 존경을 보여주고 좋은 사용자 경험을 제공 할 수 있습니다.
의사 고유 ID를 사용하면 비슷한 장치가 있음을 기반으로 중복이있을 수 있다는 사실에만 실제로 실행됩니다.결합 된 방법을 조정하여 더 독특하게 만들 수 있습니다.그러나 일부 개발자는 장치 설치를 추적해야하며 비슷한 장치를 기반으로 트릭이나 성능을 수행합니다.
## api> = 9 :
Android 기기가 API 9 이상인 경우 'build.serial'필드 때문에 고유하게 보장됩니다.
API <9가있는 사용자의 약 0.5 %의 사용자의 약 0.5 %가 거친 것을 기억하십시오. 이것은 나머지 부분에 집중할 수 있습니다. 이것은 사용자의 99.5 %입니다!
## API <9 :
사용자의 안드로이드 장치가 API 9보다 낮 으면;바라건대, 그들은 공장 재설정을하지 않았으며 'secure.android_id'가 보존되거나 'null'가 아닌가 아닙니다.(http://developer.android.com/about/dashboards/index.html 참조)
## 모두가 실패하면 :
모든 다른 모든 경우 사용자가 API 9보다 낮 으면 장치를 재설정하거나 '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 개발자 프로그램 정책 모든 새로운 앱 업로드 및 업데이트가 필요합니다. 어떤 광고 목적 으로든 다른 지속적인 식별자를 대신합니다. 더 알아보기
구현:
허가:
<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/identifer/advertisingidclient.html.
##중요한:
그것은 광고 ID가 기존을 완전히 대체하는 것으로 의도된다. 광고 목적으로 다른 식별자의 사용 (예 : Android_ID 사용 Google Play 서비스를 사용할 수있는 경우 설정.사례 Google Play 서비스를 사용할 수없는 경우 GooglePlayServicesNotAvailableException이 던져진다 getAdvertisingInfo ().
## 경고, 사용자가 재설정 할 수 있습니다.
http://en.kioskea.net/faq/34732-Android-Reset-Your-advertiving-ID.
나는 내가 정보를 얻은 모든 링크를 참조하려고 노력했다.누락되고 포함되어야하는 경우에는 의견을 말해주십시오!
Google Player Services 인스트니다
https://developers.google.com/instance-id/
답변
Dave WebB가 언급하면서 Android 개발자 블로그에는이를 다루는 기사가 있습니다.선호되는 해결책은 장치가 아닌 앱 설치를 추적하고 대부분의 사용 사례에서는 잘 작동합니다.블로그 게시물은 그 일을하는 데 필요한 코드를 보여줄 것이고, 확인하는 것이 좋습니다.
그러나 앱 설치 식별자가 아닌 장치 식별자가 아닌 장치 식별자가 필요한 경우 블로그 게시물이 솔루션을 논의하기 위해 계속됩니다.나는 당신이 그렇게 해야하는 경우 몇 가지 항목에 대한 몇 가지 추가 설명을 얻으려면 Google에서 누군가와 이야기했습니다.다음은 앞서 언급 한 블로그 게시물에 언급되지 않은 장치 식별자에 대해 알았던 것입니다.
android_id가 기본 설정된 장치 식별자입니다.Android_ID는 Android 버전에서 완벽하게 신뢰할 수 있습니다 <= 2.1 또는> = 2.3.2.2만이 게시물에 언급 된 문제가 있습니다. 여러 제조업체의 여러 장치는 2.2의 Android_ID 버그의 영향을받습니다. 내가 결정할 수있는 한, 영향을받는 모든 장치는 9774D56D682E549C 인 Android_ID가 동일합니다.또한 에뮬레이터에 의해보고 된 동일한 장치 ID 인 BTW입니다. Google은 OEM이 많은 또는 대부분의 장치에 대한 문제를 패치 한 것으로 믿지만 2011 년 4 월 초반부터 Android_ID가 깨진 장치를 찾는 것은 여전히 쉽습니다.
Google의 권장 사항을 기반으로, 각 장치에 대한 고유 한 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;
}
}
답변
다음은 사용자에게 고유 한 ID를 얻으려면 올해 Google I / O 프레젠테이션에서 사용 된 Google I / O 프레젠테이션에서 사용 된 코드입니다.
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;
}
클라우드에 환경 설정을 보낼 백업 전략 으로이 작업을 수행하는 경우 (Retro의 Talk에서도 설명한 경우, 사용자가 묶어서 장치가 닦거나 교체 된 후에도 주위에 끼워지는 ID가 있어야합니다. 나는 이것을 사용할 계획이다.분석에서 앞으로 나아가는 (즉, 나는 아직 그것을하지 않았습니다 :).
답변
또한 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
출처:https://stackoverflow.com/questions/2785485/is-there-a-unique-android-device-id
최근댓글