티스토리 뷰

안드로이드 개발을 진행하다 보면 각 단말기의 고유값이 필요한 경우가 많습니다.회원가입이 필수인 앱이 경우에는 회원아이디로 타 사용자와 구분하여 비지니스 로직을 처리 하면 되지만, 회원가입 없이도 이용이 가능한 앱인 경우 다른 사용자와 구분할수 있는 값이 필요하게 됩니다. 이번 포스팅에서는 이럴때 유용하게 사용되는 단말기 고유값에 대해서 설명 할려고 합니다.



.1.TelephonyManager를 이용한 DeviceId가져와 사용하는 방법


핸드폰 번호를 갖고 있지 않는 태블릿 이나 Wifi 만을 제공 하는 디바이스는 TelephonyManager 를 통한 디바이스 번호를 획득 하지 못 할 수도 있습니다. 한번 생성된 번호에 대한 지속 여부를 보장 할 수 가 없습니다. 디바이스가 공장 초기화 될 경우 다른값으로 변경 됩니다. 뿐만 아니라, 현재 까지 몇몇 버그들이 report 되어 있습니다. 안드로이드 디바이스는 제조사 마다 다양하게 커스터마이징 가능 하기 때문에 000000000000000 같이 의미 없는 값이나 null 이 반환 될수도 있습니다.


1
2
TelephonyManager mgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
 String idByTelephonyManager = mgr.getDeviceId();
cs



.2.ANDROID_ID를 사용하는 방법


가장 명확한 방법이며, 디바이스가 최초 Boot 될때 생성 되는 64-bit 값입니다. 하지만 ANDROID_ID 또한 단점이 있는데, Proyo 2.2 이전 Version 에는 100% 디바이스 고유 번호를 획득 한다고는 보장 할 수 없으며, 몇몇 Vendor 에서 출하된 디바이스에 동일한 고유 번호(ex."9774d56d682e549c")가 획득 됩니다.


1
String idByANDROID_ID = Settings.Secure.getString(mContext.getContentResolver(), Settings.Secure.ANDROID_ID);
cs



.3.Serial Number를 사용하는 방법


안드로이드의 API Level 9 (진저브레드 2.3) 이후 부터 제공 하는 고유 번호 로서 TelephonyManager 클래스를 통한 획득 보다는 안전 하다고 할 수 있지만 2.3 미만의 Version 에서는 문제가 발생 할 수 가 있는 문제가 있습니다. 거의 사용하지 않는 방법입니다.


1
2
3
4
5
 try {
       String idBySerialNumber = (String) Build.class.getField("SERIAL").get(null);
     } catch (Exception e) {
         e.printStackTrace();;
     }
cs



각각 방법은 장점과 단점이 존재 합니다. 어떤것이 무조건 맞다고 볼수 없으며, 틀리다고 볼수도 없습니다. 해외사이트에서 알려져 있는 고유값을 가지고 처리되는 소스를 공유해 드립니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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();
                    }
                }
            }
        }
    }
 
    public UUID getDeviceUuid() {
        return uuid;
    }
}
cs


위 소스를 간단히 살펴보면 고유값(UUID)을 가지고 오기 위해 우선 preferences에 저장된 UUID를 확인 한 후에 저장된 UUID가 없으면,제일 정확하다고 알려진 ANDROID_ID를 가져와 동일한 버그 고유값(9774d56d682e549c)이 아니면 UUID에 저장하고 버그값이 맞다면 ANDROID_ID를 사용 하지 않고 TelephonyManager를 이용한 DeviceId를가져옵니다. 가지고 온 DeviceId도 NULL인 경우에 랜덤으로 UUID를 생성하여 preferences에 저장하여 사용 하고 있습니다.

물론 위 방법도 100% UUID는 아니지만 현재 사용할수 있는 방법중에서 가장 100%에 근접한 접급 방식인것 같습니다.



댓글