android相機(jī)拍照的編碼實(shí)現(xiàn)

本篇在android手機(jī)上調(diào)用攝像頭拍照。
新建項(xiàng)目MyCameraAlbum,然后修改activity_main.xml中的代碼。

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

    <Button
        android:id="@+id/button_take_photo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAllCaps="false"
        android:text="Tack Photo"/>
    <ImageView
        android:id="@+id/photo_pictrue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

</LinearLayout>

布局中只有兩個(gè)控件,一個(gè)Button,一個(gè)ImageView。Button是打開攝像頭的按鈕,ImageView則是用來(lái)顯示拍到的圖片。
調(diào)用攝像頭的具體邏輯,修改MainActivity中的代碼:

public class MainActivity 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.activity_main);

        Button btnTakePhoto = (Button) findViewById(R.id.button_take_photo);    //按鈕
        picture = (ImageView) findViewById(R.id.photo_pictrue);                 //圖片控件,用來(lái)顯示照片的。

        btnTakePhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //創(chuàng)建File對(duì)象,用于存儲(chǔ)拍照后的圖片
                File outputImage = new File(getExternalCacheDir(), "output_image.jpg");
                try {
                    if (outputImage.exists()) {
                        outputImage.delete();
                    }
                    outputImage.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //android 7.0版本以下的系統(tǒng),直接Uri.fromFile取得真實(shí)文件路徑;7.0及以上版本的系統(tǒng),使用fileprovider封裝過(guò)的Uri再提供出去。
                if (Build.VERSION.SDK_INT >= 24) {
                    imageUri = FileProvider.getUriForFile(MainActivity.this, "com.cofox.mycameraalbum.fileprovider", outputImage);
                } else {
                    imageUri = Uri.fromFile(outputImage);
                }
                //啟動(dòng)相機(jī)程序
                Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
                intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                startActivityForResult(intent, TAKE_PHOTO);     //啟動(dòng)Intent活動(dòng),拍完照會(huì)有結(jié)果返回到onActivityResult()方法中。
            }
        });
    }

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

                }
                break;
            default:
                break;
        }
    }
}

這段代碼,首先分別獲取到Button和ImageView的實(shí)例,并給Button注冊(cè)點(diǎn)擊事件。在點(diǎn)擊事件里開始處理調(diào)用攝像頭的邏輯。
首先創(chuàng)建一個(gè)File對(duì)象,用戶存儲(chǔ)攝像頭拍下的圖片。這里命名圖片名稱為outout_image.jpg,并將它存放在手機(jī)應(yīng)用關(guān)聯(lián)緩存目錄下。
應(yīng)用關(guān)聯(lián)緩存目錄是指專門用于存放當(dāng)前應(yīng)用緩存數(shù)據(jù)的位置,調(diào)用getExternalCacheDir()方法可以得到這個(gè)目錄。具體路徑是/sdcard/Android/data/<package name>/cache。
之所以使用應(yīng)用緩存來(lái)存放圖片,是因?yàn)閺腶ndroid 6.0系統(tǒng)開始,讀寫SD卡被列為了危險(xiǎn)權(quán)限,圖片要存放在SD卡的任何其他目錄,都要進(jìn)行運(yùn)行時(shí)權(quán)限處理,而使用應(yīng)用關(guān)聯(lián)目錄則可以跳過(guò)這一步。

if (Build.VERSION.SDK_INT >= 24) {
                    imageUri = FileProvider.getUriForFile(MainActivity.this, "com.cofox.mycameraalbum.fileprovider", outputImage);
                } else {
                    imageUri = Uri.fromFile(outputImage);
                }

這段代碼,是根據(jù)當(dāng)前android系統(tǒng)的版本,提供不同的Uri。
android 7.0一下版本,使用真實(shí)文件路徑。

Uri.fromFile(outputImage)

7.0及以上版本的系統(tǒng),使用fileprovider封裝過(guò)的Uri再提供出去。

FileProvider.getUriForFile(MainActivity.this, "com.cofox.mycameraalbum.fileprovider", outputImage)

FileProvider是一種特殊的內(nèi)容提供器,使用了內(nèi)容提供器類似的機(jī)制來(lái)對(duì)數(shù)據(jù)進(jìn)行保護(hù),可以選擇性地將封裝過(guò)的Uri共享給外部,從而提高了安全性。
之后構(gòu)建一個(gè)Intent對(duì)象,并將這個(gè)Intent的action指定為android.media.action.IMAGE_CAPTURE,再調(diào)用Intent的putExtra()指定圖片的輸出地址,這里填入剛剛得到的Uri對(duì)象。最后startActivityForResult()來(lái)啟動(dòng)活動(dòng)。

startActivityForResult(intent, TAKE_PHOTO); 

使用startActivityForResult()來(lái)啟動(dòng)活動(dòng)的,拍照結(jié)束會(huì)有結(jié)果返回onActivityResult()。
如果拍照成功

resultCode == RESULT_OK

調(diào)用BitmapFactory的decodeStream()方法將output_image.jpg解析成Bitmap對(duì)象,然后設(shè)置到ImageView中顯示出來(lái)。

代碼中使用的內(nèi)容提供器,必須在AndroidManifest.xml中對(duì)內(nèi)容提供器進(jìn)行注冊(cè)。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.cofox.mycameraalbum">

    <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=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <provider
            android:authorities="com.cofox.mycameraalbum.fileprovider"
            android:name="android.support.v4.content.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
    </application>

</manifest>

在android:authorities屬性的值必須和剛才FileProvider.getUrlFile()方法中的第二個(gè)參數(shù)一致。
<provider>標(biāo)簽的內(nèi)部使用<meta-date>來(lái)指定Url的共享路徑,并引用了一個(gè)@xml/file_paths資源。這個(gè)資源現(xiàn)在還不存在,馬上創(chuàng)建。

右擊res目錄->New->Directory,創(chuàng)建一個(gè)xml目錄;右擊這個(gè)xml目錄->New->File,創(chuàng)建file_paths.xml文件。然后修改file-paths.xml為下面代碼:

<?xml version="1.0" encoding="utf-8"?>

    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-path name="my_images" path="" />
    </paths>

這里的extenal-path是用來(lái)指定Uri共享的。path屬性的值就是表示共享的具體路徑。當(dāng)前為空的設(shè)置,表示將整個(gè)SD卡進(jìn)行共享。
最后一點(diǎn)要注意的,如果是古老的android 4.4之前的系統(tǒng),訪問SD卡的應(yīng)用關(guān)聯(lián)目錄要聲明權(quán)限。android 4.4不需要聲明。為了兼容那些老版本的系統(tǒng),在AndroidManifest.xml中聲明SD的訪問權(quán)限。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
點(diǎn)擊按鈕拍照
拍照成功之后的狀態(tài)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容