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


当前回答

为了包括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。

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

其他回答

Settings.Secure#ANDROID_ID返回每个用户64位十六进制字符串的唯一ANDROID ID。

import android.provider.Settings.Secure;

private String android_id = Secure.getString(getContext().getContentResolver(),
                                                        Secure.ANDROID_ID);

另请阅读唯一标识符的最佳实践:https://developer.android.com/training/articles/user-data-ids

TelephonyManager.getDeviceId()返回唯一的设备ID,例如,GSM的IMEI和CDMA电话的MEID或ESN。

final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);            
String myAndroidDeviceId = mTelephony.getDeviceId(); 

但我建议使用:

Settings.Secure.ANDROID_ID,将ANDROID ID作为唯一的64位十六进制字符串返回。

    String   myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID); 

有时TelephonyManager.getDeviceId()将返回null,因此为了确保唯一的id,您将使用以下方法:

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

API级别9(Android 2.3-姜饼)中的Build类中添加了一个Serial字段。文档表示它代表硬件序列号。因此,如果设备上存在,它应该是唯一的。

我不知道API级别>=9的所有设备是否都支持(=不为空)。

要获取用户id,您可以使用Google Play授权库。

要下载此库,请打开SDK管理器=>SDK工具。下载的库文件的路径为:

path_to_android_sdk_on_your_pc/extras/google/market_licensing/library

将库包含在项目中(只需复制其文件)。

接下来,您需要一些策略接口的实现(只需使用库中的两个文件之一:ServerManagedPolicy或StrictPolicy)。

将在processServerResponse()函数中为您提供用户id:

public void processServerResponse(int response, ResponseData rawData) {
    if(rawData != null) {
        String userId = rawData.userId
        // use/save the value
    }
    // ...
}

接下来,需要使用策略构造LicenseChecker,并调用checkAccess()函数。使用MainActivity.java作为示例说明如何执行此操作。MainActivity.ava位于以下文件夹中:

path_to_android_sdk_on_your_pc/extras/google/market_licensing/sample/src.com/sample/android/market/licensing

不要忘记将CHECK_LICENSE权限添加到AndroidManifest.xml。

有关授权库的详细信息:https://developer.android.com/google/play/licensing

为了完整起见,以下是如何在Xamarin.Android和C#中获取Id:

var id = Settings.Secure.GetString(ContentResolver, Settings.Secure.AndroidId);

或者如果您不在“活动”中:

var id = Settings.Secure.GetString(context.ContentResolver, Settings.Secure.AndroidId);

其中上下文是传入的上下文。