1. 程式人生 > >實現開啟Android系統相簿、照相機並實現照相,錄影功能。

實現開啟Android系統相簿、照相機並實現照相,錄影功能。

通過本篇部落格,你將學到以下知識點: 
1.學會如何開啟Android系統中相簿的圖片,視訊,並使用這些圖片,視訊。 
2.學會如何打Android開照相機進行照相,錄影,並使用這樣圖片和視訊。 
下面我將展示兩種方法來實現這些需求,注意:以下程式碼要用真機測試才行。 
一. 第一種方法: 

①.想順利的開啟Android手機中的相簿和照相機,首先我們要在清單中註冊一些許可權:

 <!--使用相機硬體的許可權-->
    <uses-permission android:name="android.permission.CAMERA"/>
    <!--錄音的許可權-->
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <!--過濾不支援相機的裝置-->
    <uses-feature android:name="android.hardware.Camera"/>


 
②.MainActivity的程式碼:
 

/**
 * 通過相機拍照返回的Bitmap有兩種方式:
 * 1.不傳入MediaStore.EXTRA_OUTPUT時,直接由data返回一個縮圖
 * 2.當傳入MediaStore.EXTRA_OUTPUT時,可以通過設定的圖片儲存路徑來獲取完整圖片
 */
public class MainActivity extends AppCompatActivity {

    private ImageView iv;

    private VideoView videoView;

    private final static int FLAG_REQUEST_SYSTEM_IMAGE = 0;

    private final static int FLAG_REQUEST_CAMERA_IMAGE = 1;

    private final static int FLAG_REQUEST_CAMERA_VIDEO = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv = (ImageView) findViewById(R.id.iv);
        videoView = (VideoView) findViewById(R.id.video);
    }

    public void doclick(View view) {
        switch (view.getId()) {
            case R.id.btn_pick_imager:
                // TODO 選取系統相簿圖片
                doPickImageFromSystem();
                break;
            case R.id.btn_open_pick_imager:
                // TODO 開啟相機拍照
                doOpenCameraForImage();
                break;
            case R.id.btn_open_pick_video:
                // TODO 開啟相機錄影
                doOpenCameraForVideo();
                break;
        }
    }

    private void doPickImageFromSystem() {
        /**
         * 引數一:開啟系統相簿的ACTION
         * 引數二:返回資料的方式(從系統相簿的資料庫獲取)
         */
        Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(intent, FLAG_REQUEST_SYSTEM_IMAGE);
    }

    private void doOpenCameraForImage() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        //todo 僅當設定了MediaStore.EXTRA_OUTPUT引數時,系統將不再返回縮圖,而是會被完整儲存以下路徑
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File("/sdcard/test.jpg")));

        startActivityForResult(intent,FLAG_REQUEST_CAMERA_IMAGE);
    }

    private void doOpenCameraForVideo() {
        Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File("/sdcard/test.mp4")));
        startActivityForResult(intent, FLAG_REQUEST_CAMERA_VIDEO);
    }

    //TODO onActivityResul該方法根據requestCode返回碼進行判斷和處理資料
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        //當結果碼為RESULT_OK時,表示使用者有效
        if (resultCode == RESULT_OK) {
            Log.i("info", "確認使用者操作");
            switch (requestCode) {
                case FLAG_REQUEST_SYSTEM_IMAGE:
                    //TODO 處理從相簿返回的圖片資料
                    Uri uri = data.getData();//使用getData方法獲取要呼叫的介面
                    //第二個引數表示要查詢的資料的欄位名
                    Cursor c = getContentResolver().query(uri, new String[]{MediaStore.Images.Media.DATA}, null, null, null);
                    if (c != null) {
                        c.moveToFirst();
                        //通過遊標來獲取名為MediaStore.Images.Media.DATA欄位的值
                        String path = c.getString(c.getColumnIndex(MediaStore.Images.Media.DATA));
                        iv.setImageBitmap(BitmapFactory.decodeFile(path));
                    }
                    break;
                case FLAG_REQUEST_CAMERA_IMAGE:
                    //TODO 處理從相機返回的圖片資料
                    if (data != null) {
                        Bitmap bm = data.getParcelableExtra("data");
                        iv.setImageBitmap(bm);
                    } else {
                        Bitmap bm = BitmapFactory.decodeFile("/sdcard/test.jpg");
                        iv.setImageBitmap(bm);
                    }
                    break;
                case FLAG_REQUEST_CAMERA_VIDEO:
                    //TODO 處理從相機返回的視訊資料
                    videoView.setVideoURI(Uri.parse("/sdcard/test.mp4"));
                    videoView.start();
                    break;
            }
        } else {
            Log.i("info", "取消使用者操作");
        }
    }
}
 


 
③佈局xml檔案:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   android:orientation="vertical">
    <Button
        android:id="@+id/btn_pick_imager"
        android:onClick="doclick"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="選取系統相簿"/>
    <Button
        android:id="@+id/btn_open_pick_imager"
        android:onClick="doclick"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="開啟相機拍照"/>
    <Button
        android:id="@+id/btn_open_pick_video"
        android:onClick="doclick"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="開啟相機錄影"
       />

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:id="@+id/iv"/>
    <VideoView
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:id="@+id/video"/>
</LinearLayout>

第二種方法:這種方法主要是使用CameraUtils這個工具類,因為這個工具類封裝了這些繁瑣的方法,有了這個工具類,程式碼量將減少很多,想實現這些業務的話只要呼叫CameraUtils這個工具類即可。 

①。第一步還是註冊許可權:

 <!--使用相機硬體的許可權-->
    <uses-permission android:name="android.permission.CAMERA"/>
    <!--錄音的許可權-->
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <!--過濾不支援相機的裝置-->
    <uses-feature android:name="android.hardware.Camera"/>


②MainActivity的程式碼:

/**
 * 通過相機拍照返回的Bitmap有兩種方式:
 * 1.不傳入MediaStore.EXTRA_OUTPUT時,直接由data返回一個縮圖
 * 2.當傳入MediaStore.EXTRA_OUTPUT時,可以通過設定的圖片儲存路徑來獲取完整圖片
 */
public class MainActivity extends AppCompatActivity {

    private ImageView iv;

    private VideoView videoView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv = (ImageView) findViewById(R.id.iv);
        videoView = (VideoView) findViewById(R.id.video);
    }

    public void doClick(View view) {
        switch (view.getId()) {
            case R.id.btn_pick_image:
                // TODO 選取系統相簿圖片
                doPickImageFromSystem();
                break;
            case R.id.btn_open_camera_for_image:
                // TODO 開啟相機拍照
                doOpenCameraForImage();
                break;
            case R.id.btn_open_camera_for_video:
                // TODO 開啟相機錄影
                doOpenCameraForVideo();
                break;
        }
    }

    private void doPickImageFromSystem() {
        /**
         * 引數一:開啟系統相簿的ACTION
         * 引數二:返回資料的方式(從系統相簿的資料庫獲取)
         */
        CameraUtils.pickImageFromSystem(this);
    }

    private void doOpenCameraForImage() {

        CameraUtils.openCameraForImage(this);
    }

    private void doOpenCameraForVideo() {

        CameraUtils.openCameraForVideo(this);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        //當結果碼為RESULT_OK時,表示使用者有效
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
                case CameraUtils.RequestCode.FLAG_REQUEST_SYSTEM_IMAGE:

                    String path = CameraUtils.getImagePathFromSystem(this, data);
                    if (path != null) {
                        iv.setImageBitmap(BitmapFactory.decodeFile(path));
                    }
                    break;
                case CameraUtils.RequestCode.FLAG_REQUEST_CAMERA_IMAGE:
                    //TODO 處理從相機返回的圖片資料
                    if (data != null) {
                        Bitmap bm = data.getParcelableExtra("data");

                        iv.setImageBitmap(bm);
                    } else {
                        Bitmap bm = BitmapFactory.decodeFile(CameraUtils.CAMERA_IMAGE);
                        iv.setImageBitmap(bm);
                    }

                    break;
                case CameraUtils.RequestCode.FLAG_REQUEST_CAMERA_VIDEO:
                    //TODO 處理從相機返回的視訊資料
                    videoView.setVideoURI(data.getData());
                    videoView.start();
                    break;
            }
        } else {
            Log.i("info", "取消使用者操作");
        }
    }
} 

 
③.CameraUtils工具類的程式碼:

public class CameraUtils
{
    public static final String CAMERA_IMAGE = "/sdcard/test.jpg";

    public static final String CAMERA_VIDEO = "/sdcard/test.mp4";

    public static void pickImageFromSystem(Activity activity)
    {
        /**
         * 引數一:開啟系統相簿的ACTION 引數二:返回資料的方式(從系統相簿的資料庫獲取)
         */
        Intent intent = new Intent(Intent.ACTION_PICK,
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        activity.startActivityForResult(intent,
                RequestCode.FLAG_REQUEST_SYSTEM_IMAGE);
    }

    public static String getImagePathFromSystem(Activity activity, Intent data)
    {
        // TODO 處理從相簿返回的圖片資料
        Uri uri = data.getData();// 使用getData方法獲取要呼叫的介面
        // 第二個引數表示要查詢的資料的欄位名
        Cursor c = activity.getContentResolver().query(uri,
                new String[]{MediaStore.Images.Media.DATA}, null, null, null);
        if (c != null)
        {
            c.moveToFirst();
            // 通過遊標來獲取名為MediaStore.Images.Media.DATA欄位的值
            String path = c.getString(c
                    .getColumnIndex(MediaStore.Images.Media.DATA));
            return path;
        }
        return null;
    }

    public static void openCameraForImage(Activity activity)
    {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // 僅當設定了MediaStore.EXTRA_OUTPUT引數時,系統將不再返回縮圖,而是會被完整儲存以下路徑
        intent.putExtra(MediaStore.EXTRA_OUTPUT,
                Uri.fromFile(new File(CAMERA_IMAGE)));
        activity.startActivityForResult(intent,
                CameraUtils.RequestCode.FLAG_REQUEST_CAMERA_IMAGE);
    }

    public static void openCameraForVideo(Activity activity)
    {
        Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        // 僅當設定了MediaStore.EXTRA_OUTPUT引數時,系統將不再返回縮圖,而是會被完整儲存以下路徑
        intent.putExtra(MediaStore.EXTRA_OUTPUT,
                Uri.fromFile(new File(CAMERA_VIDEO)));
        activity.startActivityForResult(intent,
                RequestCode.FLAG_REQUEST_CAMERA_VIDEO);
    }

    public interface RequestCode
    {
        int FLAG_REQUEST_SYSTEM_IMAGE = 0;

        int FLAG_REQUEST_CAMERA_IMAGE = 1;

        int FLAG_REQUEST_CAMERA_VIDEO = 2;
    }
}

 
④.佈局xml檔案:

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

    <Button
        android:id="@+id/btn_pick_image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="doClick"
        android:text="選取系統相簿圖片" />

    <Button
        android:id="@+id/btn_open_camera_for_image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="doClick"
        android:text="開啟相機拍照" />

    <Button
        android:id="@+id/btn_open_camera_for_video"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="doClick"
        android:text="開啟相機錄影" />

    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="120dp" />

    <VideoView
        android:id="@+id/video"
        android:layout_width="match_parent"
        android:layout_height="200dp" />
</LinearLayout>

 

--------------------- 
作者:Allen-華 
來源:CSDN 
原文:https://blog.csdn.net/carry_code/article/details/51615205