调用摄像头拍照

首先新建一个CameraAlbumTest项目。然后修改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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/take_photo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Take Phote"
        />


    <ImageView
        android:id="@+id/picture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        />

</LinearLayout>

定义完布局后,定义mainactivity

package com.example.cameraalbumtest;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

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 takePhoto=(Button) findViewById(R.id.take_photo);
        picture =(ImageView) findViewById(R.id.picture);

        takePhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //创建file对象,用于存储拍照后的图片
                File outputImage=new File(getExternalCacheDir(),"output_image.jpg");//把图片进行命名
                //调用getExternalCacheDir()可以得到手机SD卡的应用关联缓存目录
                //所谓的应用关联缓存目录,就是指SD卡中专门用于存放当前应用缓存数据的位置
                //具体的路径是/sdcard/Android/data/<package name>/cache

                //因为从Android 6.0系统开始,读写SD卡被列为了危险权限,
                // 如果将图片存放在SD卡的任何其他目录,都要进行运行时权限处理才行,而使用应用关联目录则可以跳过这一步。
                try {
                    if (outputImage.exists()) {//如果已经存在了图片,则删掉,
                        outputImage.delete();
                    }
                    outputImage.createNewFile();//将图片放入
                }catch (IOException e){
                    e.printStackTrace();
                }

                //获取Uri对象
                //这个Uri对象标识着output_image.jpg这张图片的本地真实路径。
                if (Build.VERSION.SDK_INT >= 24) {
                    //调用FileProvider的getUriForFile() 方法将File 对象转换成一个封装过的Uri对象
                    imageUri = FileProvider.getUriForFile(MainActivity.this,"com.example.cameraalbumtest.fileprovider", outputImage);
                    //FileProvider则是一种特殊的内容提供器,它使用了和内容提供器类似的机制来对数据进行保护,
                    // 可以选择性地将封装过的Uri共享给外部,从而提高了应用的安全性。
                    //第一个参数要求传入Context 对象
                    //第二个参数可以是任意唯一的字符串 (需要在AndroidManifest.xml中声明)
                    //第三个参数则是我们刚刚创建的File 对象

                } else {//若系统的版本低于Android7.0,则调用下面的方法将File对象转换为Uri对象
                    imageUri = Uri.fromFile(outputImage);
                }

                //启动相机程序
                Intent intent= new Intent("android.media.action.IMAGE_CAPTURE");
                intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);//指定图片的输出地址
                startActivityForResult(intent,TAKE_PHOTO);//调用startActivityForResult() 来启动活动。
            }
        });

    }

    //使用startActivityForResult() 来启动活动的,
    // 因此拍完照后会有结果返回到onActivityResult() 方法中。
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case TAKE_PHOTO:
                if (resultCode == RESULT_OK) {//如果拍照成功
                    try {
                        // 将拍摄的照片显示出来
                        //可以调用BitmapFactory的decodeStream() 方法将output_image.jpg这张照片解析成Bitmap 对象
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
                        picture.setImageBitmap(bitmap);//将Bitmap对象,设置到ImageView中显示出来。
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                break;
            default:
                break;
        }
    }
}

 

由于采用到了内容提供器(FileProvider),那么我们自然要在AndroidManifest.xml中对内容提供器进行注册了,如下所示:

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

    <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">

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.cameraalbumtest.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

其中,android:name 属性的值是固定的,android:authorities 属性的值必须要和刚才FileProvider.getUriForFile() 方法中的第二个参数一致。另外,这里还在<provider> 标签的内部使用<meta-data> 来指定Uri 的共享路径,并引用了一个@xml/file_paths 资源。当然,这个资源现在还是不存在的,下面我们就来创建它。
右击res 目录→New→Directory,创建一个xml目录,接着右击xml目录→New→File,创建一个file_paths.xml文件。然后修改file_paths.xml文件中的内容,如下所示:

1 <?xml version="1.0" encoding="utf-8"?>
2 <paths xmlns:android="http://schemas.android.com/apk/res/android">
3     <external-path name="my_images" path="" />
4 </paths>

其中,external-path 就是用来指定Uri 共享的,name 属性的值可以随便填,path 属性的值表示共享的具体路径。这里设置空值就表示将整个SD卡进行共享。

同时声明一下访问SD卡的权限

1 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

运行会发现报错。感觉第一行代码里面的程序的版本还是有点低哎。比如这里,必须填路径,但是里面就说空都可以。修改AndroidManifest.xml中的fileprovider后有

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

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <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:name="androidx.core.content.FileProvider"
            android:authorities="***.fileProvider"
            android:exported="false"
            android:grantUriPermissions="true"
            xmlns:tools="http://schemas.android.com/tools"
            tools:replace="android:authorities">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>


    </application>

</manifest>

再修改

1 <?xml version="1.0" encoding="utf-8"?>
2 <paths xmlns:android="http://schemas.android.com/apk/res/android">
3     <external-path name="my_images" path="/" />
4 </paths>
 

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

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<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:name="androidx.core.content.FileProvider"
android:authorities="com.example.cameraalbumtest.fileprovider"
android:exported="false"
android:grantUriPermissions="true"
xmlns:tools="http://schemas.android.com/tools"
tools:replace="android:authorities">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>


</application>

</manifest>

posted on 2022-05-24 19:08  GHOST-CR  阅读(52)  评论(0)    收藏  举报