安卓Q中google彻底禁止了第三发应用获取imei,并且mac地址返回的地址也变成了02:00:00:00:00:00。
这是官方给出的解决方案:
https://developer.android.com/training/articles/user-data-ids
这是官网的截图:
方法一:
既然这两个都没法获取了,所以想到获取ANDROID_ID:
public static String getAndroidId (Context context) { String ANDROID_ID = Settings.System.getString(context.getContentResolver(), Settings.System.ANDROID_ID); return ANDROID_ID; }
但是发现不同应用的正式包在相同设备上得到的ANDROID_ID结果不同,因此显然该方案不可行。
方法二:
按照google官方意见,是在安装应用时,生成UUID,保存到本地,如果本地已经存在UUID,则不在保存,这样就可以将UUID作为唯一标识符。下面是官方推荐截图:
好的,那么就使用UUID:
String uuidStr = UUID.randomUUID().toString();
将UUID以文件的形式保存在多媒体文件目录下,这样一来各个不同的应用间都能采用同一个UUID。生成UUID。其中 saveFileName 为存放uuid数据的文件名:
/** * 在媒体文件中 生成fileName文件 * 向Mediastore添加内容 * * @param saveFileName 保存文件的名称 */ private void creatUUIDFile(String saveFileName) { ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.DISPLAY_NAME, saveFileName); values.put(MediaStore.Images.Media.MIME_TYPE, "image/*"); // TODO: 2019-10-11 IS_PENDING = 1表示对应的item还没准备好 values.put(MediaStore.Images.Media.IS_PENDING, 1); ContentResolver resolver = this.getContentResolver(); Uri collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY); Uri uri = resolver.insert(collection, values); try { //访问 对于单个媒体文件,请使用 openFileDescriptor()。 ParcelFileDescriptor fielDescriptor = resolver.openFileDescriptor(uri, "w", null); FileOutputStream outputStream = new FileOutputStream(fielDescriptor.getFileDescriptor()); try { //讲UUID写入到文件中 String uuidStr = UUID.randomUUID().toString(); outputStream.write(uuidStr.getBytes()); outputStream.close(); Log.d(TAG, "写入 uuidStr:" + uuidStr); } catch (IOException e) { e.printStackTrace(); } values.clear(); values.put(MediaStore.Images.Media.IS_PENDING, 0); //设置为0 resolver.update(uri, values, null, null); } catch (FileNotFoundException e) { e.printStackTrace(); } }
如果需要判断是否已经存在存放uuid的文件,则用下面的方法:
/** * 检查文件是否存在 * * @param saveFileName 保存文件的名称 * @return true 为存在 false为不存在 */ private boolean checkUUIDFileByUri(String saveFileName) { Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; String[] projection = { MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media._ID }; //查询 ContentResolver contentResolver = this.getContentResolver(); // 添加筛选条件 String selection = MediaStore.Images.Media.DISPLAY_NAME + "=" + "'" + saveFileName + "'"; Cursor mCursor = contentResolver.query(mImageUri, projection, selection, null, null); String getSaveContent = ""; if (mCursor != null) { while (mCursor.moveToNext()) { int fileIdIndex = mCursor.getColumnIndex(MediaStore.Images.Media._ID); String thumbPath = MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon() .appendPath(String.valueOf(mCursor.getInt(fileIdIndex))).build().toString(); Uri fileUri = Uri.parse(thumbPath); try { ParcelFileDescriptor fielDescriptor = contentResolver.openFileDescriptor(fileUri, "r", null); FileInputStream inputStream = new FileInputStream(fielDescriptor.getFileDescriptor()); getSaveContent = inputStreamToString(inputStream); } catch (FileNotFoundException e) { e.printStackTrace(); } //只有在得到的唯一标识符不为空的情况下才结束循环,否则一直循环 if (!TextUtils.isEmpty(getSaveContent)) { break; } } mCursor.close(); } return !getSaveContent.equals(""); }
上面代码中的inputStreamToString()方法为流转字符串,代码如下:
/** * 流转为字符串 * * @param is 流 * @return 转换完成的字符串 */ public String inputStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line; try { while ((line = reader.readLine()) != null) { sb.append(line).append("/n"); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); }