Làm cách nào để tìm số sê-ri của thiết bị Android?


115

Tôi cần sử dụng ID duy nhất cho ứng dụng Android và tôi nghĩ số sê-ri cho thiết bị sẽ là một ứng cử viên sáng giá. Làm cách nào để truy xuất số sê-ri của thiết bị Android trong ứng dụng của tôi?


2
Đừng quên thêm android: name = "
ERIC.READ_PHONE_STATE


Nếu bạn muốn nhận một ID duy nhất mà không có bất kỳ quyền nào, bạn có thể sử dụng thư viện này để tạo một ID duy nhất cho mỗi thiết bị với Identity.getDeviceId (bối cảnh) hoặc một mã định danh cho cài đặt ứng dụng của bạn thông qua Identity.getInstallationId (bối cảnh) .
caw

Câu trả lời:


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

getSystemService là một phương thức từ lớp Activity. getDeviceID () sẽ trả về MDN hoặc MEID của thiết bị tùy thuộc vào loại điện thoại mà điện thoại sử dụng (GSM hoặc CDMA).

Mỗi thiết bị PHẢI trả về một giá trị duy nhất tại đây (giả sử đó là điện thoại). Điều này sẽ hoạt động cho mọi thiết bị Android có khe cắm sim hoặc radio CDMA. Bạn đang ở một mình với lò vi sóng chạy Android đó ;-)


@Hasemam Điều này không hiệu quả với tôi, gây ra lỗi "Buộc đóng"
Paresh Mayani

23
@Hasemam hiện đang chạy tốt sau khi thêm quyền <used-allow android: name = "ERIC.READ_PHONE_STATE"> </ used-allow> trong tệp androidManifest.xml.
Paresh Mayani

23
Có một số lời khuyên trên blog Android phát triển chính thức về việc sử dụng định danh này: android-developers.blogspot.com/2011/03/...
David Snabel-Caunt

8
ngoài lò vi sóng chạy Android, còn máy tính bảng chạy Android thì sao? :)
ajacian81

21
Phương pháp này nên tránh, phương pháp này sẽ hoạt động trên điện thoại nhưng sẽ không hoạt động trên các thiết bị không có chip điện thoại (máy tính bảng là một ví dụ). Từ 2.3 bạn có thể sử dụng android.os.Build.SERIAL nhưng hãy xem blog nhà phát triển mà @DavidCaunt đề xuất.
John Mitchell

71

Như Dave Webb đã đề cập, Blog Nhà phát triển Android có một bài viết đề cập đến vấn đề này.

Tôi đã nói chuyện với ai đó tại Google để có thêm một số giải thích rõ ràng về một vài mặt hàng. Đây là những gì tôi phát hiện ra rằng KHÔNG được đề cập trong bài viết trên blog đã nói ở trên:

  • ANDROID_ID là giải pháp ưu tiên. ANDROID_ID hoàn toàn đáng tin cậy trên các phiên bản Android <= 2.1 hoặc> = 2.3. Chỉ có 2.2 có vấn đề được đề cập trong bài.
  • Một số thiết bị của một số nhà sản xuất bị ảnh hưởng bởi lỗi ANDROID_ID trong 2.2.
  • Theo như tôi đã có thể xác định, tất cả các thiết bị bị ảnh hưởng đều có cùng ANDROID_ID , đó là 9774d56d682e549c . Đó cũng là id thiết bị tương tự được báo cáo bởi trình giả lập, btw.
  • Google tin rằng các OEM đã khắc phục sự cố cho nhiều hoặc hầu hết các thiết bị của họ, nhưng tôi đã có thể xác minh rằng kể từ đầu tháng 4 năm 2011, ít nhất, vẫn dễ dàng tìm thấy các thiết bị bị hỏng ANDROID_ID.

Dựa trên các đề xuất của Google, tôi đã triển khai một lớp sẽ tạo ra một UUID duy nhất cho mỗi thiết bị, sử dụng ANDROID_ID làm hạt giống khi thích hợp, quay lại TelephonyManager.getDeviceId () nếu cần, và nếu không, hãy sử dụng UUID duy nhất được tạo ngẫu nhiên được duy trì trên toàn bộ ứng dụng khởi động lại (nhưng không cài đặt lại ứng dụng).

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
Những quyền nào được yêu cầu cho một ứng dụng để sử dụng điều này?
Dave L.

1
<used-allow android: name = "ERIC.READ_PHONE_STATE"> </ used-allow>
Gabrielle

1
@ ef2011 đó là mẫu khóa được kiểm tra hai lần: en.wikipedia.org/wiki/Double-checked_locking
emmby

3
Cảm ơn vì đăng. Nhưng điều gì để ngăn người nào đó có điện thoại đã root không cần chỉnh sửa device_id.xml để đặt UUID mới theo lựa chọn của họ? (tức là phá vỡ kiểm tra 'dùng thử miễn phí') Sẽ không tốt hơn nếu lớp chỉ lưu trữ giá trị trong tệp ưu tiên nếu nó phải dùng đến phương thức ID ngẫu nhiên? Mặt khác, không cần phải duy trì nó giữa các lần chạy ứng dụng; nó an toàn hơn để tạo lại.
Carlos P

1
"ANDROID_ID" là giải pháp ưu tiên ". Lưu ý rằng ANDROID_ID không còn nhận dạng duy nhất một thiết bị: 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) {
}

Mã này trả về số sê-ri thiết bị bằng API Android ẩn.


7
điều này chỉ mang lại cho tôi giá trị tương đương với giá trị tôi nhận được với android.os.Build.SERIAL
josephus

Tôi có nhầm không, hay số sê-ri này giống nhau trong tất cả các thiết bị có rom tùy chỉnh cụ thể? Số sê-ri thiết bị của tôi (trong trình khởi chạy thiết bị nhật thực) hiển thị 01234567890ABC cho điện thoại có rom tùy chỉnh.
Peterdk

@Peterdk trên thiết bị của tôi với cyanogen-9 cả hai phương pháp (trước andy-9 như trong câu trả lời và dễ dàng hơn từ andy-9 on) báo cáo s / n chính xác (giống như trên nhãn dán của nhà sản xuất). Nó có thể phụ thuộc vào phiên bản rom tùy chỉnh cụ thể, mặc dù. Bạn đang sử dụng bản rom / phiên bản nào?
morgwai

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

Mặc dù, không đảm bảo rằng Android ID sẽ là một định danh duy nhất.


@Paresh Mayani, thật khó để nói điều gì có thể là vấn đề mà không cần nhìn vào mã. Giả định duy nhất của tôi getContentResolverlà trở về null. Tuy nhiên, nó có thể có giá trị trong khi mở một câu hỏi và đăng mã của bạn.
Anthony Forloney

4
ID này xuất phát từ tài khoản Google được liên kết với điện thoại. Trình mô phỏng thường không có. Một chiếc điện thoại thực sự cũng có thể không có. Ngoài ra, nó được ghi là "có thể thay đổi khi khôi phục cài đặt gốc" và có thể thay đổi tùy ý bất cứ lúc nào trên điện thoại đã root. Sử dụng có nguy cơ của riêng bạn. Không có lựa chọn nào tốt - các ID thiết bị dự kiến ​​khác không có sẵn trên toàn cầu hoặc không phải là duy nhất hoặc cả hai. Xem câu trả lời khác cho phần còn lại của câu chuyện buồn này.
Seva Alekseyev

14

một bài viết tuyệt vời trên Blog của Nhà phát triển Android thảo luận về điều này .

Nó khuyên bạn không nên sử dụng TelephonyManager.getDeviceId()vì nó không hoạt động trên các thiết bị Android không phải là điện thoại như máy tính bảng, nó cần có sự READ_PHONE_STATEcho phép và nó không hoạt động đáng tin cậy trên tất cả các điện thoại.

Thay vào đó, bạn có thể sử dụng một trong những điều sau đây:

  • Địa chỉ MAC
  • Số sê-ri
  • ANDROID_ID

Bài viết thảo luận về ưu và nhược điểm của từng loại và nó đáng để đọc để bạn có thể tìm ra cái nào là tốt nhất cho việc sử dụng của bạn.


+1, xin chào, thanx để làm rõ vì hiện tại tôi đang phát triển một ứng dụng cho máy tính bảng, nơi tôi cần có ID duy nhất của thiết bị Android, vậy tôi nên sử dụng gì để có được thiết bị máy tính bảng Android độc đáo?
Paresh Mayani

12

Đối với một số đơn giản là duy nhất cho thiết bị và không đổi trong suốt vòng đời của thiết bị (chặn cài đặt gốc hoặc hack), hãy sử dụng Settings.Secure.ANDROID_ID .

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

Để sử dụng số sê-ri của thiết bị (số được hiển thị trong "Cài đặt hệ thống / Giới thiệu / Trạng thái") nếu có và quay lại ID Android:

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

câu trả lời thẳng thắn !!
faris faris

Build.SERftimeAL không dùng nữa trong java
Eyyüp Alkış

7

IMEI tốt nhưng chỉ hoạt động trên thiết bị Android có điện thoại. Bạn cũng nên xem xét hỗ trợ cho Máy tính bảng hoặc các thiết bị Android khác, không có điện thoại.

Bạn có một số lựa chọn thay thế như: Xây dựng thành viên lớp, BT MAC, WLAN MAC hoặc thậm chí tốt hơn - kết hợp tất cả những thứ này.

Tôi đã giải thích những chi tiết này trong một bài viết trên blog của mình, xem: http://www.pocketmagic.net/?p=1662


6

không có câu trả lời nào ở đây đề cập đến một ID hoàn hảo, không chứng minh được cả PERSISTENT thông qua các bản cập nhật hệ thống và tồn tại trong TẤT CẢ các thiết bị (chủ yếu là do không có giải pháp riêng lẻ nào từ Google), tôi đã quyết định đăng một phương pháp điều tốt nhất tiếp theo bằng cách kết hợp hai trong số các định danh có sẵn và kiểm tra để chọn giữa chúng trong thời gian chạy.

Trước mã, 3 sự thật:

  1. TelephonyManager.getDeviceId()(akaIMEI) sẽ không hoạt động tốt hoặc hoàn toàn cho các thiết bị không phải GSM, 3G, LTE, v.v., nhưng sẽ luôn trả về một ID duy nhất khi có phần cứng liên quan , ngay cả khi không có SIM nào được lắp hoặc ngay cả khi không có khe cắm SIM ( một số OEM đã làm điều này).

  2. Vì Gingerbread (Android 2.3) android.os.Build.SERIAL phải tồn tại trên bất kỳ thiết bị nào không cung cấp IMEI , tức là, không có phần cứng nói trên, theo chính sách của Android.

  3. Do thực tế (2.), ít nhất một trong hai số nhận dạng duy nhất này LUÔN LUÔN có mặt và SERIAL có thể có mặt cùng lúc với IMEI.

Lưu ý: Fact (1.) và (2.) dựa trên các tuyên bố của Google

GIẢI PHÁP

Với các sự kiện ở trên, người ta luôn có thể có một mã định danh duy nhất bằng cách kiểm tra xem có phần cứng ràng buộc IMEI hay không và quay lại SERIAL khi không, vì người ta không thể kiểm tra xem SERIAL hiện tại có hợp lệ không. Lớp tĩnh sau đây trình bày 2 phương thức để kiểm tra sự hiện diện đó và sử dụng IMEI hoặc 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;
    }


}

Tôi sẽ tư vấn về việc sử dụng getCleartextID_HARDCHECK. Nếu sự phản chiếu không dính vào môi trường của bạn, getCleartextID_SIMCHECKthay vào đó hãy sử dụng phương pháp, nhưng hãy xem xét nó phải phù hợp với nhu cầu hiện diện SIM cụ thể của bạn.

PS : Xin lưu ý rằng các OEM đã tìm cách khắc phục SERIAL chống lại chính sách của Google (nhiều thiết bị có cùng SERIAL) và Google như đã nêu có ít nhất một trường hợp được biết đến trong một OEM lớn (không được tiết lộ và tôi không biết thương hiệu nào đó là một trong hai, tôi đoán Samsung).

Tuyên bố miễn trừ trách nhiệm : Điều này trả lời câu hỏi ban đầu về việc nhận ID thiết bị duy nhất, nhưng OP đã đưa ra sự mơ hồ bằng cách nói rằng anh ta cần một ID duy nhất cho một ứng dụng. Ngay cả khi với các kịch bản như vậy, Android_ID sẽ tốt hơn, nó sẽ KHÔNG LÀM VIỆC sau khi giả sử Titanium Backup của một ứng dụng thông qua 2 lần cài đặt ROM khác nhau (thậm chí có thể là cùng một ROM). Giải pháp của tôi duy trì sự bền bỉ không phụ thuộc vào flash hoặc khôi phục cài đặt gốc và sẽ chỉ thất bại khi xảy ra giả mạo IMEI hoặc SERIAL thông qua hack / mod phần cứng.


5

Có vấn đề với tất cả các phương pháp trên. Tại Google, i / o Reto Meier đã đưa ra một câu trả lời mạnh mẽ về cách tiếp cận vấn đề này sẽ đáp ứng hầu hết các nhu cầu của nhà phát triển để theo dõi người dùng qua các cài đặt.

Cách tiếp cận này sẽ cung cấp cho bạn ID người dùng an toàn, ẩn danh, sẽ tồn tại lâu dài cho người dùng trên các thiết bị khác nhau (bao gồm cả máy tính bảng, dựa trên tài khoản Google chính) và trên các cài đặt trên cùng một thiết bị. Cách tiếp cận cơ bản là tạo ID người dùng ngẫu nhiên và lưu trữ tệp này trong các tùy chọn chia sẻ ứng dụng. Sau đó, bạn sử dụng tác nhân sao lưu của Google để lưu trữ các tùy chọn được chia sẻ được liên kết với tài khoản Google trên đám mây.

Hãy đi qua cách tiếp cận đầy đủ. Trước tiên, chúng tôi cần tạo bản sao lưu cho SharedPreferences bằng Dịch vụ sao lưu Android. Bắt đầu bằng cách đăng ký ứng dụng của bạn thông qua liên kết này: http://developer.android.com/google/backup/signup.html

Google sẽ cung cấp cho bạn khóa dịch vụ sao lưu mà bạn cần thêm vào bảng kê khai. Bạn cũng cần yêu cầu ứng dụng sử dụng BackupAgent như sau:

<application android:label="MyApplication"
         android:backupAgent="MyBackupAgent">
    ...
    <meta-data android:name="com.google.android.backup.api_key"
        android:value="your_backup_service_key" />
</application>

Sau đó, bạn cần tạo tác nhân sao lưu và bảo nó sử dụng tác nhân trợ giúp cho các cuộc họp chung:

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

Để hoàn thành bản sao lưu, bạn cần tạo một phiên bản của BackupManager trong Hoạt động chính của mình:

BackupManager backupManager = new BackupManager(context);

Cuối cùng tạo ID người dùng, nếu nó chưa tồn tại và lưu nó trong 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 này bây giờ sẽ liên tục trong các cài đặt, ngay cả khi người dùng chuyển đổi thiết bị.

Để biết thêm thông tin về cách tiếp cận này, hãy xem Reto nói chuyện tại đây http://www.google.com/events/io/2011/simes/android-protips-advified-topics-for-expert-android-app-developers.html

Và để biết chi tiết đầy đủ về cách triển khai tác nhân sao lưu, hãy xem trang web của nhà phát triển tại đây: http://developer.android.com/guide/topics/data/backup.html Tôi đặc biệt khuyên bạn nên kiểm tra phần dưới cùng để kiểm tra vì sao lưu không xảy ra tức thời và vì vậy để kiểm tra bạn phải buộc sao lưu.


2

Một cách khác là sử dụng / sys / class / android_usb / android0 / iSerial trong một Ứng dụng không có quyền gì.

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

Để làm điều này trong java, người ta chỉ cần sử dụng FileInputStream để mở tệp iSerial và đọc các ký tự. Chỉ cần chắc chắn rằng bạn bọc nó trong một trình xử lý ngoại lệ vì không phải tất cả các thiết bị đều có tệp này.

Ít nhất các thiết bị sau đây được biết là có tệp này có thể đọc được trên thế giới:

  • Galaxy Nexus
  • Nexus S
  • Motorola Xoom 3g
  • Toshiba AT300
  • HTC One V
  • MK MK Mini
  • Samsung Galaxy S II

Bạn cũng có thể xem bài đăng trên blog của tôi ở đây: http://insitusec.blogspot.com/2013/01/leaking-android-hardware-serial-number.html nơi tôi thảo luận về những tệp khác có sẵn để biết thông tin.


Cảm ơn đã gửi câu trả lời của bạn! Hãy chắc chắn đọc Câu hỏi thường gặp về Tự quảng cáo một cách cẩn thận. Cũng lưu ý rằng nó là cần thiết mà bạn gửi một từ chối trách nhiệm mỗi khi bạn liên kết đến trang web / sản phẩm của riêng bạn.
Andrew Barber

1

Như @haserman nói:

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

Nhưng nó cần thiết bao gồm sự cho phép trong tệp kê khai:

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

1

ID thiết bị duy nhất của Thiết bị HĐH Android dưới dạng Chuỗi.

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

nhưng tôi thực sự khuyên dùng phương pháp này được đề xuất bởi Google ::

Xác định cài đặt ứng dụng


1

Build.SERIALlà cách đơn giản nhất để đi, mặc dù không hoàn toàn đáng tin cậy vì nó có thể trống hoặc đôi khi trả về một giá trị khác ( bằng chứng 1 , bằng chứng 2 ) so với những gì bạn có thể thấy trong cài đặt của thiết bị.

Có một số cách để có được số đó tùy thuộc vào nhà sản xuất thiết bị và phiên bản Android, vì vậy tôi quyết định biên dịch mọi giải pháp có thể tôi có thể tìm thấy trong một ý chính . Đây là phiên bản đơn giản hóa của nó:

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

Tôi biết câu hỏi này đã cũ nhưng nó có thể được thực hiện trong một dòng mã

String deviceID = Build.SERIAL;


AFAIK, điều này sẽ thay đổi sau khi cập nhật hệ điều hành của thiết bị, ví dụ từ 4.4.2 đến 4.4.4 hoặc bất cứ điều gì.
Den Drobiazko

-1

Tôi thấy lớp ví dụ được đăng bởi @emmby ở trên là một điểm khởi đầu tuyệt vời. Nhưng nó có một vài sai sót, như được đề cập bởi các áp phích khác. Cái chính là nó duy trì UUID thành một tệp XML một cách không cần thiết và sau đó luôn lấy nó từ tệp này. Điều này đặt lớp mở cho một hack dễ dàng: bất kỳ ai có điện thoại đã root đều có thể chỉnh sửa tệp XML để tạo cho mình một UUID mới.

Tôi đã cập nhật mã để nó chỉ tồn tại thành XML nếu thực sự cần thiết (nghĩa là khi sử dụng UUID được tạo ngẫu nhiên) và xác nhận lại logic theo câu trả lời của @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;
    }

Việc đưa id vào các prefs được chia sẻ sẽ thỏa hiệp với mục đích ban đầu để có được id thực sự độc đáo. Ví dụ: nếu bạn muốn sử dụng id đó làm khóa cho một số hạn chế thì bạn sẽ bị lừa khi người dùng có kỹ năng root thiết bị và có quyền truy cập vào tệp tùy chọn chia sẻ của bạn. Nội dung của nó có thể được sao chép có nghĩa là ...
Eugene Wechsler

Ngoài ra còn có một lỗi khác đối với câu trả lời của MB và của bạn..Nếu bạn sử dụng RandomUUID làm thiết bịID và appID, nó hoạt động cho tất cả các thiết bị trên boord cho dù chúng có phải là điện thoại hay không hoặc chúng có phải là thiết bị của google exp hay không.
Fred Grott

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.