Я думаю, вы можете использовать параметр nrows
. Из docs :
nrows : int, default None
Number of rows of file to read. Useful for reading pieces of large files
, который, похоже, работает. Используя один из стандартных больших тестовых файлов (988504479 байт, 5344499 строк):
In [1]: import pandas as pd
In [2]: time z = pd.read_csv("P00000001-ALL.csv", nrows=20)
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.00 s
In [3]: len(z)
Out[3]: 20
In [4]: time z = pd.read_csv("P00000001-ALL.csv")
CPU times: user 27.63 s, sys: 1.92 s, total: 29.55 s
Wall time: 30.23 s
Settings.Secure#ANDROID_ID
возвращает идентификатор Android в качестве , уникального для каждого пользователя 64-битной шестнадцатеричной строки.
import android.provider.Settings.Secure;
private String android_id = Secure.getString(getContext().getContentResolver(),
Secure.ANDROID_ID);
ОБНОВЛЕНИЕ: по последним версиям Android многие проблемы с ANDROID_ID
были решены, и я считаю, что этот подход больше не нужен. Пожалуйста, взгляните на ответ Антони .
Полное раскрытие: мое приложение первоначально использовало подход ниже, но больше не использует этот подход, и теперь мы используем подход, описанный в [], который emmby ответил на ссылки (а именно, создание и сохранение UUID#randomUUID()
).
На этот вопрос много ответов, большинство из которых будут работать только «некоторые» времени, и, к сожалению, это недостаточно.
Основываясь на моих тестах устройств (все телефоны, по крайней мере один из которых не активирован):
TelephonyManager.getDeviceId()
TelephonyManager.getSimSerialNumber()
getSimSerialNumber()
(как ожидалось) ANDROID_ID
ANDROID_ID
, так и TelephonyManager.getDeviceId()
- , пока добавлена учетная запись Google во время настройки. Итак, если вам нужно что-то уникальное для самого устройства, TM.getDeviceId()
должно быть достаточным. Очевидно, что некоторые пользователи более параноики, чем другие, поэтому было бы полезно хешировать один или несколько из этих идентификаторов, так что строка по-прежнему практически уникальна для устройства, но явно не идентифицирует фактическое устройство пользователя. Например, использование String.hashCode()
в сочетании с UUID:
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
Он работает достаточно хорошо для меня.
Как упоминает Ричард ниже, не забывайте, что вам нужно разрешение читать свойства TelephonyManager
, поэтому добавьте это в свой манифест:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
import libs
import android.content.Context;
import android.telephony.TelephonyManager;
import android.view.View;
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
в файл манифеста. При сохранении в базе данных возвращаемая строка имеет длину 36 символов.
– Richard
27 February 2011 в 23:28
В частности, Settings.Secure.ANDROID_ID
. Это 64-разрядное количество, которое генерируется и сохраняется при первом загрузке устройства. Он сбрасывается при стирании устройства.
ANDROID_ID
кажется хорошим выбором для уникального идентификатора устройства. Есть недостатки: во-первых, он не на 100% надежен в выпусках Android до 2.2 (“Froyo”).
. Кроме того, в популярном мобильном телефоне был обнаружен хотя бы один широко распространенный телефон от крупного производителя, где каждый экземпляр имеет тот же ANDROID_ID .
Добавить код ниже в файле класса:
final TelephonyManager tm = (TelephonyManager) getBaseContext()
.getSystemService(SplashActivity.TELEPHONY_SERVICE);
final String tmDevice, tmSerial, androidId;
tmDevice = "" + tm.getDeviceId();
Log.v("DeviceIMEI", "" + tmDevice);
tmSerial = "" + tm.getSimSerialNumber();
Log.v("GSM devices Serial Number[simcard] ", "" + tmSerial);
androidId = "" + android.provider.Settings.Secure.getString(getContentResolver(),
android.provider.Settings.Secure.ANDROID_ID);
Log.v("androidId CDMA devices", "" + androidId);
UUID deviceUuid = new UUID(androidId.hashCode(),
((long) tmDevice.hashCode() << 32) | tmSerial.hashCode());
String deviceId = deviceUuid.toString();
Log.v("deviceIdUUID universally unique identifier", "" + deviceId);
String deviceModelName = android.os.Build.MODEL;
Log.v("Model Name", "" + deviceModelName);
String deviceUSER = android.os.Build.USER;
Log.v("Name USER", "" + deviceUSER);
String devicePRODUCT = android.os.Build.PRODUCT;
Log.v("PRODUCT", "" + devicePRODUCT);
String deviceHARDWARE = android.os.Build.HARDWARE;
Log.v("HARDWARE", "" + deviceHARDWARE);
String deviceBRAND = android.os.Build.BRAND;
Log.v("BRAND", "" + deviceBRAND);
String myVersion = android.os.Build.VERSION.RELEASE;
Log.v("VERSION.RELEASE", "" + myVersion);
int sdkVersion = android.os.Build.VERSION.SDK_INT;
Log.v("VERSION.SDK_INT", "" + sdkVersion);
Добавить в AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Идентификатор MAC-устройства Android также является уникальным идентификатором, он не изменится, если мы отформатируем само устройство, поэтому используя следующий код, чтобы получить mac id
WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = manager.getConnectionInfo();
String address = info.getMacAddress();
Также не забудьте добавить соответствующие разрешения в ваш AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
Идентификатор экземпляра Google
Выпущен на I / O 2015; на Android требуется игровые сервисы 7.5.
https://developers.google.com/instance-id/ https://developers.google.com/instance- id / guide / android-implementation
InstanceID iid = InstanceID.getInstance( context ); // Google docs are wrong - this requires context
String id = iid.getId(); // blocking call
Кажется, Google намерен использовать этот идентификатор для идентификации установок на Android, Chrome и iOS.
Он идентифицирует установку, а не устройство, но опять же, ANDROID_ID (который является принятым ответом) теперь больше не идентифицирует устройства. С помощью среды ARC для каждой установки создается новый ANDROID_ID (подробности здесь ), как и этот новый идентификатор экземпляра.
Преимущества идентификатора экземпляра
Мне кажется, что Google намерен для этого (с указанием ваших установок), он является кросс-платформенным и может использоваться для ряда других целей (см. ссылки выше).
Если вы используете GCM, то в конечном итоге вы необходимо использовать этот идентификатор экземпляра, потому что вам нужно его, чтобы получить токен GCM (который заменяет старый идентификатор регистрации GCM).
Недостатки / проблемы
В текущей реализации ( GPS 7.5) идентификатор экземпляра извлекается с сервера, когда ваше приложение запрашивает его. Это означает, что вызов выше - это блокирующий вызов - в моем ненаучном тестировании он занимает 1-3 секунды, если устройство находится в сети, и 0,5-1,0 секунды, если он отключен (предположительно, это то, как долго он ждет, прежде чем отказаться от случайный идентификатор). Это было протестировано в Северной Америке на Nexus 5 с Android 5.1.1 и GPS 7.5.
Если вы используете идентификатор для своих целей - например. аутентификация приложения, идентификация приложения, GCM - я думаю, что это 1-3 секунды может быть неприятным (в зависимости от вашего приложения, конечно).
Как отмечает Дейв Вебб, в блоге разработчиков Android есть статья , которая охватывает это. Их предпочтительным решением является отслеживание приложений, а не устройств, и это будет хорошо работать для большинства случаев использования. Сообщение в блоге покажет вам необходимый код, чтобы сделать эту работу, и я рекомендую вам проверить его.
Однако в блоге идет обсуждение решений, если вам нужен идентификатор устройства, а не установка приложения идентификатор. Я поговорил с кем-то в Google, чтобы получить некоторые дополнительные разъяснения по нескольким пунктам в случае, если вам нужно это сделать. Вот что я узнал об идентификаторах устройств, которые НЕ упоминаются в вышеупомянутом сообщении в блоге:
Основываясь на рекомендациях Google, я внедрил класс, который будет генерировать уникальный UUID для каждого устройства, используя ANDROID_ID в качестве семени, где это необходимо, при необходимости возвращаться к TelephonyManager.getDeviceId (), и если это не удается, прибегая к произвольно сгенерированному уникальному UUID, который сохраняется в перезагрузке приложений (но не при повторной установке приложения).
Обратите внимание, что для устройств, которые должны отступать от идентификатора устройства, уникальный идентификатор WILL сохраняется на заводских сбрасываниях. Это то, о чем нужно знать. Если вам нужно убедиться, что сброс на заводе сбросит ваш уникальный идентификатор, вы можете захотеть вернуться обратно к случайному 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 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;
}
}
Как насчет IMEI . Это уникально для Android или других мобильных устройств.
Вот как я генерирую уникальный id:
public static String getDeviceId(Context ctx)
{
TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
String tmDevice = tm.getDeviceId();
String androidId = Secure.getString(ctx.getContentResolver(), Secure.ANDROID_ID);
String serial = null;
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) serial = Build.SERIAL;
if(tmDevice != null) return "01" + tmDevice;
if(androidId != null) return "02" + androidId;
if(serial != null) return "03" + serial;
// other alternatives (i.e. Wi-Fi MAC, Bluetooth MAC, etc.)
return null;
}
Также вы можете рассмотреть MAC-адрес адаптера Wi-Fi. Получено так:
WifiManager wm = (WifiManager)Ctxt.getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getMacAddress();
Требуется разрешение android.permission.ACCESS_WIFI_STATE
в манифесте.
Сообщается, что он доступен, даже если Wi-Fi не подключен. Если Джо из приведенного выше ответа дает этому возможность попробовать свои многочисленные устройства, это было бы хорошо.
На некоторых устройствах он недоступен, когда Wi-Fi отключен.
ПРИМЕЧАНИЕ. Начиная с Android 6.x, он возвращает согласованный поддельный MAC-адрес: 02:00:00:00:00:00
В Google теперь есть рекламный ID . Это также можно использовать, но обратите внимание, что:
Идентификатор рекламы является уникальным, уникальным, сбрасываемым идентификатором пользователя
blockquote>и
< blockquote>позволяет пользователям сбросить свой идентификатор или отказаться от рекламы на основе интересов в приложениях Google Play.
blockquote>Итак, хотя этот идентификатор может измениться, кажется, что вскоре мы может не иметь выбора , зависит от цели этого идентификатора.
Дополнительная информация @ develper.android
HTH
TelephonyManger.getDeviceId () Возвращает уникальный идентификатор устройства, например IMEI для GSM и MEID или ESN для телефонов CDMA.
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String myAndroidDeviceId = mTelephony.getDeviceId();
Но я рекомендую использовать:
Settings.Secure.ANDROID_ID, который возвращает идентификатор Android в качестве уникальной 64-разрядной шестнадцатеричной строки.
String myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
Иногда TelephonyManger.getDeviceId () возвращает null, поэтому для обеспечения уникального идентификатора вы будете используйте этот метод:
public String getUniqueID(){
String myAndroidDeviceId = "";
TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephony.getDeviceId() != null){
myAndroidDeviceId = mTelephony.getDeviceId();
}else{
myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
}
return myAndroidDeviceId;
}
Я думаю, что это верный способ создания скелета для уникального идентификатора ... проверьте его.
Псевдо-уникальный идентификатор, который работает на всех устройствах Android. Некоторые устройства не имеют телефона (например, планшеты) или по какой-либо причине вы не хотите включать разрешение READ_PHONE_STATE. Вы все еще можете читать такие данные, как ПЗУ, имя производителя, тип ЦП и другие детали оборудования, которые будут хорошо подходить, если вы хотите использовать идентификатор для проверки серийного ключа или других общих целей. Идентификатор, вычисленный таким образом, не будет уникальным: можно найти два устройства с одинаковым ID (на основе одного и того же аппаратного и ROM-изображения), но изменения в реальных приложениях незначительны. Для этого вы можете использовать класс Build:
String m_szDevIDShort = "35" + //we make this look like a valid IMEI
Build.BOARD.length()%10+ Build.BRAND.length()%10 +
Build.CPU_ABI.length()%10 + Build.DEVICE.length()%10 +
Build.DISPLAY.length()%10 + Build.HOST.length()%10 +
Build.ID.length()%10 + Build.MANUFACTURER.length()%10 +
Build.MODEL.length()%10 + Build.PRODUCT.length()%10 +
Build.TAGS.length()%10 + Build.TYPE.length()%10 +
Build.USER.length()%10 ; //13 digits
. Большинство членов Build - это строки, то, что мы делаем здесь, - это взять их длину и преобразовать их по модулю в цифре. У нас есть 13 таких цифр, и мы добавляем еще два передних (35), чтобы иметь тот же ID размера, что и IMEI (15 цифр). Здесь есть и другие возможности, просто взгляните на эти строки. Возвращает что-то вроде 355715565309247
.
(Дополнительная информация: приведенная выше техника была скопирована из статьи на Pocket Magic .)
]Для аппаратного распознавания определенного Android-устройства вы можете проверить MAC-адреса.
вы можете сделать это следующим образом:
в AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
теперь в вашем коде:
List<NetworkInterface> interfacesList = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface interface : interfacesList) {
// This will give you the interface MAC ADDRESS
interface.getHardwareAddress();
}
В каждом устройстве Android их, по крайней мере, «wlan0» интерфейс - это чип WI-FI. Этот код работает даже тогда, когда WI-FI не включен.
P.S. Они представляют собой группу других интерфейсов, которые вы получите из списка, содержащего MACS. Но это может измениться между телефонами.
Другим способом является использование /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 и зачитать символы , Просто убедитесь, что вы завернули его в обработчик исключений, потому что не все устройства имеют этот файл.
Известно, что, по крайней мере, следующие устройства читают этот мир:
Вы также можете увидеть мой пост в блоге Утечка серийного номера аппаратного обеспечения Android в непривилегированные приложения , где я обсуждаю, какие другие файлы доступны для информации.
ro.serialno
используется для генерации Settings.Secure.ANDROID_ID
. Таким образом, они представляют собой в основном разные представления одинакового значения.
– Martin
23 June 2011 в 07:31
ANDROID_ID
.
– Ronnie
17 September 2011 в 09:28
android.os.Build.SERIAL
будет устаревшим в Android O, см. android-developers.googleblog.com/2017/04/…
– EpicPandaForce
12 April 2017 в 08:28
Здесь довольно полезная информация здесь .
Она охватывает пять разных типов идентификаторов:
android.permission.READ_PHONE_STATE
) android.permission.ACCESS_WIFI_STATE
) android.permission.BLUETOOTH
) Одна вещь, которую я добавлю: у меня есть одна из этих уникальных ситуаций.
Использование:
deviceId = Secure.getString(this.getContext().getContentResolver(), Secure.ANDROID_ID);
Оказывается, хотя мой планшет Viewsonic G сообщает DeviceID, что не является нулевым, каждый отдельный G Tablet сообщает о том же номере.
Делает интересным воспроизведение «Pocket Empires», которое дает вам мгновенный доступ к чьей-либо учетной записи на основе «уникального» DeviceID.
На моем устройстве нет сотовой радиостанции.
Здесь есть 30 ответов, а некоторые - одни и те же, и некоторые из них уникальны. Этот ответ основан на нескольких ответах. Один из них - ответ @Lenn Dolling.
Он объединяет 3 идентификатора и создает 32-значную шестую строку. Он работал очень хорошо для меня.
3 ID: Pseudo-ID - генерируется на основе спецификаций физических устройств ANDROID_ID - Settings.Secure.ANDROID_ID
Адрес Bluetooth - адрес адаптера Bluetooth
Он вернет что-то вроде этого: 551F27C060712A72730B0A0F734064B1
Примечание. Вы всегда можете добавить больше идентификаторов в строку longId
. Например, Serial #. беспроводной адаптер адрес. IMEI. Таким образом, вы делаете его более уникальным для каждого устройства.
@SuppressWarnings("deprecation")
@SuppressLint("HardwareIds")
public static String generateDeviceIdentifier(Context context) {
String pseudoId = "35" +
Build.BOARD.length() % 10 +
Build.BRAND.length() % 10 +
Build.CPU_ABI.length() % 10 +
Build.DEVICE.length() % 10 +
Build.DISPLAY.length() % 10 +
Build.HOST.length() % 10 +
Build.ID.length() % 10 +
Build.MANUFACTURER.length() % 10 +
Build.MODEL.length() % 10 +
Build.PRODUCT.length() % 10 +
Build.TAGS.length() % 10 +
Build.TYPE.length() % 10 +
Build.USER.length() % 10;
String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
String btId = "";
if (bluetoothAdapter != null) {
btId = bluetoothAdapter.getAddress();
}
String longId = pseudoId + androidId + btId;
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(longId.getBytes(), 0, longId.length());
// get md5 bytes
byte md5Bytes[] = messageDigest.digest();
// creating a hex string
String identifier = "";
for (byte md5Byte : md5Bytes) {
int b = (0xFF & md5Byte);
// if it is a single digit, make sure it have 0 in front (proper padding)
if (b <= 0xF) {
identifier += "0";
}
// add number to string
identifier += Integer.toHexString(b);
}
// hex string to uppercase
identifier = identifier.toUpperCase();
return identifier;
} catch (Exception e) {
Log.e("TAG", e.toString());
}
return "";
}
longId
и сохранение его в файле сделает его самым уникальным идентификатором: String uuid = UUID.randomUUID().toString();
– Mousa Alfhaily
11 April 2017 в 07:08
Я использую следующий код, чтобы получить IMEI
или использовать Secure. ANDROID_ID
в качестве альтернативы, когда устройство не имеет возможностей телефона:
String identifier = null;
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE));
if (tm != null)
identifier = tm.getDeviceId();
if (identifier == null || identifier .length() == 0)
identifier = Secure.getString(activity.getContentResolver(),Secure.ANDROID_ID);
Мои два цента - NB это для уникального идентификатора устройства (err) - не для установки, как описано в блоге разработчиков разработчиков Android .
Следует отметить, что решение , предоставленное @emmby, возвращается в каждом идентификаторе приложения, поскольку SharedPreferences не синхронизированы между процессами (см. здесь здесь и здесь ). Поэтому я избегал этого вообще.
Вместо этого я инкапсулировал различные стратегии для получения идентификатора (устройства) в перечислении - изменение порядка констант перечисления влияет на приоритет различных способов получения идентификатора. Возвращается первый ненулевой идентификатор или генерируется исключение (согласно хорошей практике Java, не дающей значения null). Так, например, у меня сначала ТЕЛЕФОННЫЙ, но хорошим выбором по умолчанию будет бета-версия ANDROID_ID:
import android.Manifest.permission;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.wifi.WifiManager;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;
import android.util.Log;
// TODO : hash
public final class DeviceIdentifier {
private DeviceIdentifier() {}
/** @see http://code.google.com/p/android/issues/detail?id=10603 */
private static final String ANDROID_ID_BUG_MSG = "The device suffers from "
+ "the Android ID bug - its ID is the emulator ID : "
+ IDs.BUGGY_ANDROID_ID;
private static volatile String uuid; // volatile needed - see EJ item 71
// need lazy initialization to get a context
/**
* Returns a unique identifier for this device. The first (in the order the
* enums constants as defined in the IDs enum) non null identifier is
* returned or a DeviceIDException is thrown. A DeviceIDException is also
* thrown if ignoreBuggyAndroidID is false and the device has the Android ID
* bug
*
* @param ctx
* an Android constant (to retrieve system services)
* @param ignoreBuggyAndroidID
* if false, on a device with the android ID bug, the buggy
* android ID is not returned instead a DeviceIDException is
* thrown
* @return a *device* ID - null is never returned, instead a
* DeviceIDException is thrown
* @throws DeviceIDException
* if none of the enum methods manages to return a device ID
*/
public static String getDeviceIdentifier(Context ctx,
boolean ignoreBuggyAndroidID) throws DeviceIDException {
String result = uuid;
if (result == null) {
synchronized (DeviceIdentifier.class) {
result = uuid;
if (result == null) {
for (IDs id : IDs.values()) {
try {
result = uuid = id.getId(ctx);
} catch (DeviceIDNotUniqueException e) {
if (!ignoreBuggyAndroidID)
throw new DeviceIDException(e);
}
if (result != null) return result;
}
throw new DeviceIDException();
}
}
}
return result;
}
private static enum IDs {
TELEPHONY_ID {
@Override
String getId(Context ctx) {
// TODO : add a SIM based mechanism ? tm.getSimSerialNumber();
final TelephonyManager tm = (TelephonyManager) ctx
.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null) {
w("Telephony Manager not available");
return null;
}
assertPermission(ctx, permission.READ_PHONE_STATE);
return tm.getDeviceId();
}
},
ANDROID_ID {
@Override
String getId(Context ctx) throws DeviceIDException {
// no permission needed !
final String andoidId = Secure.getString(
ctx.getContentResolver(),
android.provider.Settings.Secure.ANDROID_ID);
if (BUGGY_ANDROID_ID.equals(andoidId)) {
e(ANDROID_ID_BUG_MSG);
throw new DeviceIDNotUniqueException();
}
return andoidId;
}
},
WIFI_MAC {
@Override
String getId(Context ctx) {
WifiManager wm = (WifiManager) ctx
.getSystemService(Context.WIFI_SERVICE);
if (wm == null) {
w("Wifi Manager not available");
return null;
}
assertPermission(ctx, permission.ACCESS_WIFI_STATE); // I guess
// getMacAddress() has no java doc !!!
return wm.getConnectionInfo().getMacAddress();
}
},
BLUETOOTH_MAC {
@Override
String getId(Context ctx) {
BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
if (ba == null) {
w("Bluetooth Adapter not available");
return null;
}
assertPermission(ctx, permission.BLUETOOTH);
return ba.getAddress();
}
}
// TODO PSEUDO_ID
// http://www.pocketmagic.net/2011/02/android-unique-device-id/
;
static final String BUGGY_ANDROID_ID = "9774d56d682e549c";
private final static String TAG = IDs.class.getSimpleName();
abstract String getId(Context ctx) throws DeviceIDException;
private static void w(String msg) {
Log.w(TAG, msg);
}
private static void e(String msg) {
Log.e(TAG, msg);
}
}
private static void assertPermission(Context ctx, String perm) {
final int checkPermission = ctx.getPackageManager().checkPermission(
perm, ctx.getPackageName());
if (checkPermission != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Permission " + perm + " is required");
}
}
// =========================================================================
// Exceptions
// =========================================================================
public static class DeviceIDException extends Exception {
private static final long serialVersionUID = -8083699995384519417L;
private static final String NO_ANDROID_ID = "Could not retrieve a "
+ "device ID";
public DeviceIDException(Throwable throwable) {
super(NO_ANDROID_ID, throwable);
}
public DeviceIDException(String detailMessage) {
super(detailMessage);
}
public DeviceIDException() {
super(NO_ANDROID_ID);
}
}
public static final class DeviceIDNotUniqueException extends
DeviceIDException {
private static final long serialVersionUID = -8940090896069484955L;
public DeviceIDNotUniqueException() {
super(ANDROID_ID_BUG_MSG);
}
}
}
TelephonyManager
и ANDROID_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, см. Идентификация установок приложений .
Существует множество различных подходов к решению этих проблем ANDROID_ID
(иногда может быть null
, или устройства определенной модели всегда возвращают один и тот же идентификатор) с плюсами и минусами:
Я сам предпочитаю использовать существующую реализацию OpenUDID (см. https : //github.com/ylechelle/OpenUDID ) для Android (см. https://github.com/vieux/OpenUDID ). Легко интегрировать и использовать ANDROID_ID
с резервными исправлениями для упомянутых выше проблем.
ro.serialno
используется для генерации Settings.Secure.ANDROID_ID
. Таким образом, они представляют собой в основном разные представления одинакового значения.
– Martin
23 June 2011 в 07:31
ANDROID_ID
.
– Ronnie
17 September 2011 в 09:28
android.os.Build.SERIAL
будет устаревшим в Android O, см. android-developers.googleblog.com/2017/04/…
– EpicPandaForce
12 April 2017 в 08:28
Подробные инструкции о том, как получить уникальный идентификатор для каждого Android-устройства, на котором установлено ваше приложение, см. в официальной публикации блога разработчиков Android Идентификация приложений .
Кажется, вам лучше всего создать его самостоятельно при установке, а затем прочитать его, когда приложение заново запущено.
Я лично считаю это приемлемым, но не идеальным. Ни один идентификатор, предоставляемый Android, не работает во всех случаях, поскольку большинство из них зависит от состояния радиосвязи телефона (включение / выключение Wi-Fi, включение / выключение соты, включение / выключение Bluetooth). Другие, такие как Settings.Secure.ANDROID_ID
, должны быть реализованы изготовителем и не гарантированы быть уникальными.
Ниже приведен пример записи данных в файл installation , который будет сохраненный вместе с любыми другими данными, которые приложение сохраняет локально.
public class Installation {
private static String sID = null;
private static final String INSTALLATION = "INSTALLATION";
public synchronized static String id(Context context) {
if (sID == null) {
File installation = new File(context.getFilesDir(), INSTALLATION);
try {
if (!installation.exists())
writeInstallationFile(installation);
sID = readInstallationFile(installation);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
return sID;
}
private static String readInstallationFile(File installation) throws IOException {
RandomAccessFile f = new RandomAccessFile(installation, "r");
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
f.close();
return new String(bytes);
}
private static void writeInstallationFile(File installation) throws IOException {
FileOutputStream out = new FileOutputStream(installation);
String id = UUID.randomUUID().toString();
out.write(id.getBytes());
out.close();
}
}
ro.serialno
используется для генерации Settings.Secure.ANDROID_ID
. Таким образом, они представляют собой в основном разные представления одинакового значения.
– Martin
23 June 2011 в 07:31
ANDROID_ID
.
– Ronnie
17 September 2011 в 09:28
android.os.Build.SERIAL
будет устаревшим в Android O, см. android-developers.googleblog.com/2017/04/…
– EpicPandaForce
12 April 2017 в 08:28
Поле Serial было добавлено в класс Build
в уровне API 9 (Android 2.3 - Gingerbread). Документация говорит, что он представляет собой серийный номер оборудования. Таким образом, он должен быть уникальным, если он существует на устройстве.
Я не знаю, действительно ли он поддерживается (= не null) всеми устройствами с уровнем API> = 9.
ro.serialno
используется для генерации Settings.Secure.ANDROID_ID
. Таким образом, они представляют собой в основном разные представления одинакового значения.
– Martin
23 June 2011 в 07:31
ANDROID_ID
.
– Ronnie
17 September 2011 в 09:28
android.os.Build.SERIAL
будет устаревшим в Android O, см. android-developers.googleblog.com/2017/04/…
– EpicPandaForce
12 April 2017 в 08:28
Используя приведенный ниже код, вы можете получить уникальный идентификатор устройства устройства Android OS в виде строки.
deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
ro.serialno
используется для генерации Settings.Secure.ANDROID_ID
. Таким образом, они представляют собой в основном разные представления одинакового значения.
– Martin
23 June 2011 в 07:31
ANDROID_ID
.
– Ronnie
17 September 2011 в 09:28
android.os.Build.SERIAL
будет устаревшим в Android O, см. android-developers.googleblog.com/2017/04/…
– EpicPandaForce
12 April 2017 в 08:28
Следующий код возвращает серийный номер устройства с помощью скрытого API Android. Но этот код не работает на вкладке Samsung Galaxy Tab, потому что на этом устройстве не установлено «ro.serialno».
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) {
}
ro.serialno
используется для генерации Settings.Secure.ANDROID_ID
. Таким образом, они представляют собой в основном разные представления одинакового значения.
– Martin
23 June 2011 в 07:31
ANDROID_ID
.
– Ronnie
17 September 2011 в 09:28
android.os.Build.SERIAL
будет устаревшим в Android O, см. android-developers.googleblog.com/2017/04/…
– EpicPandaForce
12 April 2017 в 08:28