Android设备有唯一的ID吗?如果有,使用Java访问它的简单方法是什么?
当前回答
我认为这是建立一个独特身份的骨架的最佳方式……看看吧。
伪唯一ID,适用于所有Android设备某些设备没有电话(例如平板电脑),或者出于某种原因,您不希望包含READ_phone_STATE权限。您仍然可以阅读ROM版本、制造商名称、CPU类型和其他硬件详细信息,如果您想将ID用于串行密钥检查或其他一般用途,这些信息将非常适合。以这种方式计算的ID不会是唯一的:可以找到两个具有相同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),以具有与IMEI相同的大小ID(15个数字)。这里还有其他的可能性,好吧,看看这些字符串。返回355715565309247。无需特别许可,这使得该方法非常方便。
(额外信息:上面给出的技术是从Pocket Magic上的一篇文章中复制的。)
其他回答
有关如何为安装应用程序的每个Android设备获取唯一标识符的详细说明,请参阅官方Android开发者博客“识别应用程序安装”。
似乎最好的方法是在安装时自己生成一个,然后在重新启动应用程序时读取它。
我个人认为这是可以接受的,但并不理想。Android提供的标识符在所有情况下都不起作用,因为大多数都取决于手机的无线电状态(Wi-Fi开/关、手机开/关和蓝牙开/关)。其他设置(如Settings.Secure.ANDROID_ID)必须由制造商实现,并且不保证是唯一的。
以下是将数据写入安装文件的示例,该文件将与应用程序本地保存的任何其他数据一起存储。
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();
}
}
另一种方法是在没有任何权限的应用程序中使用/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文件并读取字符。只需确保将其包装在异常处理程序中,因为并非所有设备都有此文件。
已知至少以下设备具有此文件世界可读性:
银河天枢Nexus S公司摩托罗拉Xoom 3G东芝AT300HTC一V迷你MK802三星Galaxy S II
你也可以看到我的博客文章“泄露Android硬件序列号给未经授权的应用程序”,在这里我讨论了哪些其他文件可供参考。
1.使用提供唯一id(即IMEI)的电话管理器。参见示例,
import android.telephony.TelephonyManager;
import android.content.Context;
// ...
TelephonyManager telephonyManager;
telephonyManager = (TelephonyManager) getSystemService(Context.
TELEPHONY_SERVICE);
/*
* getDeviceId() returns the unique device ID.
* For example,the IMEI for GSM and the MEID or ESN for CDMA phones.
*/
String deviceId = telephonyManager.getDeviceId();
/*
* getSubscriberId() returns the unique subscriber ID,
*/
String subscriberId = telephonyManager.getSubscriberId();
这需要为您的用户提供android.permission.READ_PHONE_STATE,这很难证明遵循您所做的应用程序类型。
没有电话服务的设备(如平板电脑)必须报告一个唯一的设备ID,该ID可以通过android.os.Build.SERIAL从android 2.3 Gingerbread获得。一些具有电话服务的电话还可以定义序列号。就像不是所有的Android设备都有序列号一样,这种解决方案并不可靠。在设备首次启动时,会生成并存储一个随机值。此值可通过Settings.Secure.ANDROID_ID获得。它是一个64位数字,在设备的生命周期内应保持不变。ANDROID_ID似乎是唯一设备标识符的好选择,因为它适用于智能手机和平板电脑。要检索值,可以使用以下代码:,StringandroidId=Settings.Secure.getString(getContentResolver(),Settings.Secure.ANDROID_ID);
但是,如果在设备上执行出厂重置,则该值可能会更改。制造商的流行手机也存在一个已知的缺陷,每个实例都有相同的ANDROID_ID。显然,该解决方案并非100%可靠。
使用UUID。由于大多数应用程序的要求是识别特定的安装,而不是物理设备,因此,如果使用UUID类,获取用户的唯一id是一个很好的解决方案。以下解决方案由来自Google的Reto Meier在Google I/O演示中提出,
SharedPreferences sharedPrefs = context.getSharedPreferences(
PREF_UNIQUE_ID, Context.MODE_PRIVATE);
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
更新:选项#1和#2在android 10之后不再可用,因为谷歌进行了隐私更新。因为选项2和3需要关键许可。
您将通过使用以下代码获得wifi mac地址,无论您在尝试连接到wifi时是否使用了随机地址,也无论wifi是否打开或关闭。
我使用了下面链接中的一个方法,并添加了一个小修改,以获得准确的地址,而不是随机化的地址:
在Android 6.0中获取MAC地址
public static String getMacAddr() {
StringBuilder res1 = new StringBuilder();
try {
List<NetworkInterface> all =
Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {
if (!nif.getName().equalsIgnoreCase("p2p0")) continue;
byte[] macBytes = nif.getHardwareAddress();
if (macBytes == null) {
continue;
}
res1 = new StringBuilder();
for (byte b : macBytes) {
res1.append(String.format("%02X:",b));
}
if (res1.length() > 0) {
res1.deleteCharAt(res1.length() - 1);
}
}
} catch (Exception ex) {
}
return res1.toString();
}
以下代码使用隐藏的Android API返回设备序列号。但是,这个代码在三星Galaxy Tab上不起作用,因为这个设备上没有设置“ro.seriano”。
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) {
}
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 碎片中的onCreateOptionsMenu
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- DSL元素android.dataBinding。enabled'已过时,已被'android.buildFeatures.dataBinding'取代
- ConstraintLayout:以编程方式更改约束
- PANIC: AVD系统路径损坏。检查ANDROID_SDK_ROOT值
- 如何生成字符串类型的buildConfigField
- Recyclerview不调用onCreateViewHolder
- Android API 21工具栏填充
- Android L中不支持操作栏导航模式
- 如何在TextView中添加一个子弹符号?
- PreferenceManager getDefaultSharedPreferences在Android Q中已弃用
- 在Android Studio中创建aar文件