Android 기기의 일련 번호를 찾는 방법은 무엇입니까?


115

Android 앱에 고유 ID를 사용해야하는데 기기의 일련 번호가 좋은 후보라고 생각했습니다. 내 앱에서 Android 장치의 일련 번호를 검색하려면 어떻게합니까?


2
이름 = 매니페스트에 "android.permission.READ_PHONE_STATE의"안드로이드 추가하는 것을 잊지 마세요
마이클 SIlveus


당신이 어떤 권한이없는 고유 한 ID를 얻고 싶은 경우에, 당신은 사용할 수 있습니다 이 라이브러리를 가진 장치마다 고유 ID 중 하나를 생성하는 Identity.getDeviceId (컨텍스트) 를 통해 또는 앱 설치에 대한 식별자 Identity.getInstallationId (컨텍스트) .
caw

답변:


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

getSystemService는 Activity 클래스의 메소드입니다. getDeviceID ()는 전화기가 사용하는 무선 (GSM 또는 CDMA)에 따라 장치의 MDN 또는 MEID를 반환합니다.

각 기기는 여기에서 고유 한 값을 반환해야합니다 (휴대 전화라고 가정). 이것은 sim 슬롯 또는 CDMA 라디오가있는 모든 Android 장치에서 작동합니다. Android 구동 전자 레인지를 사용하면됩니다 ;-)


@Hasemam 이것은 나를 위해 작동하지 않고 "강제 닫기"오류를 제공합니다
Paresh Mayani

23
@Hasemam은 androidManifest.xml 파일에 <uses-permission android : name = "android.permission.READ_PHONE_STATE"> </ uses-permission> 권한을 추가 한 후 정상적으로 실행됩니다.
Paresh Mayani

23
이 식별자 사용에 대한 공식 Android 개발자 블로그에 몇 가지 조언이 있습니다. android-developers.blogspot.com/2011/03/…
David Snabel-Caunt 2011

8
Android 구동 전자 레인지를 제외하고 Android 구동 태블릿은 어떻습니까? :)
ajacian81

21
이 방법은 피해야합니다.이 방법은 휴대폰에서는 작동하지만 휴대폰 칩이없는 장치에서는 작동하지 않습니다 (태블릿이 한 예임). 2.3부터는 android.os.Build.SERIAL을 사용할 수 있지만 @DavidCaunt가 제안한 개발자 블로그를 확인하십시오.
John Mitchell

71

Dave Webb이 언급했듯이 Android 개발자 블로그에는 이를 다루는 가 있습니다.

몇 가지 항목에 대한 추가 설명을 얻기 위해 Google 직원과 이야기했습니다. 앞서 언급 한 블로그 게시물에서 언급되지 않은 내용은 다음과 같습니다.

  • ANDROID_ID가 선호되는 솔루션입니다. ANDROID_ID는 Android <= 2.1 또는> = 2.3 버전에서 완벽하게 신뢰할 수 있습니다. 2.2 만 게시물에 언급 된 문제가 있습니다.
  • 여러 제조업체의 여러 기기가 2.2의 ANDROID_ID 버그의 영향을받습니다.
  • 지금까지 내가 결정할 수있었습니다으로, 영향을받는 모든 장치는이 같은 ANDROID_ID 입니다 9774d56d682e549c을 . 에뮬레이터 btw에서보고 한 것과 동일한 장치 ID이기도합니다.
  • Google은 OEM이 대부분 또는 대부분의 기기에 문제를 패치했다고 생각하지만, 적어도 2011 년 4 월 초부터 ANDROID_ID가 고장난 기기를 찾는 것이 여전히 꽤 쉬웠 음을 확인할 수있었습니다.

Google의 권장 사항에 따라 적절한 경우 ANDROID_ID를 시드로 사용하고 필요에 따라 TelephonyManager.getDeviceId ()로 폴백하고, 실패 할 경우 무작위로 생성 된 고유 UUID를 사용하여 각 기기에 대해 고유 한 UUID를 생성하는 클래스를 구현했습니다. 앱을 다시 시작해도 유지됩니다 (앱 재설치는 아님).

import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;

import java.io.UnsupportedEncodingException;
import java.util.UUID;

public class DeviceUuidFactory {

    protected static final String PREFS_FILE = "device_id.xml";
    protected static final String PREFS_DEVICE_ID = "device_id";
    protected static volatile UUID uuid;

    public DeviceUuidFactory(Context context) {
        if (uuid == null) {
            synchronized (DeviceUuidFactory.class) {
                if (uuid == null) {
                    final SharedPreferences prefs = context
                            .getSharedPreferences(PREFS_FILE, 0);
                    final String id = prefs.getString(PREFS_DEVICE_ID, null);
                    if (id != null) {
                        // Use the ids previously computed and stored in the
                        // prefs file
                        uuid = UUID.fromString(id);
                    } else {
                        final String androidId = Secure.getString(
                            context.getContentResolver(), Secure.ANDROID_ID);
                        // Use the Android ID unless it's broken, in which case
                        // fallback on deviceId,
                        // unless it's not available, then fallback on a random
                        // number which we store to a prefs file
                        try {
                            if (!"9774d56d682e549c".equals(androidId)) {
                                uuid = UUID.nameUUIDFromBytes(androidId
                                        .getBytes("utf8"));
                            } else {
                                final String deviceId = ((TelephonyManager) 
                                        context.getSystemService(
                                            Context.TELEPHONY_SERVICE))
                                            .getDeviceId();
                                uuid = deviceId != null ? UUID
                                        .nameUUIDFromBytes(deviceId
                                                .getBytes("utf8")) : UUID
                                        .randomUUID();
                            }
                        } catch (UnsupportedEncodingException e) {
                            throw new RuntimeException(e);
                        }
                        // Write the value out to the prefs file
                        prefs.edit()
                                .putString(PREFS_DEVICE_ID, uuid.toString())
                                .commit();
                    }
                }
            }
        }
    }

    /**
     * Returns a unique UUID for the current android device. As with all UUIDs,
     * this unique ID is "very highly likely" to be unique across all Android
     * devices. Much more so than ANDROID_ID is.
     * 
     * The UUID is generated by using ANDROID_ID as the base key if appropriate,
     * falling back on TelephonyManager.getDeviceID() if ANDROID_ID is known to
     * be incorrect, and finally falling back on a random UUID that's persisted
     * to SharedPreferences if getDeviceID() does not return a usable value.
     * 
     * In some rare circumstances, this ID may change. In particular, if the
     * device is factory reset a new device ID may be generated. In addition, if
     * a user upgrades their phone from certain buggy implementations of Android
     * 2.2 to a newer, non-buggy version of Android, the device ID may change.
     * Or, if a user uninstalls your app on a device that has neither a proper
     * Android ID nor a Device ID, this ID may change on reinstallation.
     * 
     * Note that if the code falls back on using TelephonyManager.getDeviceId(),
     * the resulting ID will NOT change after a factory reset. Something to be
     * aware of.
     * 
     * Works around a bug in Android 2.2 for many devices when using ANDROID_ID
     * directly.
     * 
     * @see http://code.google.com/p/android/issues/detail?id=10603
     * 
     * @return a UUID that may be used to uniquely identify your device for most
     *         purposes.
     */
    public UUID getDeviceUuid() {
        return uuid;
    }
}

1
앱에서이를 사용하려면 어떤 권한이 필요합니까?
Dave L.

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

1
@ ef2011 그것은 이중 확인 잠금 패턴입니다 : en.wikipedia.org/wiki/Double-checked_locking
emmby

3
게시 해 주셔서 감사합니다. 그러나 루팅 된 전화를 가진 누군가가 단순히 device_id.xml을 편집하여 자신이 선택한 새 UUID를 입력하지 못하도록 막는 방법은 무엇입니까? (즉, '무료 평가판'검사를 우회하기 위해) 임의의 ID 방법을 사용해야하는 경우 클래스가 기본 설정 파일에만 값을 저장하는 것이 더 좋지 않습니까? 그렇지 않으면 응용 프로그램 실행 사이에이를 유지할 필요가 없습니다. 재생성하는 것이 더 안전합니다.
Carlos P

1
"ANDROID_ID"가 선호되는 솔루션입니다. "ANDROID_ID는 더 이상 장치를 고유하게 식별하지 않습니다. stackoverflow.com/a/13465373/150016
Tom

32
String serial = null; 

try {
    Class<?> c = Class.forName("android.os.SystemProperties");
    Method get = c.getMethod("get", String.class);
    serial = (String) get.invoke(c, "ro.serialno");
} catch (Exception ignored) {
}

이 코드는 숨겨진 Android API를 사용하여 기기 일련 번호를 반환합니다.


7
이것은 단지 나에게 내가 android.os.Build.SERIAL로 얻을 것과 같은 값을 제공합니다
요세푸스

내가 잘못했거나 특정 사용자 지정 ROM이있는 모든 장치에서이 일련 번호가 동일합니까? 내 장치 일련 번호 (eclipse 장치 실행기에서)는 사용자 지정 ROM이있는 전화기의 경우 01234567890ABC를 표시합니다.
Peterdk

cyanogen-9를 사용하는 내 장치의 @Peterdk 두 가지 방법 (답변에있는 andy-9 이전 및 andy-9에서 사용할 수있는 쉬운 방법)이 올바른 s / n (제조업체 스티커와 동일)을보고합니다. 그러나 특정 사용자 지정 ROM 버전에 따라 다를 수 있습니다. 어떤 ROM / 버전을 사용하고 있습니까?
morgwai

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

하지만 Android ID가 고유 한 식별자라는 보장은 없습니다.


@Paresh Mayani, 코드를 보지 않고는 문제가 무엇인지 말하기가 어렵습니다. 내 유일한 가정은 getContentResolver돌아 오는 것 null입니다. 그러나 질문을 열고 코드를 게시하는 동안 가치가있을 수 있습니다.
Anthony Forloney

4
이 ID는 전화와 연결된 Google 계정에서 가져옵니다. 시뮬레이터에는 일반적으로 하나가 없습니다. 실제 전화에는 하나도 없을 수 있습니다. 또한 "초기화시 변경 가능"으로 문서화되어 있으며 루팅 된 휴대폰에서 언제든지 임의로 변경할 수 있습니다. 자신의 책임하에 사용하십시오. 좋은 대안은 없습니다. 다른 임시 장치 ID는 보편적으로 사용할 수 없거나 고유하지 않거나 둘 다입니다. 이 슬픈 이야기의 나머지 부분에 대해서는 다른 답변을 참조하십시오.
Seva Alekseyev

14

이에 대해 논의하는 Android 개발자 블로그에 훌륭한 게시물이 있습니다.

TelephonyManager.getDeviceId()태블릿과 같은 휴대폰이 아닌 안드로이드 기기에서는 작동하지 않으므로 사용 을 권장 하지 않습니다.READ_PHONE_STATE 권한 모든 휴대폰에서 안정적으로 작동하지 않습니다.

대신 다음 중 하나를 사용할 수 있습니다.

  • Mac 주소
  • 일련 번호
  • ANDROID_ID

이 게시물은 각각의 장단점에 대해 설명하며 어느 것이 가장 적합한 지 알아낼 수 있도록 읽을 가치가 있습니다.


+1, 안녕하세요 dave, 고맙습니다. 지금은 태블릿 용 애플리케이션을 개발 중입니다. 현재 Android 기기의 고유 ID가 필요한 경우 고유 Android 태블릿 기기를 얻으려면 무엇을 사용해야합니까?
Paresh Mayani 2011

12

기기에 고유하고 수명 동안 일정한 (초기화 또는 해킹 제외) 단순한 숫자의 경우 Settings.Secure.ANDROID_ID를 사용 하세요 .

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

가능한 경우 기기 일련 번호 ( '시스템 설정 / 정보 / 상태'에 표시된 번호)를 사용하고 Android ID로 대체하려면 다음 단계를 따르세요.

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

솔직한 대답 !!
faris faris

Build.SERİAL은 자바에서 더 이상 사용되지 않습니다
Eyyüp Alkış

7

IMEI는 좋지만 휴대 전화가있는 Android 기기에서만 작동합니다. 휴대 전화가없는 태블릿 또는 기타 Android 기기에 대한 지원도 고려해야합니다.

클래스 멤버 빌드, BT MAC, WLAN MAC 등의 대안이 있습니다.이 모든 것의 조합입니다.

내 블로그의 기사에서 이러한 세부 사항을 설명했습니다. http://www.pocketmagic.net/?p=1662


6

여기에는 시스템 업데이트를 통해 지속되고 모든 장치에 존재하는 완벽한 오류 방지 ID가 언급되어 있지 않기 때문에 (주로 Google의 개별 솔루션이 없다는 사실로 인해) 저는 다음과 같은 방법을 게시하기로 결정했습니다. 두 개의 사용 가능한 식별자를 결합하고 런타임에 둘 중에서 선택하는 검사를 통해 차선책입니다.

코드 이전에 3 가지 사실 :

  1. TelephonyManager.getDeviceId()(akaIMEI)는 GSM, 3G, LTE 등이 아닌 기기에서는 잘 작동하지 않거나 전혀 작동하지 않지만 관련 하드웨어가 있으면 항상 고유 ID를 반환합니다. SIM이 삽입되지 않았거나 SIM 슬롯이없는 경우에도 마찬가지입니다 ( 일부 OEM이이 작업을 수행했습니다.)

  2. Gingerbread (Android 2.3) android.os.Build.SERIAL 는 IMEI를 제공하지 않는 모든 기기에 있어야합니다. 즉, Android 정책에 따라 앞서 언급 한 하드웨어가 없습니다.

  3. 사실 (2.)로 인해이 두 고유 식별자 중 적어도 하나는 항상 존재 하며 SERIAL IMEI와 동시에 존재할 있습니다.

참고 : 사실 (1.) 및 (2.)는 Google 진술을 기반으로합니다.

해결책

위의 사실을 통해 IMEI 바인딩 하드웨어가 있는지 확인하여 항상 고유 식별자를 가질 수 있으며, 기존 SERIAL이 유효한지 확인할 수 없으므로 그렇지 않은 경우 SERIAL로 폴백 할 수 있습니다. 다음 정적 클래스는 이러한 존재를 확인하고 IMEI 또는 SERIAL을 사용하는 두 가지 방법을 제공합니다.

import java.lang.reflect.Method;

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

public class IDManagement {

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

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

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

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

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


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

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

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

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


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

        int simState = telMgr.getSimState();

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

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

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

        PackageManager pm = mContext.getPackageManager();

        if (pm == null)
            return false;

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

        return retval;
    }


}

나는 getCleartextID_HARDCHECK. 반사가 환경에 고정되지 않으면 getCleartextID_SIMCHECK대신 방법을 사용하되 특정 SIM 존재 요구 사항에 맞게 조정해야한다는 점을 고려하십시오.

추신 : OEM은 Google 정책 (동일한 SERIAL을 사용하는 여러 기기) 에 대해 SERIAL을 버그로 처리 했으며 Google은 대형 OEM에 알려진 사례가 하나 이상 있다고 언급했습니다 (공개되지 않았고 어떤 브랜드인지 모르겠습니다) 어느 쪽이든, 나는 삼성을 추측하고있다).

면책 조항 : 이것은 고유 장치 ID를 얻는 원래 질문에 대한 답변이지만 OP는 APP에 대한 고유 ID가 필요하다는 것을 명시하여 모호성을 도입했습니다. 이러한 시나리오의 경우 Android_ID가 더 좋더라도 2 개의 다른 ROM 설치를 통한 앱의 티타늄 백업 (동일한 ROM 일 수도 있음) 후에는 작동하지 않습니다. 내 솔루션은 플래시 또는 공장 초기화와 무관 한 지속성을 유지하며 해킹 / 하드웨어 모드를 통해 IMEI 또는 SERIAL 변조가 발생할 때만 실패합니다.


5

위의 모든 접근 방식에는 문제가 있습니다. Google i / o에서 Reto Meier는 설치 전반에 걸쳐 사용자를 추적하는 데 필요한 대부분의 개발자를 충족해야하는 접근 방법에 대한 강력한 답변을 발표했습니다.

이 접근 방식은 다른 기기 (기본 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>

그런 다음 백업 에이전트를 만들고 공유 기본 설정에 대한 도우미 에이전트를 사용하도록 지시해야합니다.

public class MyBackupAgent extends BackupAgentHelper {
    // The name of the SharedPreferences file
    static final String PREFS = "user_preferences";

    // A key to uniquely identify the set of backup data
    static final String PREFS_BACKUP_KEY = "prefs";

    // Allocate a helper and add it to the backup agent
    @Override
    public void onCreate() {
        SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this,          PREFS);
        addHelper(PREFS_BACKUP_KEY, helper);
    }
}

백업을 완료하려면 기본 활동에서 BackupManager 인스턴스를 만들어야합니다.

BackupManager backupManager = new BackupManager(context);

마지막으로 사용자 ID가없는 경우 생성하고 SharedPreferences에 저장합니다.

  public static String getUserID(Context context) {
            private static String uniqueID = null;
        private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";
    if (uniqueID == null) {
        SharedPreferences sharedPrefs = context.getSharedPreferences(
                MyBackupAgent.PREFS, Context.MODE_PRIVATE);
        uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
        if (uniqueID == null) {
            uniqueID = UUID.randomUUID().toString();
            Editor editor = sharedPrefs.edit();
            editor.putString(PREF_UNIQUE_ID, uniqueID);
            editor.commit();

            //backup the changes
            BackupManager mBackupManager = new BackupManager(context);
            mBackupManager.dataChanged();
        }
    }

    return uniqueID;
}

이 User_ID는 이제 사용자가 장치를 전환하더라도 설치 전반에 걸쳐 지속됩니다.

이 접근 방식에 대한 자세한 내용은 여기에서 Reto의 이야기를 참조 하십시오. http://www.google.com/events/io/2011/sessions/android-protips-advanced-topics-for-expert-android-app-developers.html

백업 에이전트를 구현하는 방법에 대한 자세한 내용은 여기 개발자 사이트를 참조하십시오. http://developer.android.com/guide/topics/data/backup.html 특히 백업이 수행하는 것처럼 테스트 하단의 섹션을 권장합니다. 즉시 발생하지 않으므로 테스트하려면 백업을 강제해야합니다.


2

또 다른 방법은 권한이없는 앱에서 / sys / class / android_usb / android0 / iSerial을 사용하는 것입니다.

user@creep:~$ adb shell ls -l /sys/class/android_usb/android0/iSerial
-rw-r--r-- root     root         4096 2013-01-10 21:08 iSerial
user@creep:~$ adb shell cat /sys/class/android_usb/android0/iSerial
0A3CXXXXXXXXXX5

Java에서이를 수행하려면 FileInputStream을 사용하여 iSerial 파일을 열고 문자를 읽습니다. 모든 장치에이 파일이있는 것은 아니므로 예외 처리기로 래핑해야합니다.

최소한 다음 장치가이 파일을 세계에서 읽을 수있는 것으로 알려져 있습니다.

  • Galaxy Nexus
  • Nexus S
  • Motorola Xoom 3g
  • 도시바 AT300
  • HTC One V
  • 미니 MK802
  • 삼성 Galaxy S II

여기에서 내 블로그 게시물을 볼 수도 있습니다. http://insitusec.blogspot.com/2013/01/leaking-android-hardware-serial-number.html 여기서 정보를 얻을 수있는 다른 파일에 대해 논의합니다.


답변을 게시 해 주셔서 감사합니다! Self-Promotion에 대한 FAQ를 주의 깊게 읽어 보시기 바랍니다 . 또한 자신의 사이트 / 제품에 연결할 때마다 면책 조항을 게시 해야 합니다.
Andrew Barber

1

@haserman이 말했듯이 :

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

그러나 매니페스트 파일에 권한을 포함해야합니다.

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

1

Android OS 기기의 고유 기기 ID (문자열).

String deviceId;
    final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        if (mTelephony.getDeviceId() != null){
            deviceId = mTelephony.getDeviceId(); 
         }
        else{
            deviceId = Secure.getString(getApplicationContext().getContentResolver(),   Secure.ANDROID_ID); 
         }

하지만 Google에서 제안한이 방법을 강력히 권장합니다.

앱 설치 식별


1

Build.SERIAL비어 있을 있거나 때로는 기기 설정에서 볼 수 있는 것과 다른 값 ( 증명 1 , 증명 2 )을 반환 할 수 있으므로 완전히 신뢰할 수는 없지만 가장 간단한 방법 입니다.

기기 제조업체와 Android 버전에 따라 해당 번호를 얻는 방법은 여러 가지가 있으므로 단일 요점 에서 찾을 수있는 가능한 모든 솔루션을 컴파일하기로 결정했습니다 . 다음은 단순화 된 버전입니다.

public static String getSerialNumber() {
    String serialNumber;

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

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

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

    return serialNumber;
}

0

이 질문은 오래되었지만 한 줄의 코드로 수행 할 수 있습니다.

String deviceID = Build.SERIAL;


AFAIK, 이것은 장치의 OS 업데이트 후에 변경됩니다 (예 : 4.4.2에서 4.4.4로).
Den Drobiazko 2015-06-18

-1

위의 @emmby가 게시 한 예제 클래스가 훌륭한 출발점이라는 것을 알았습니다. 그러나 다른 포스터에서 언급했듯이 몇 가지 결함이 있습니다. 중요한 것은 UUID를 XML 파일에 불필요하게 유지하고 그 후에는 항상이 파일에서 검색한다는 것입니다. 이것은 수업을 쉽게 해킹 할 수있는 기회를 제공합니다. 루팅 된 전화를 가진 사람은 누구나 XML 파일을 편집하여 새로운 UUID를 제공 할 수 있습니다.

절대적으로 필요한 경우 (즉, 임의로 생성 된 UUID를 사용할 때) XML로만 유지되도록 코드를 업데이트하고 @Brill Pappin의 답변에 따라 논리를 리팩터링했습니다.

import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;

import java.io.UnsupportedEncodingException;
import java.util.UUID;

public class DeviceUuidFactory {
    protected static final String PREFS_FILE = "device_id.xml";
    protected static final String PREFS_DEVICE_ID = "device_id";

    protected static UUID uuid;

    public DeviceUuidFactory(Context context) {

        if( uuid ==null ) {
            synchronized (DeviceUuidFactory.class) {
                if( uuid == null) {
                    final SharedPreferences prefs = context.getSharedPreferences( PREFS_FILE, 0);
                    final String id = prefs.getString(PREFS_DEVICE_ID, null );

                    if (id != null) {
                        // Use the ids previously computed and stored in the prefs file
                        uuid = UUID.fromString(id);

                    } else {

                        final String androidId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);

                        // Use the Android ID unless it's broken, in which case fallback on deviceId,
                        // unless it's not available, then fallback on a random number which we store
                        // to a prefs file
                        try {
                             if ( "9774d56d682e549c".equals(androidId) || (androidId == null) ) {
                                final String deviceId = ((TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE )).getDeviceId();

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

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



                    }

                }
            }
        }

    }


    /**
     * Returns a unique UUID for the current android device.  As with all UUIDs, this unique ID is "very highly likely"
     * to be unique across all Android devices.  Much more so than ANDROID_ID is.
     *
     * The UUID is generated by using ANDROID_ID as the base key if appropriate, falling back on
     * TelephonyManager.getDeviceID() if ANDROID_ID is known to be incorrect, and finally falling back
     * on a random UUID that's persisted to SharedPreferences if getDeviceID() does not return a
     * usable value.
     *
     * In some rare circumstances, this ID may change.  In particular, if the device is factory reset a new device ID
     * may be generated.  In addition, if a user upgrades their phone from certain buggy implementations of Android 2.2
     * to a newer, non-buggy version of Android, the device ID may change.  Or, if a user uninstalls your app on
     * a device that has neither a proper Android ID nor a Device ID, this ID may change on reinstallation.
     *
     * Note that if the code falls back on using TelephonyManager.getDeviceId(), the resulting ID will NOT
     * change after a factory reset.  Something to be aware of.
     *
     * Works around a bug in Android 2.2 for many devices when using ANDROID_ID directly.
     *
     * @see http://code.google.com/p/android/issues/detail?id=10603
     *
     * @return a UUID that may be used to uniquely identify your device for most purposes.
     */
    public UUID getDeviceUuid() {
        return uuid;
    }

ID를 공유 환경에 넣으면 정말 고유 한 ID를 얻으려는 원래의 목표가 손상됩니다. 예를 들어 해당 ID를 일부 제한 사항에 대한 키로 사용하려는 경우 숙련 된 사용자가 장치를 루팅하고 공유 환경 설정 파일에 액세스 할 때 문제가 발생할 수 있습니다. 그 내용은 복사 될 수 있습니다. 즉 ...
Eugene Wechsler

또한 MB의 답변과 귀하의 답변에 또 다른 오류가 있습니다 .. deviceID 및 appID로 randomUUID를 사용하면 전화인지 여부 또는 Google exp 장치인지 여부에 관계없이 boord의 모든 장치에서 작동합니다.
Fred Grott

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.