【基礎(chǔ)筆記】Android Studio拍照相味、選擇相冊(系統(tǒng)原生方式)

一、前言

引用《第一行代碼》8.3調(diào)用攝像頭和相冊

二殉挽、調(diào)用攝像頭

1丰涉、Android7.0之后加入了provider拓巧,首先Android Studio中添加provider的相關(guān)代碼。
  • 在AndroidManifest注冊provider
  <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".TakeAPhoto">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.administrator.drawable.fileprovider"http://自己的包名.fileprovider
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

    </application>
  • 創(chuàng)建file_paths.xml文件:res-->xml(新建)-->file.paths(新建)一死。
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="" />
</paths>

注:空值就表示將整個SD卡進(jìn)行共享肛度,當(dāng)然也可以僅共享我們存放output_image.jpg這張圖片的路徑。

2投慈、相機(jī)拍照需要獲取寫入內(nèi)存的權(quán)限贤斜,在AndroidManifest中添加權(quán)限。在調(diào)用相機(jī)時詢問并獲取權(quán)限逛裤。
  • 添加權(quán)限
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.cameraalbumtest">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
  • 詢問并獲取權(quán)限
             if (ContextCompat.checkSelfPermission(TakeAPhoto.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(TakeAPhoto.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
              } else {
                    takePhoto();
                }
  • 重寫獲取權(quán)限的結(jié)果,進(jìn)行相關(guān)操作
 @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 1) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.
                    PERMISSION_GRANTED) {
                //需要進(jìn)行的操作
            } else {
                Toast.makeText(TakeAPhoto.this, "您取消了申請權(quán)限", Toast.LENGTH_LONG).show();
            }
        }
    }
3猴抹、調(diào)用相機(jī)的相關(guān)代碼带族。
public class TakeAPhoto extends AppCompatActivity {
    public static final int TAKE_PHOTO = 1;
    private ImageView picture;
    private Uri imageUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.take_a_photo);
        final Button takePhoto = (Button) findViewById(R.id.take_photo);
        picture = (ImageView) findViewById(R.id.picture);
        takePhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //  獲取權(quán)限
                if (ContextCompat.checkSelfPermission(TakeAPhoto.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(TakeAPhoto.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
                } else {
                    takePhoto();
                }
            }
        });
    }


    private void takePhoto() {
        // 創(chuàng)建File對象,用于存儲拍照后的圖片蟀给◎觯可根據(jù)自己需求創(chuàng)建對應(yīng)的文件夾
        File outputImage = new File(getExternalCacheDir(),
                "output_image.jpg");//這里可以用當(dāng)前時間戳來命名。 System.currentTimeMillis() + ".jpg" ;
        try {
            if (outputImage.exists()) {
                outputImage.delete();
            }
            outputImage.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (Build.VERSION.SDK_INT >= 24) {
            imageUri = FileProvider.getUriForFile(TakeAPhoto.this,
                    "com.example.administrator.drawable.fileprovider", outputImage);
        } else {
            imageUri = Uri.fromFile(outputImage);
        }
        // 啟動相機(jī)程序
        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        startActivityForResult(intent, TAKE_PHOTO);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case TAKE_PHOTO:
                if (resultCode == RESULT_OK) {
                    try {
                        // 將拍攝的照片顯示出來
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
                        picture.setImageBitmap(bitmap);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 1) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.
                    PERMISSION_GRANTED) {
                takePhoto();
            } else {
                Toast.makeText(TakeAPhoto.this, "您取消了申請權(quán)限", Toast.LENGTH_LONG).show();
            }
        }
    }
}

打開相機(jī)思路:添加Provider跋理,添加權(quán)限择克,調(diào)用相機(jī)打開拍照,打開前判斷手機(jī)版本是否高于23(7.0)前普,獲取對應(yīng)的Uri肚邢。在進(jìn)行操作,在重寫的返回結(jié)果中顯示圖片

三拭卿、打開相冊

1骡湖、獲取權(quán)限(AndroidManifest中申明,在打開相冊前詢問并授權(quán))峻厚,同上
2响蕴、打開相冊相關(guān)代碼
public class TakeAPhoto extends AppCompatActivity {
    public static final int TAKE_PHOTO = 1;
    public static final int CHOOSE_PHOTO = 2;
    private ImageView picture;
    private Uri imageUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.take_a_photo);
        .....
        Button chooseFromAlbum = (Button) findViewById(R.id.choose_from_album);
        .....

        chooseFromAlbum.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ContextCompat.checkSelfPermission(TakeAPhoto.this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.
                        PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(TakeAPhoto.this, new
                            String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
                } else {
                    openAlbum();
                }
            }
        });
    }


    private void openAlbum() {
        Intent intent = new Intent("android.intent.action.GET_CONTENT");
        intent.setType("image/*");
        startActivityForResult(intent, CHOOSE_PHOTO); // 打開相冊
    }

   ..........

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case TAKE_PHOTO:
                if (resultCode == RESULT_OK) {
                    try {
                        // 將拍攝的照片顯示出來
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
                        picture.setImageBitmap(bitmap);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                break;
            case CHOOSE_PHOTO:
                if (requestCode == RESULT_OK) {
                    // 判斷手機(jī)系統(tǒng)版本號
                    if (Build.VERSION.SDK_INT >= 19) {
                        // 4.4及以上系統(tǒng)使用這個方法處理圖片
                        handleImageOnKitKat(data);
                    } else {
                        // 4.4以下系統(tǒng)使用這個方法處理圖片
                        handleImageBeforeKitKat(data);
                    }

                }
                break;
            default:
                break;
        }
    }

    @TargetApi(19)
    private void handleImageOnKitKat(Intent data) {
        String imagePath = null;
        Uri uri = data.getData();
        if (DocumentsContract.isDocumentUri(this, uri)) {
            // 如果是document類型的Uri,則通過document id處理
            String docId = DocumentsContract.getDocumentId(uri);
            if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                String id = docId.split(":")[1]; // 解析出數(shù)字格式的id
                String selection = MediaStore.Images.Media._ID + "=" + id;
                imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
            } else if ("com.android.providers.downloads.documents".equals(uri.
                    getAuthority())) {
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
                        imagePath = getImagePath(contentUri, null);
            }
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // 如果是content類型的Uri惠桃,則使用普通方式處理
            imagePath = getImagePath(uri, null);
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            // 如果是file類型的Uri浦夷,直接獲取圖片路徑即可
            imagePath = uri.getPath();
        }
        displayImage(imagePath); // 根據(jù)圖片路徑顯示圖片
    }

    private void handleImageBeforeKitKat(Intent data) {
        Uri uri = data.getData();
        String imagePath = getImagePath(uri, null);
        displayImage(imagePath);
    }

    private String getImagePath(Uri uri, String selection) {
        String path = null;
        // 通過Uri和selection來獲取真實(shí)的圖片路徑
        Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                path = cursor.getString(cursor.getColumnIndex(MediaStore.
                        Images.Media.DATA));
            }
            cursor.close();
        }
        return path;
    }

    private void displayImage(String imagePath) {
        if (imagePath != null) {
            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
            picture.setImageBitmap(bitmap);
        } else {
            Toast.makeText(this, "failed to get image", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 1) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.
                    PERMISSION_GRANTED) {
//                takePhoto();
                openAlbum();
            } else {
                Toast.makeText(TakeAPhoto.this, "您取消了申請權(quán)限", Toast.LENGTH_LONG).show();
            }
        }
    }
}

思路:先添加權(quán)限,通過Intent打開相冊選取照片辜王,選擇照片后判斷手機(jī)版本是否低于4.4劈狐,在重寫的返回結(jié)果中使用對應(yīng)的方法進(jìn)行操作(不用provider)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呐馆,一起剝皮案震驚了整個濱河市懈息,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌摹恰,老刑警劉巖辫继,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怒见,死亡現(xiàn)場離奇詭異,居然都是意外死亡姑宽,警方通過查閱死者的電腦和手機(jī)遣耍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來炮车,“玉大人舵变,你說我怎么就攤上這事∈菽拢” “怎么了纪隙?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長扛或。 經(jīng)常有香客問我绵咱,道長,這世上最難降的妖魔是什么熙兔? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任悲伶,我火速辦了婚禮,結(jié)果婚禮上住涉,老公的妹妹穿的比我還像新娘麸锉。我一直安慰自己,他們只是感情好舆声,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布花沉。 她就那樣靜靜地躺著,像睡著了一般媳握。 火紅的嫁衣襯著肌膚如雪主穗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天毙芜,我揣著相機(jī)與錄音忽媒,去河邊找鬼。 笑死腋粥,一個胖子當(dāng)著我的面吹牛晦雨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播隘冲,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼闹瞧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了展辞?” 一聲冷哼從身側(cè)響起奥邮,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后洽腺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脚粟,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年蘸朋,在試婚紗的時候發(fā)現(xiàn)自己被綠了核无。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡藕坯,死狀恐怖团南,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情炼彪,我是刑警寧澤同木,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布酸员,位于F島的核電站乒验,受9級特大地震影響拙寡,放射性物質(zhì)發(fā)生泄漏躯护。R本人自食惡果不足惜葛假,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一债热、第九天 我趴在偏房一處隱蔽的房頂上張望形真。 院中可真熱鬧旭咽,春花似錦贞奋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至仲墨,卻和暖如春勾缭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背目养。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工俩由, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人癌蚁。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓幻梯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親努释。 傳聞我的和親對象是個殘疾皇子碘梢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評論 2 361