亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android 版本、權(quán)限適配相關(guān)總結(jié)

 更新時(shí)間:2021年05月20日 08:44:54   作者:東慕雨  
針對(duì) Android 6.0 (API 23)已以上版本,Google 增強(qiáng)全新的權(quán)限,應(yīng)用程序在使用敏感權(quán)限(如拍照、查閱聯(lián)系人或存儲(chǔ))時(shí)需要先征求用戶必須贏得用戶同意。

請(qǐng)求存儲(chǔ)權(quán)限

首先需要在 AndroidManifest.xml 文件中聲明權(quán)限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

在代碼中請(qǐng)求用戶權(quán)限:

    // 權(quán)限請(qǐng)求碼
    private static final int PERMISSION_REQ_ID = 0;  
    // 請(qǐng)求權(quán)限
    private static final String[] REQUESTED_PERMISSIONS = {
            Manifest.permission.READ_EXTERNAL_STORAGE
    };

    ...

     // 判斷有沒(méi)有存儲(chǔ)權(quán)限
    if (checkSelfPermission(REQUESTED_PERMISSIONS[0],PERMISSION_REQ_ID)){
        //YSE 
    }else {
        //NO
    }
    private boolean checkSelfPermission(String permissions,int requestCode){
        if (ContextCompat.checkSelfPermission(this,permissions) != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this, REQUESTED_PERMISSIONS, requestCode);
            return false;
        }
        return true;
    }

    // 重寫(xiě)此方法,接收用戶授權(quán)回調(diào)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        Log.i(TAG, "onRequestPermissionsResult: requestCode =" + requestCode
                +"\n,permissions =" + Arrays.toString(permissions)
                +"\n,grantResults =" + Arrays.toString(grantResults));
        if (requestCode == PERMISSION_REQ_ID){
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
                //用戶同意權(quán)限
            }else {
                //用戶拒絕權(quán)限
            }
        }
    

版本適配

從 Android 6.0 到 Android 10 存儲(chǔ)/訪問(wèn)文件功能,有發(fā)生了很多變化。

Android 7.0 前

在Android 7.0 以前我們?cè)L問(wèn)內(nèi)存中的文件可以通過(guò) Uri.fromFile,將 File 轉(zhuǎn)換成 Uri 對(duì)象,這個(gè) Uri 對(duì)象表示這本地真實(shí)路徑。 訪問(wèn)一個(gè)圖片:

String fileName = "default_Image.jpg";
File file = new File("file_path", fileName);
Uri uri = Uri.fromFile(file);

Android 7.0 后

在 7.0 后,這種通過(guò)真實(shí)路徑來(lái)獲取的 Uri 被認(rèn)為是不安全的,所以提供了一種新的解決方案,就是通過(guò) FileProvide 來(lái)實(shí)現(xiàn)文件的訪問(wèn),F(xiàn)ileProvider 是一種比較特殊的內(nèi)容提供器,他使用了類似于內(nèi)容提供器的機(jī)制來(lái)對(duì)數(shù)據(jù)進(jìn)行保護(hù)。 訪問(wèn)一個(gè)圖片:

    File file = new File(CACHE_IMG, "file_name");
    Uri imageUri = FileProvider.getUriForFile(activity,"com.sandan.fileprovider", file); //這里進(jìn)行替換uri的獲得方式

然而上面這種真的好嗎,對(duì)用開(kāi)發(fā)者而且這算是好處吧,但是對(duì)用用戶而言,上述的無(wú)疑一些流氓作用,因?yàn)殚_(kāi)發(fā)者完全可以訪問(wèn)的內(nèi)存中的所有位置,并作出一些改變,導(dǎo)致 SD 卡中的空間變得非常亂,即使卸載了 app,但是一些垃圾文件卻還在內(nèi)存中。

Android 10.0

在 Android 10.0 ,為了解決上述問(wèn)題,Google 在 Android 10.0 中加入了 作用域功能。

什么是作用域

就是 Android 系統(tǒng)對(duì) SD 卡做了很大的限制,從 Android 10.0 開(kāi)始,每個(gè)程序只能有權(quán)在自己的外置存儲(chǔ)空間關(guān)聯(lián)的目錄下讀取和創(chuàng)建相應(yīng)的文件,也稱作沙箱。獲取該目錄的代碼是:getExternalFilesDir() ,關(guān)聯(lián)的目錄路徑大致如下:

 Html CSS JavaScript Vb vbs Asp PHP Perl Python Ruby C# C++ SQL Delphi Diff Groovy Java JavaFX ActionScript3 Bash/shell powershell Plain Text Scala XML顯示語(yǔ)言名稱 顯示行號(hào) 允許折疊 

將數(shù)據(jù)放在這個(gè)目錄下,你可以使用之前的方法對(duì)文件進(jìn)行讀寫(xiě),不需要作出任何變更和適配。但是這個(gè)文件夾中的文件會(huì)隨著應(yīng)用卸載而被隨之刪除。 那如果需要訪問(wèn)其他目錄怎么辦呢?比如獲取相冊(cè)中的圖片,向相冊(cè)中添加一張圖片。為此,Android 系統(tǒng)針對(duì)系統(tǒng)文件類型進(jìn)行了分類:圖片,音頻,視頻 這三類文件可以通過(guò) MediaStore API 來(lái)進(jìn)行訪問(wèn),這種稱為共享空間,其他的系統(tǒng)文件需要使用 系統(tǒng)的文件選擇器來(lái)進(jìn)行訪問(wèn),另外,如果程序向媒體庫(kù)寫(xiě)入圖片,視頻,音頻,將會(huì)自動(dòng)用于讀寫(xiě)權(quán)限,不需要額外申請(qǐng)權(quán)限,如果你要讀取其他程序向媒體貢獻(xiàn)的圖片,視頻,音頻,則必須要申請(qǐng) READ_EXTERNAL_STORAGE 權(quán)限,WRITE_EXTERNAL_STORAGE 權(quán)限會(huì)在未來(lái)的版本中被廢棄。

舉個(gè)栗子

舉例說(shuō)明:有一張本地圖片,向這張圖片添加水印,并保存到相冊(cè)。

直接上代碼:

    /**
     * 保存圖片到相冊(cè)
     *
     * @param context 上下文
     * @param text 水印文字
     */
    private void savePhotoAlbum(final Context context, final String text) {
        //這里開(kāi)啟子線程,防止堵塞。
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //從本地獲取一張圖片,轉(zhuǎn)成Bitmap
                    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_info);
                    //在沙箱中創(chuàng)建文件,名稱:info.jpg
                    File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "info.jpg");
                    //判斷文件是否存在,不存在創(chuàng)建文件。
                    if (!file.exists()) {
                        file.createNewFile();
                    }
                    // 向圖片添加水印
                    Bitmap newBitmap = addInfoWatermark(context, bitmap, text);
                    // 更新相冊(cè)
                    updatePhotoAlbum(context, newBitmap, file);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start(); //開(kāi)始線程
    }

   /**
     * 保存到相冊(cè)
     *
     * @param context 上下文
     * @param src  源圖片
     * @param text 水印文字
     */
    private Bitmap addInfoWatermark(final Context context, Bitmap src, String text) {
        //判斷圖片/水印文字 是否為空
        if (isEmptyBitmap(src) || text == null ) {
            return null;
        }
        // 從源圖片復(fù)制一份
        Bitmap ret = src.copy(src.getConfig(), true);
        // 初始化畫(huà)筆
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
         // 初始化畫(huà)布
        Canvas canvas = new Canvas(ret);
        // 水印文字:黑色
        paint.setColor(Color.BLACK);
        // 文字大小:19dp
        paint.setTextSize(dip2px(context, 19));
         // 開(kāi)始繪畫(huà)
        canvas.drawText(text, 10, 10 , paint);
        // 循環(huán)利用資源
        if (!src.isRecycled()) {
            src.recycle(); 
        }
        return ret;
    }

    /**
     * 保存到相冊(cè)
     *
     * @param context 上下文
     * @param src  源圖片
     * @param file 要保存到的文件
     */
    private void savePhotoAlbum(final Context context, Bitmap src, final File file) {
        //判斷圖片 是否為空
        if (isEmptyBitmap(src)) {
            return;
        }
        // 保存文件
        OutputStream outputStream;
        try {
            //輸出這個(gè)文件
            outputStream = new BufferedOutputStream(new FileOutputStream(file));
            // 壓縮
            src.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
            // 循環(huán)利用資源
            if (!src.isRecycled()) {
                src.recycle();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // 更新圖庫(kù),這個(gè)在 Android 6.0 和 Android 10.0 更新圖庫(kù),存在差異。
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {  
            // Android 10.0 及以上
            // 創(chuàng)建 ContentValues 對(duì)象,準(zhǔn)備插入數(shù)據(jù)
            ContentValues values = new ContentValues();
            values.put(MediaStore.MediaColumns.DISPLAY_NAME, file.getName());
            values.put(MediaStore.MediaColumns.MIME_TYPE, getMimeType(file));
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
            ContentResolver contentResolver = context.getContentResolver();
            // 插入數(shù)據(jù),返回所插入數(shù)據(jù)對(duì)應(yīng)的Uri
            Uri uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            if (uri == null) {
                return;
            }
            try {
                // 獲取剛插入的數(shù)據(jù)的Uri對(duì)應(yīng)的輸出流
                outputStream = contentResolver.openOutputStream(uri);
                FileInputStream fileInputStream = new FileInputStream(file);
                // 從一個(gè)流復(fù)制到另一個(gè)流上
                FileUtils.copy(fileInputStream, outputStream);
                //關(guān)閉流
                fileInputStream.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            // android 6.0 - 10.0
            // 掃描文件
            MediaScannerConnection.scanFile( context.getApplicationContext(), new String[]{file.getAbsolutePath()}, new String[]{"image/jpeg"},
                    new MediaScannerConnection.OnScanCompletedListener() {
                        @Override
                        public void onScanCompleted(String path, Uri uri) {
                            //通知相冊(cè)更新
                            // 插入圖片
                            MediaStore.Images.Media.insertImage( context.getContentResolver(),  BitmapFactory.decodeFile(path), file.getName(), null);
                            Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                            Uri u = Uri.fromFile(file);
                            intent.setData(u);
                            context.sendBroadcast(intent);  // 發(fā)廣播通知,更新相冊(cè)
                        }
                    });
        }
    }

    /**
     * Bitmap對(duì)象是否為空。
     */
    private static boolean isEmptyBitmap(Bitmap src) {
        return src == null || src.getWidth() == 0 || src.getHeight() == 0;
    }

    /**
     * 獲取 Mime 類型
     *
     * @param file 文件
     * @return Mime 類型
     */
    private static String getMimeType(File file) {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        String type = fileNameMap.getContentTypeFor(file.getName());
        return type;
    }

    /**
     * 根據(jù)手機(jī)的分辨率從 px(像素) 的單位 轉(zhuǎn)成為 dp
     */
    public int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

以上就是Android 版本、權(quán)限適配相關(guān)總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Android 版本、權(quán)限適配的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論