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


当前回答

在Google I/O上,Reto Meier发布了一个关于如何实现这一点的有力答案,这应该能满足大多数开发人员在安装过程中跟踪用户的需求。安东尼·诺兰(Anthony Nolan)在他的回答中指明了方向,但我想我应该写出完整的方法,这样其他人就可以很容易地看到如何做到这一点(我花了一段时间才弄清楚细节)。

这种方法将为您提供一个匿名、安全的用户ID,该ID将在不同设备(基于主要的Google帐户)和不同安装中为用户持久保存。基本方法是生成一个随机用户ID,并将其存储在应用程序的共享偏好中。然后使用Google的备份代理将链接到Google帐户的共享首选项存储在云中。

让我们了解一下完整的方法。首先,我们需要使用Android备份服务为SharedPreferences创建备份。通过注册应用程序开始http://developer.android.com/google/backup/signup.html.

谷歌会给你一个备份服务密钥,你需要将其添加到清单中。您还需要告诉应用程序使用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>

然后,您需要创建备份代理,并告诉它使用helper代理进行共享引用:

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

最后创建一个用户ID(如果它还不存在),并将其存储在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现在也将在安装过程中保持不变。

有关此方法的更多信息,请参阅Reto的演讲。

有关如何实施备份代理的详细信息,请参阅数据备份。我特别推荐底部的测试部分,因为备份不会立即发生,所以为了测试,必须强制备份。

其他回答

在类文件中添加以下代码:

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" />

当设备没有电话功能时,我使用以下代码获取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);
String SERIAL_NUMER = Build.SERIAL;

以每个设备中唯一的字符串形式返回SERIAL NUMBER。

要获取用户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

此外,您还可以考虑Wi-Fi适配器的MAC地址。检索方式如下:

WifiManager wm = (WifiManager)Ctxt.getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getMacAddress();

清单中需要权限android.permission.ACCESS_WIFI_STATE。

据报道,即使未连接Wi-Fi,也可用。如果上面的答案中的乔在他的许多设备上尝试一下,那就太好了。

在某些设备上,当Wi-Fi关闭时,它不可用。

注意:从Android6.x,它返回一致的假mac地址:02:00:00:00:00