小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

適配Android10 拍照,相冊,裁剪,上傳圖片

 頭號碼甲 2021-12-13

  這篇文章主要介紹了適配Android 10(Q)后,調(diào)用系統(tǒng)拍照,系統(tǒng)相冊,系統(tǒng)裁剪和上傳問題,這是一個(gè)很常用的功能,但是在Android 6.0,Android 7.0和Android 10.0以上版本的實(shí)現(xiàn)都有所不同,這篇文章從Android 4適配到Android 10。

  之前寫畢設(shè)的時(shí)候,在寫上傳頭像的功能時(shí),參考網(wǎng)上的方法寫了一大堆,在我的手機(jī)(Android 9)上可以正常運(yùn)行,當(dāng)時(shí)沒多想,以為高版本可以向下兼容,后來我把程序發(fā)給同學(xué)去試驗(yàn),結(jié)果都告訴我上傳頭像用不了,一問才知道他們用的是Android 10的手機(jī),于是只能上網(wǎng)查找原因,然后發(fā)現(xiàn)Android 10的存儲(chǔ)方式發(fā)生了變化,Android 10的文件系統(tǒng)采用了沙盒文件系統(tǒng),最顯著的變化就是文件系統(tǒng)變安全了,于是app也沒辦法拿到外部文件的絕對路徑了,網(wǎng)上給出的方法就是將共享文件復(fù)制到沙盒目錄下,然后再進(jìn)行文件操作。話不多說,上代碼。

  demo源碼

在文件清單AndroidManifest.xml中添加權(quán)限:

1 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><!-- 儲(chǔ)存卡的讀權(quán)限 -->2 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!-- 儲(chǔ)存卡的寫權(quán)限 -->3 <uses-permission android:name="android.permission.CAMERA" /><!-- 調(diào)用相機(jī)權(quán)限 -->

在官方7.0的以上的系統(tǒng)中,嘗試傳遞 file://URI可能會(huì)觸發(fā)FileUriExposedException,使用FileProvider來共享文件,AndroidManifest.xml:

<application
        ...
        <!-- 兼容Android7.0拍照閃退 -->
        <provider            android:name="androidx.core.content.FileProvider"
            android:authorities="com.example.camera.test"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
    </application>

在主界面放一個(gè)ImageView和兩個(gè)按鈕,activity_main.xml:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas./apk/res/android"
    xmlns:tools="http://schemas./tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ImageView        android:id="@+id/image"
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:layout_marginTop="20dp"
        android:layout_gravity="center_horizontal"/>

    <TextView        android:id="@+id/tv_camera"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:text="相機(jī)"
        android:textSize="18sp"
        android:textColor="#FFF"
        android:padding="10dp"
        android:background="#1878FF"
        android:layout_marginHorizontal="20dp"
        android:gravity="center_horizontal"/>

    <TextView        android:id="@+id/tv_album"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:text="相冊"
        android:textSize="18sp"
        android:textColor="#FFF"
        android:padding="10dp"
        android:background="#1878FF"
        android:layout_marginHorizontal="20dp"
        android:gravity="center_horizontal"/></LinearLayout>

接下來是主頁面的代碼:

獲取控件,對兩個(gè)按鈕添加點(diǎn)擊監(jiān)聽,判斷權(quán)限:

    
    private ImageView image;
    private TextView tvCamera, tvAlbum;
    @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init(){ image = findViewById(R.id.image); tvCamera = findViewById(R.id.tv_camera); tvAlbum = findViewById(R.id.tv_album); tvCamera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //相機(jī) if ((ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) { //權(quán)限都齊的情況下,跳轉(zhuǎn)相機(jī) openCamera(); } else { if (activity != null) { //請求權(quán)限 ActivityCompat.requestPermissions(activity, new String[]{ Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE }, PHOTO_REQUEST_CAMERA); } } } }); tvAlbum.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //相冊 if ((ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) { //權(quán)限都齊的情況下,跳轉(zhuǎn)相冊 openAlbum(); } else { if (activity != null) { //請求權(quán)限 ActivityCompat.requestPermissions(activity, new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE }, PHOTO_REQUEST_ALBUM); } } } }); }

權(quán)限申請回調(diào):

    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        switch (requestCode) {            case PHOTO_REQUEST_CAMERA:                //相機(jī)權(quán)限請求回調(diào)
                if (grantResults.length > 0) {                    if (grantResults[0] == PackageManager.PERMISSION_GRANTED                            && grantResults[1] == PackageManager.PERMISSION_GRANTED                            && grantResults[2] == PackageManager.PERMISSION_GRANTED) {                        //跳轉(zhuǎn)相機(jī)                        openCamera();
                    } else {                        //無權(quán)限提示
                        Toast.makeText(context, "權(quán)限未通過", Toast.LENGTH_SHORT).show();
                    }
                }                break;            case PHOTO_REQUEST_ALBUM:                if (grantResults.length > 0) {                    if (grantResults[0] == PackageManager.PERMISSION_GRANTED                            && grantResults[1] == PackageManager.PERMISSION_GRANTED) {                        //跳轉(zhuǎn)相冊                        openAlbum();
                    } else {                        //無權(quán)限提示
                        Toast.makeText(context, "權(quán)限未通過", Toast.LENGTH_SHORT).show();
                    }
                }                break;
        }
    }

跳轉(zhuǎn)相機(jī):

 = 
         (activity !=  && context !=  && intent.resolveActivity(activity.getPackageManager()) != = 
                uri =
                file = (file != 
                     (Build.VERSION.SDK_INT >=
                        uri = FileProvider.getUriForFile(context, "com.example.camera.test"=="相機(jī)保存的圖片Uri:" + (uri !=

Android 10以上的創(chuàng)建Uri,Uri創(chuàng)建在沙盒內(nèi):

contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/0/");

以上設(shè)置的保存路徑為:".../包名/files/Pictures/0",可按需更改

用于保存拍照之后的照片:

    private Uri createImageUri(@NonNull Context context){
        String status = Environment.getExternalStorageState();
        ContentValues contentValues = new ContentValues();
        contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, SAVE_AVATAR_NAME);
        contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/*");
        contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/0/");        //判斷是否有SD卡
        if (status.equals(Environment.MEDIA_MOUNTED)){            return context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
        } else {            return context.getContentResolver().insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, contentValues);
        }
    }

Android 10以下的返回一個(gè)file來保存拍照后的圖片:

    private File createImageFile(@NonNull Context context){
        File file = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);        if (file != null && !file.exists()){            if (file.mkdir()){
                Log.e(TAG, "文件夾創(chuàng)建成功");
            } else {
                Log.e(TAG, "file為空或者文件夾創(chuàng)建失敗");
            }
        }
        File tempFile = new File(file, SAVE_AVATAR_NAME);
        Log.e(TAG, "臨時(shí)文件路徑:" + tempFile.getAbsolutePath());        if (!Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(tempFile))){            return null;
        }        return tempFile;
    }

跳轉(zhuǎn)相冊:

    private void openAlbum(){
        Intent intent = new Intent(Intent.ACTION_PICK, null);
        intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
        startActivityForResult(intent, ALBUM_REQUEST_CODE);
    }

跳轉(zhuǎn)裁剪,裁剪在相機(jī)拍照后跳轉(zhuǎn),用一個(gè)file來加載:

private void openCrop(Uri uri){        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && context != null){
            file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES + "/0"), SAVE_AVATAR_NAME);
        }
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        intent.setDataAndType(uri, "image/*");        // 設(shè)置裁剪
        intent.putExtra("crop", "true");        // aspectX aspectY 是寬高的比例
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);        // 裁剪后輸出圖片的尺寸大小
        intent.putExtra("outputX", 250);
        intent.putExtra("outputY", 250);        //適配Android10,存放圖片路徑        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));        // 圖片格式
        intent.putExtra("outputFormat", "PNG");
        intent.putExtra("noFaceDetection", true);// 取消人臉識別
        intent.putExtra("return-data", true);// true:不返回uri,false:返回uri        startActivityForResult(intent, TAILOR_REQUEST_CODE);
    }

跳轉(zhuǎn)相機(jī)、相冊和裁剪的回調(diào),如果有上傳需求的,直接上傳代碼中的file即可:

    @Override    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {        super.onActivityResult(requestCode, resultCode, data);        if (resultCode == -1){            //回調(diào)成功
            switch (requestCode) {                case CAMERA_REQUEST_CODE:                    //相機(jī)回調(diào)
                    Log.e(TAG, "相機(jī)回調(diào)");                    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {                        //照片裁剪                        openCrop(imageUri);
                    } else {
                        Toast.makeText(context, "未找到存儲(chǔ)卡", Toast.LENGTH_SHORT).show();
                    }                    break;                case ALBUM_REQUEST_CODE:                    //相冊回調(diào)
                    Log.e(TAG, "相冊回調(diào)");                    if (data != null && data.getData() != null) {
                        image.setImageURI(data.getData());                        //如果需要上傳操作的可以使用這個(gè)方法
                        File file = FileUtils.uriToFile(data.getData(), context);                        //這里的file就是需要上傳的圖片了                    }                    break;                case TAILOR_REQUEST_CODE:                    //圖片剪裁回調(diào)
                    Log.e(TAG, "圖片剪裁回調(diào)");//                    Glide.with(context).load(file).into(image);
                    Uri uri = Uri.fromFile(file);
                    image.setImageURI(uri);                    //如果需要上傳全局的這個(gè)file就是需要上傳的圖片了
                    File file = this.file;                    break;
            }
        } else {
            Toast.makeText(context, "取消", Toast.LENGTH_SHORT).show();
        }
    }

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多