Android设备有唯一的ID吗?如果有,使用Java访问它的简单方法是什么?


当前回答

只获取一次设备ID,然后将其存储在数据库或文件中。在这种情况下,如果它是应用程序的第一次启动,它将生成一个ID并存储它。下次,它将只获取存储在文件中的ID。

其他回答

另一种方法是在没有任何权限的应用程序中使用/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硬件序列号给未经授权的应用程序”,在这里我讨论了哪些其他文件可供参考。

经过多次搜索。我意识到没有确定的方法可以拥有唯一的ID。

假设我们希望每个用户只能在一部手机上使用该应用程序。

我所做的是:

当用户在我的应用程序中注册时,我将当前时间保存为服务器和应用程序数据库中的唯一ID。

当用户尝试登录另一个电话时,我从服务器获取用户信息,并意识到该用户已经登录,因为唯一ID字段已满,所以向他/她显示一个对话框,表明他/她已经登录到另一个设备,无论他/她是否想离开上一个会话,如果他说是,我将为他创建一个新的唯一ID,并更新服务器上的唯一ID详细信息。

在我自己的应用程序中,每次运行时,我都会从服务器获取用户配置文件。如果存储在服务器上的唯一ID与存储在应用程序数据库中的唯一ID不同,我将自动注销用户。

为了包括Android 9,我只有一个想法可以继续工作,那就是(可能)不违反任何条款,需要权限,并且可以跨安装和应用程序工作。

涉及服务器的指纹应该能够唯一地识别设备。硬件信息+已安装的应用程序和安装时间的组合应该会起到作用。除非卸载并再次安装应用程序,否则首次安装时间不会更改。但这必须对设备上的所有应用程序进行,以便无法识别设备(即,在工厂重置后)。

我会这样做:

提取硬件信息、应用程序包名称和首次安装时间。

这是从Android中提取所有应用程序的方法(无需权限):

final PackageManager pm = application.getPackageManager();
List<ApplicationInfo> packages = 
pm.getInstalledApplications(PackageManager.GET_META_DATA);

for (ApplicationInfo packageInfo : packages) {
    try {
        Log.d(TAG, "Installed package :" + packageInfo.packageName);
        Log.d(TAG, "Installed :" + pm.getPackageInfo(packageInfo.packageName, 0).firstInstallTime);
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
}

在将每个包名称和安装时间戳组合发送到服务器之前,您可能需要对其进行哈希,因为用户在设备上安装的内容可能与您的业务无关,也可能与您无关。有些应用程序(实际上很多)是系统应用程序。这些可能具有相同的安装时间戳,与出厂重置后的最新系统更新相匹配。因为它们具有相同的安装时间戳,所以用户无法安装它们,并且可以过滤掉它们。将信息发送到服务器,并让它在先前存储的信息中查找最近的匹配。在安装和卸载应用程序时,您需要在与以前存储的设备信息进行比较时设置阈值。但我的猜测是,这一门槛可能很低,因为任何软件包名称和首次安装时间戳组合对于一个设备来说都是非常独特的,而且应用程序的安装和卸载并不频繁。拥有多个应用程序只会增加独一无二的可能性。返回为匹配项生成的唯一id,或生成唯一id,存储设备信息并返回此新id。

注:这是一种未经测试和验证的方法!我相信它会奏效,但我也非常确信,如果这一点流行起来,他们会以某种方式关闭它。

包com.aapbd.appbajarlib.common;import android.os.Build;导入java.util.Locale;导入java.util.UUID;公共类DeviceID{公共静态字符串getDeviceLanguage(){Locale Locale=Locale.getDefault();return locale.getDisplayLanguage();}公共静态字符串getDeviceCountry(){Locale Locale=Locale.getDefault();return locale.getDisplayCountry();}公共静态字符串getDeviceName(){字符串制造商=Build.manufacturer;字符串模型=Build.model;if(model.startsWith(制造商)){回报资本化(模型);}其他{回报资本化(制造商)+“”+模型;}}公共静态字符串getAndroidVersion(){字符串释放=Build.VERSION.release;int sdkVersion=内部版本.VERSION.SDK_int;return sdkVersion+“(”+release+“)”;}公共静态int getAndroidAPILevel(){int sdkVersion=内部版本.VERSION.SDK_int;return sdkVersion;}私有静态字符串大写(字符串s){如果(s==null||s.length()==0){return“”;}char first=s.charAt(0);if(字符.isUpperCase(第一个)){返回s;}其他{return Character.toUpperCase(first)+s.substring(1);}}/***返回伪唯一ID*@返回ID*/公共静态字符串getUniquePsuedoID(){//如果所有其他操作都失败,如果用户的API低于API 9(低于//而不是姜饼),已重置其设备或“安全.ANDROID_ID”//返回“null”,则返回的ID将仅基于//关闭他们的Android设备信息。这就是碰撞的地方//可能发生。//谢谢http://www.pocketmagic.net/?p=1662!//尽量不要使用DISPLAY、HOST或ID-这些项目可能会更改。//如果发生冲突,则会出现重叠数据字符串m_szDevIDShort=“35”+(Build.BOARD.length()%10)+(Build.BRAND.length)%10()+(Build.CPU_ABI.length;//感谢@Roman SL!// http://stackoverflow.com/a/4789483/950427//只有API>=9的设备具有android.os.Build.SERIAL// http://developer.android.com/reference/android/os/Build.html#SERIAL//如果用户升级软件或根目录他们的设备,将有一个重复条目字符串序列=空;尝试{serial=android.os.Build.class.getField(“serial”).get(null).toString();//继续并返回api=>9的序列号返回新UUID(m_szDevIDShort.hashCode(),serial.hashCode)).toString();}catch(异常异常){//字符串需要初始化serial=“serial”;//一些价值}//谢谢@乔!// http://stackoverflow.com/a/2853253/950427//最后,通过使用UUID类组合我们找到的值来创建唯一标识符返回新UUID(m_szDevIDShort.hashCode(),serial.hashCode)).toString();}}

我正在使用这个,它在过去的6年中一直有效。

这是图书馆:https://github.com/nillbiplob/AppBajarLIB

您将通过使用以下代码获得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();

}