Как найти серийный номер устройства Android?
Мне нужно использовать уникальный идентификатор для Android-приложения, и я думал, что серийный номер для устройства будет хорошим кандидатом. Как получить серийный номер устройства Android в моем приложении ?
16 ответов:
TelephonyManager tManager = (TelephonyManager)myActivity.getSystemService(Context.TELEPHONY_SERVICE); String uid = tManager.getDeviceId();
getSystemService-это метод из класса Activity. getDeviceID () возвращает MDN или MEID устройства в зависимости от того, какое радио использует телефон (GSM или CDMA).
каждое устройство должно возвращать уникальное значение здесь (предполагая, что это телефон). Это должно работать для любого устройства Android с SIM-слотом или CDMA-радио. Вы сами по себе с этой микроволновой печью на Android; -)
Как упоминает Дэйв Уэбб, в блоге разработчика Android есть статья что это покрывает.
Я говорил с кем-то в Google, чтобы получить некоторые дополнительные разъяснения относительно нескольких пунктов. Вот что я обнаружил, что не упоминается в вышеупомянутом блоге:
- ANDROID_ID является предпочтительным решением. ANDROID_ID идеально надежен на версиях Android =2.3. Только 2.2 имеет проблемы, упомянутые в должность.
- несколько устройств от нескольких производителей страдают от ошибки ANDROID_ID в 2.2.
- насколько я смог определить, все уязвимые устройства тот же ANDROID_ID, которая составляет 9774d56d682e549c. Который также является тем же идентификатором устройства, сообщенным эмулятором, кстати.
- Google считает, что производители исправили проблему для многих или большинства своих устройств, но я смог проверить, что по состоянию на начало апреля 2011 года, по крайней мере, это все еще довольно легко найти устройства, которые имеют сломанный ANDROID_ID.
основываясь на рекомендациях Google, я реализовал класс, который будет генерировать уникальный UUID для каждого устройства, используя ANDROID_ID в качестве семени, где это уместно, возвращаясь к TelephonyManager.getDeviceId () по мере необходимости, и если это не удается, прибегая к случайно генерируемому уникальному 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; } }
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.
String deviceId = Settings.System.getString(getContentResolver(), Settings.System.ANDROID_ID);
хотя, это не гарантирует, что Android ID будет уникальным идентификатором.
здесь отличный пост в блоге разработчика Android обсуждает это.
он рекомендует не использовать
TelephonyManager.getDeviceId()
поскольку он не работает на устройствах Android, которые не являются телефонами, такими как планшеты, он требуетREAD_PHONE_STATE
разрешение и оно не работает надежно на всех телефонах.вместо этого вы можете использовать один из следующих вариантов:
- Mac-Адрес
- последовательный Номер
- ANDROID_ID
сообщение обсуждает плюсы и минусы каждого, и это стоит прочитать, так что вы можете решить, что было бы лучше для вашего использования.
для простого числа, которое является уникальным для устройства и постоянным для его срока службы (за исключением заводского сброса или взлома), используйте настройки.Безопасный.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);
IMEI хорош, но работает только на устройствах Android с телефоном. Вы также должны рассмотреть возможность поддержки планшетов или других устройств Android, у которых нет телефона.
У вас есть некоторые альтернативы, такие как: Build class members, BT MAC, WLAN MAC или даже лучше - комбинация всех этих.
Я объяснил эти подробности в статье на моем блоге, см.: http://www.pocketmagic.net/?p=1662
С нет ответа здесь упоминается идеальный, отказоустойчивый идентификатор, который является постоянным через системные обновления и существует во всех устройствах (в основном из-за того, что нет отдельного решения от Google), я решил опубликовать метод, который является следующей лучшей вещью, объединив два доступных идентификатора и проверку, чтобы выбрать между ними во время выполнения.
перед кодом, 3 факта:
TelephonyManager.getDeviceId()
(a.k.A.IMEI) не будет работать хорошо или вообще для не-GSM, 3G и LTE и т. д.. устройства, но всегда будет возвращать уникальный идентификатор, когда соответствующее оборудование присутствует, даже если SIM-карта не вставлена или даже когда слот SIM-карты не существует (некоторые OEM-производители сделали это).Начиная С Пряника (Android 2.3)
android.os.Build.SERIAL
должен существовать на любом устройстве, которое не предоставляет IMEI, т. е. не имеет вышеупомянутого аппаратного обеспечения, в соответствии с политикой Android.из-за того, (2.), по крайней мере один из этих двух уникальных идентификаторов всегда будет присутствовать, серийный можете присутствовать в то же время, что IMEI.
Примечание: Факт (1.) и (2.) есть на основе заявлений Google
решение
с приведенными выше фактами всегда можно иметь уникальный идентификатор, проверяя, есть ли аппаратное обеспечение с привязкой к IMEI, и вернуться к последовательному, когда это не так, поскольку нельзя проверить, есть ли существующий серийный номер действителен. Следующий статический класс представляет 2 метода для проверки такого присутствия и использования 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 (несколько устройств с одним и тем же серийным номером), и Google, как указано, есть по крайней мере один известный случай в большом OEM (не раскрывается, и я не знаю, какой это бренд, я предполагаю, что Samsung).
отказ от ответственности: это отвечает на первоначальный вопрос о получении уникального идентификатора устройства, но OP ввел двусмысленность, заявив, что ему нужен уникальный идентификатор для приложения. Даже если для таких сценариев Android_ID будет лучше, он не будет работать после, скажем, Титановой резервной копии приложения через 2 различные установки ПЗУ (может быть даже один и тот же ПЗУ). Мое решение поддерживает постоянство, которое не зависит от вспышки или заводского сброса, и будет терпеть неудачу только тогда, когда IMEI или последовательное вмешательство происходит через хаки/аппаратные моды.
есть проблемы со всеми вышеперечисленными подходами. В Google i / o Reto Meier выпустил надежный ответ на то, как подойти к этому, который должен удовлетворить большинство разработчиков, чтобы отслеживать пользователей в разных установках.
этот подход даст вам анонимный, безопасный идентификатор пользователя, который будет сохраняться для пользователя на разных устройствах (включая планшеты, основанные на основной учетной записи Google) и через установку на одном устройстве. Основной подход заключается в создании случайного идентификатора пользователя и хранить это в общих настройках приложений. Затем вы используете агент резервного копирования Google для хранения общих настроек, связанных с учетной записью Google в облаке.
давайте пройдем через полный подход. Сначала нам нужно создать резервную копию для наших SharedPreferences с помощью службы резервного копирования Android. Начните с регистрации вашего приложения по этой ссылке: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);
наконец, создайте идентификатор пользователя, если он еще не существует, и сохраните его в 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 теперь будет сохраняться во всех установках, даже если пользователь переключает устройства.
для получения дополнительной информации об этом подходе см. разговор Рето здесь 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 Я в частности рекомендуем раздел внизу при тестировании, так как резервное копирование не происходит мгновенно и поэтому для тестирования вам нужно принудительно создать резервную копию.
другой способ-использовать /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
- Toshiba AT300
- HTC One V
- Mini MK802
- Samsung Galaxy S II
вы также можете увидеть мой пост в блоге здесь:http://insitusec.blogspot.com/2013/01/leaking-android-hardware-serial-number.html где я обсуждаю, какие другие файлы доступны для информации.
уникальный идентификатор устройства Android OS устройства в виде строки.
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); }
но я strngly рекомендую этот метод, предложенный Google::
Как говорит @haserman:
TelephonyManager tManager = (TelephonyManager)myActivity.getSystemService(Context.TELEPHONY_SERVICE); String uid = tManager.getDeviceId();
но это необходимо, включая разрешение в файле манифеста:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Я знаю, что этот вопрос старый, но это можно сделать в одной строке кода
String deviceID = Build.SERIAL;
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; }
Я нашел пример класса, опубликованный @emmby выше, чтобы быть отличной отправной точкой. Но у него есть пара недостатков, о которых упоминают другие плакаты. Главным из них является то, что он сохраняет UUID в XML-файл без необходимости и после этого всегда извлекает его из этого файла. Это открывает класс для легкого взлома: любой человек с корневым телефоном может редактировать XML-файл, чтобы дать себе новый UUID.
я обновил код так, что он сохраняется только в XML, если это абсолютно необходимо (т. е. при использовании случайно сгенерированного UUID) и пересчитал логику в соответствии с ответом @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; }
да. Это серийный номер аппаратного обеспечения устройства, и он уникален. Так что на уровне API 2.3 и выше вы можете использовать android.ОС.Строить.ANDROID_ID, чтобы получить его. Для уровня API ниже 2.3 используйте TelephonyManager.getDeviceID().
вы можете прочитать это http://android-developers.blogspot.in/2011/03/identifying-app-installations.html