1.mac 地址,在 Android 6.0(API 级别 23)及更高版本中,本地设备 MAC 地址(例如 WLAN 和蓝牙)无法通过第三方 API 获取。WifiInfo.getMacAddress() 方法和 BluetoothAdapter.getDefaultAdapter().getAddress() 方法都会返回 02:00:00:00:00:00,但可以通过其他方法获取。下面是找到的一个有效的方法,在6.0,7.0设备上可以获取到。

public final class DeviceUtils {

private DeviceUtils() {

throw new UnsupportedOperationException("u can't instantiate me...");

}

/**

* Return version code of device's system.

*

* @return version code of device's system

*/

public static int getSDKVersionCode() {

return Build.VERSION.SDK_INT;

}

/**

* Return the android id of device.

*

* @return the android id of device

*/

@SuppressLint("HardwareIds")

public static String getAndroidID() {

return Settings.Secure.getString(

Utils.getApp().getContentResolver(),

Settings.Secure.ANDROID_ID

);

}

/**

* Return the MAC address.

*

Must hold

* {@code },

* {@code }

*

* @return the MAC address

*/

@RequiresPermission(allOf = {ACCESS_WIFI_STATE, INTERNET})

public static String getMacAddress() {

String macAddress = getMacAddressByWifiInfo();

if (!"02:00:00:00:00:00".equals(macAddress)) {

return macAddress;

}

macAddress = getMacAddressByNetworkInterface();

if (!"02:00:00:00:00:00".equals(macAddress)) {

return macAddress;

}

macAddress = getMacAddressByInetAddress();

if (!"02:00:00:00:00:00".equals(macAddress)) {

return macAddress;

}

macAddress = getMacAddressByFile();

if (!"02:00:00:00:00:00".equals(macAddress)) {

return macAddress;

}

return "please open wifi";

}

@SuppressLint({"HardwareIds", "MissingPermission"})

private static String getMacAddressByWifiInfo() {

try {

Context context = Utils.getApp().getApplicationContext();

WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

if (wifi != null) {

WifiInfo info = wifi.getConnectionInfo();

if (info != null) return info.getMacAddress();

}

} catch (Exception e) {

e.printStackTrace();

}

return "02:00:00:00:00:00";

}

private static String getMacAddressByNetworkInterface() {

try {

Enumerationnis = NetworkInterface.getNetworkInterfaces();

while (nis.hasMoreElements()) {

NetworkInterface ni = nis.nextElement();

if (ni == null || !ni.getName().equalsIgnoreCase("wlan0")) continue;

byte[] macBytes = ni.getHardwareAddress();

if (macBytes != null && macBytes.length > 0) {

StringBuilder sb = new StringBuilder();

for (byte b : macBytes) {

sb.append(String.format("%02x:", b));

}

return sb.substring(0, sb.length() - 1);

}

}

} catch (Exception e) {

e.printStackTrace();

}

return "02:00:00:00:00:00";

}

private static String getMacAddressByInetAddress() {

try {

InetAddress inetAddress = getInetAddress();

if (inetAddress != null) {

NetworkInterface ni = NetworkInterface.getByInetAddress(inetAddress);

if (ni != null) {

byte[] macBytes = ni.getHardwareAddress();

if (macBytes != null && macBytes.length > 0) {

StringBuilder sb = new StringBuilder();

for (byte b : macBytes) {

sb.append(String.format("%02x:", b));

}

return sb.substring(0, sb.length() - 1);

}

}

}

} catch (Exception e) {

e.printStackTrace();

}

return "02:00:00:00:00:00";

}

private static InetAddress getInetAddress() {

try {

Enumerationnis = NetworkInterface.getNetworkInterfaces();

while (nis.hasMoreElements()) {

NetworkInterface ni = nis.nextElement();

// To prevent phone of xiaomi return "10.0.2.15"

if (!ni.isUp()) continue;

Enumerationaddresses = ni.getInetAddresses();

while (addresses.hasMoreElements()) {

InetAddress inetAddress = addresses.nextElement();

if (!inetAddress.isLoopbackAddress()) {

String hostAddress = inetAddress.getHostAddress();

if (hostAddress.indexOf(':') < 0) return inetAddress;

}

}

}

} catch (SocketException e) {

e.printStackTrace();

}

return null;

}

private static String getMacAddressByFile() {

ShellUtils.CommandResult result = ShellUtils.execCmd("getprop wifi.interface", false);

if (result.result == 0) {

String name = result.successMsg;

if (name != null) {

result = ShellUtils.execCmd("cat /sys/class/net/" + name + "/address", false);

if (result.result == 0) {

String address = result.successMsg;

if (address != null && address.length() > 0) {

return address;

}

}

}

}

return "02:00:00:00:00:00";

}

2.android_Id  在 Android 8.0(API 级别 26)及更高版本中,SSAID 提供了一个在由同一开发者签名密钥签名的应用之间通用的标识符。借助它,您可以在这些应用之间共享状态,而无需要求用户登录帐号。这是官网的翻译,实在不明白是什么意思!可以知道的是恢复出厂设置这个值是会被改变的,而且存在有的设备获取到的为null 的情况

@SuppressLint("HardwareIds")

public static String getAndroidID() {

return Settings.Secure.getString(

Utils.getApp().getContentResolver(),

Settings.Secure.ANDROID_ID

);

}

以下内容取自:http://blog.rcant.com/2018/05/02/android/android_uuid_get/

3.The IMEI: 仅仅只对Android手机有效:

1

2

TelephonyManager TelephonyMgr = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);

String szImei = TelephonyMgr.getDeviceId();

采用此种方法,需要在AndroidManifest.xml中加入一个许可:android.permission.READ_PHONE_STATE,并且用户应当允许安装此应用。作为手机来讲,IMEI是唯一的,它应该类似于 359881030314356(除非你有一个没有量产的手机(水货)它可能有无效的IMEI,如:0000000000000)。

4.Pseudo-Unique ID, 这个在任何Android手机中都有效

有一些特殊的情况,一些如平板电脑的设置没有通话功能,或者你不愿加入READ_PHONE_STATE许可。而你仍然想获得唯一序列号之类的东西。这时你可以通过取出ROM版本、制造商、CPU型号、以及其他硬件信息来实现这一点。这样计算出来的ID不是唯一的(因为如果两个手机应用了同样的硬件以及Rom 镜像)。但应当明白的是,出现类似情况的可能性基本可以忽略。要实现这一点,你可以使用Build类:

大多数的Build成员都是字符串形式的,我们只取他们的长度信息。我们取到13个数字,并在前面加上“35”。这样这个ID看起来就和15位IMEI一样了

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

5.拼接生成UUID

//获取手机的唯一标识

public String getPhoneSign(){

StringBuilder deviceId = new StringBuilder();

// 渠道标志

deviceId.append("a");

try {

//IMEI(imei)

TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);

String imei = tm.getDeviceId();

if(!TextUtils.isEmpty(imei)){

deviceId.append("imei");

deviceId.append(imei);

return deviceId.toString();

}

//序列号(sn)

String sn = tm.getSimSerialNumber();

if(!TextUtils.isEmpty(sn)){

deviceId.append("sn");

deviceId.append(sn);

return deviceId.toString();

}

//如果上面都没有, 则生成一个id:随机码

String uuid = getUUID();

if(!TextUtils.isEmpty(uuid)){

deviceId.append("id");

deviceId.append(uuid);

return deviceId.toString();

}

} catch (Exception e) {

e.printStackTrace();

deviceId.append("id").append(getUUID());

}

return deviceId.toString();

}

/**

* 得到全局唯一UUID

*/

private String uuid;

public String getUUID(){

SharedPreferences mShare = getSharedPreferences("uuid",MODE_PRIVATE);

if(mShare != null){

uuid = mShare.getString("uuid", "");

}

if(TextUtils.isEmpty(uuid)){

uuid = UUID.randomUUID().toString();

mShare.edit().putString("uuid",uuid).commit();

}

return uuid;

}

UUID是指在一台机器上生成的数字,它保证对在 同一时空中 的所有机器都是唯一的。通常平台会提供生成的API。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字.

总结:个人感觉从上面的内容看,方法四 更好一些,虽然现在项目用的是mac 地址,后台要mac 给他mac 就是了,不想多BB。感觉移动端还是有点苦逼的,后台不需要了解移动端,前端更不必,但移动端却要要求懂后台和前端,还要搞jni +c 。立个flag 总有一天,前端,后台,移动端 全自己做了

android app唯一标识符,android 唯一识别码笔记相关推荐

  1. android app的签名,Android APP的签名

    Android APP的签名 Android项目以它的包名作为唯一的标识,如果在同一部手机上安装两个包名相同的APP,后者就会覆盖前面安装的应用.为了避免Android APP被随意覆盖,Androi ...

  2. android app 主界面,android ViewPager实现App主界面Tab菜单页面切换和点击事件

    Tabhost实现页面滑动切换比较麻烦,这里介绍一下viewPage 控件. 实现了三屏滑动带标题点击和tab页面内按钮的的点击事件实现: viewPage  的优点是可以滑动切换缺点是MainAct ...

  3. android app文件夹,android app文件目录结构

    转:https://blog.csdn.net/luoguopeng/article/details/72832567 android app目录: SDCard/Android/data/你的应用的 ...

  4. Android App 隐藏图标(Android 10除外)并隐式启动

    正好有个小需求,要把Android的App图标隐藏掉(Android 10除外,下面简单说明一下),并提供隐式启动. 实现这个功能非常简单,直接上代码. AndroidManifest.xml文件: ...

  5. android app 目标版本,android – 在gradle中使用目标sdk版本23时,ZBA...

    我在我的项目中使用zbar扫描程序库.更新到sdk 23后,Marshmallow扫描仪无法正常工作.以下是gradle文件.如果我将targetSdkVersion设置为23以外的任何东西,扫描仪正 ...

  6. android app性能测试工具,Android 性能测试 - 内存

    1.内存了解 在Android App的性能优化的各个部分里,内存方面的知识较多且不易理解,内存的问题绝对是最令人头疼的一部分,需要对内存基础知识.内存分配.内存管理机制等非常熟悉,才能排查题. 1. ...

  7. android app 天气功能,Android天气预报app改进版

    最近总是有人来和我说我以前写的一个小app无法正常获取数据~Android简易版天气预报app 今天就又运行了下来查找问题,发现或许是接口有限制吧,不能在多台手机使用同个apikey 然后,发现了我写 ...

  8. android app 退出功能,Android 应用技巧: 手把手教你 优雅实现 “一键退出 App”

    前言 在 Android开发中,会经常存在 "一键退出App" 的需求 但市面上流传着 太多不可用的"一键退出App"功能实现 本文将全面总结"一键退 ...

  9. android app 自动登录,Android APP首次登录和之后自动登录流程

    Android APP首次登录和之后自动登录流程 Android APP首次登录和之后自动登录流程 App登陆保存数据流程 App因为要实现自动登陆功能,所以必然要保存一些凭据,所以比较复杂. App ...

  10. android app被回收,Android app被回收之后会导致的问题

    当android app被回收之后,再次点击图标会回到最后打开的页面,但是一些数据已经被回收了,直接打开可能会报空指针异常之类的,我们可以判断是否被回收,然后重启app public class St ...

最新文章

  1. Jquery DIV滚动至浏览器顶部后固定不动代码
  2. 前端 圆形进度图_图解CSS3制作圆环形进度条的实例教程
  3. 【R语言学习】时间序列
  4. mysql临时表 清空_在数据库中临时表什么时候会被清除呢
  5. mysql udp服务器_netty学习:UDP服务器与Spring整合(2)
  6. mysql检索整数_MyBatis从MySql DB中检索整数为Enum
  7. 作业帮:字符串反转(头部插入)
  8. 解决 service、killall 等命令找不到的问题
  9. 翁恺老师C语言学习笔记(十)指针_运算符取得变量的地址
  10. 活性边表算法c语言,《计算机图形学》有序边表填充算法.doc
  11. python中日志logging模块和异常捕获traceback模块的使用
  12. 通过分布式把本地图片上传到FTP(1)
  13. MacOS使用技巧总结
  14. MeanShift跟踪MATLAB实现
  15. 使用python的模拟退火算法估计heston期权定价模型的五个参数(新)
  16. 怎样在PDF文档中添加插入图片
  17. web前端学习1-45集
  18. WEB页面或者H5页面如何打开高德或者百度地图APP导航(实战向)
  19. Java基础知识11——数组
  20. 导师-学生问题_广义表

热门文章

  1. 【php写日志】php将日志写入文件
  2. minio  nginx 配置
  3. Have Fun with Numbers及循环链表(约瑟夫问题)
  4. eclipse 项目显示红叉
  5. PHP如何大幅度提升运行效率? -- 把它编译成机器码!
  6. 综合应用WPF/WCF/WF/LINQ之二十九:代码生成器之DBMLToCode
  7. Elasticsearch 之索引创建原则
  8. java B2B2C 多租户电子商城系统-SpringCloud动态刷新配置信息
  9. 10.React中的组件、父子组件、React props父组件给子组件传值、子组件给父组件传值、父组件中通过refs获取子组件属性和方法...
  10. C/C++笔记(01):容易出错的几个库函数