Android Q(安卓10)獲取唯一ID(最優解)

安卓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();
    }

好的,先這樣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章