Android筆記——調用系統相機並保存到指定地址

系統相機折騰了我兩天。。。。
本來我是照着視頻學的,然鵝出了好幾個問題,一會是指定的圖片路徑不行,一會又是調用相機後點擊確認沒反應,真的是頭疼
經過仔細查閱資料,我發現,因爲Android在API24以後對訪問權限回收,也就是說,用一個app調用另一個app,第二個app是沒有第一個app調用的文件夾的讀寫權限的。。。自從API23之後真是越來越安全了呢。。。。。
所以,需要向系統相機發送 content://URI,並授予 URI 臨時訪問權限。而進行此授權的最簡單方式是使用 FileProvider類。

步驟如下:

1.在AndroidManifest.xml中加入FileProvider註冊

        <provider
            android:authorities="包名.fileprovider"
            android:name="android.support.v4.content.FileProvider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths"/>
        </provider>

在這裏插入圖片描述

2.配置filepaths文件

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <!-- external-path:sd ;path:你的應用保存文件的根目錄;name隨便定義-->
    <!-- root-path 手機存儲根目錄 -->
    <root-path path="" name="posture" />
</paths>

在這裏插入圖片描述

3.調用相機代碼

public class MainActivity extends AppCompatActivity {
    private static int REQ_1=1;
    private static int REQ_2=2;
    private ImageView mImageView;
    private String mFilePath;
    private String mFileName;
    Button camera2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        camera2 = findViewById(R.id.camerabutton2);
        saveInRoot();//這個函數是檢測路徑用的

        mImageView = findViewById(R.id.iv);
        mFilePath = Environment.getExternalStorageDirectory().getPath();
        mFilePath = mFilePath+"/postureTemp/";

//        Uri photoUri = Uri.parse(mFilePath);
//
//        String path = getSDPath();

        camera2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                jump2Camera();
            }
        });
    }

	// 這是另一個按鈕調用相機的,只能在view裏顯示縮略圖
    public void startCamera(View view){
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(intent,REQ_1);
    }


    public void jump2Camera() {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            File path = new File(mFilePath);
            if (!path.exists()) {
                path.mkdirs();
            }
            mFileName = System.currentTimeMillis() + ".jpg";
            File file = new File(path, mFileName);
            if (file.exists()) {
                file.delete();
            }

//            FileUtils.startActionCapture(this,file,REQ_2);
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, getUriForFile(this, file));
            startActivityForResult(intent, REQ_2);

        } else {
            Log.e("main","sdcard not exists");
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == RESULT_OK){
            if(requestCode == REQ_1){
                Bundle bundle = data.getExtras();
                Bitmap bitmap = (Bitmap) bundle.get("data");
                mImageView.setImageBitmap(bitmap);
            }
            else if(requestCode == REQ_2){
                FileInputStream fis = null;
                Toast.makeText(MainActivity.this, "拍完了...", Toast.LENGTH_SHORT).show();
				// 將圖片展示在imageView裏
                try{
                    fis = new FileInputStream(mFilePath+mFileName);
                    Bitmap bitmap = BitmapFactory.decodeStream(fis);
                    mImageView.setImageBitmap(bitmap);
                }catch (FileNotFoundException e){
                    e.printStackTrace();
                }finally {
                    try{
                        fis.close();
                    }
                    catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public static Uri getUriForFile(Context context, File file) {
        if (context == null || file == null) {
            throw new NullPointerException();
        }
        Uri uri;
        if (Build.VERSION.SDK_INT >= 24) {
            uri = FileProvider.getUriForFile(context.getApplicationContext(), "com.example.posturer.fileprovider", file);
            Log.e("qq", "外部存儲可用..." + uri.toString());
        } else {
            uri = Uri.fromFile(file);
        }
        return uri;
    }


    public String getSDPath() {
        File sdDir = null;
        //判斷sd卡是否存在
        boolean sdCardExist = Environment.getExternalStorageState()
                .equals(android.os.Environment.MEDIA_MOUNTED);
        if (sdCardExist) {
            sdDir = Environment.getExternalStorageDirectory();//獲取根目錄
            Log.e("qq", "外部存儲可用..." + sdDir.toString());
//            Toast.makeText(MainActivity.this, "外部存儲可用...", Toast.LENGTH_SHORT).show();
        }else {
            Toast.makeText(MainActivity.this, "外部存儲不可用...", Toast.LENGTH_SHORT).show();
        }
        return sdDir.toString();
    }
    //使用
    private void saveInRoot() {
        if (getSDPath()!=null) {
            String fileName = getSDPath() + "/";
            File file = new File(fileName,"postureTemp");//參數
            if (!file.mkdir()) {
//            Toast.makeText(MainActivity.this, "目錄已存在...", Toast.LENGTH_SHORT).show();
            } else {
//            Toast.makeText(MainActivity.this, "創建新目錄...", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

4.別忘了申請權限

	<uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />

PS

還有一個採坑點,就是按鈕的點擊事件不要放佈局文件裏,最好使用setOnClickListener監聽器,更好使~

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