Android学习——调用摄像头拍照

首先新建一个CameraAlbumTest项目。然后修改activity_main.xml中的代码,如下所示:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:app="http://schemas.android.com/apk/res-auto"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     android:orientation="vertical"
 8     tools:context=".MainActivity">
 9  
10     <Button
11         android:id="@+id/take_photo"
12         android:layout_width="match_parent"
13         android:layout_height="wrap_content"
14         android:text="Take Phote"
15         />
16  
17  
18     <ImageView
19         android:id="@+id/picture"
20         android:layout_width="wrap_content"
21         android:layout_height="wrap_content"
22         android:layout_gravity="center_horizontal"
23         />
24  
25 </LinearLayout>

定义完布局后,定义mainactivity

  1 package com.example.cameraalbumtest;
  2  
  3 import androidx.appcompat.app.AppCompatActivity;
  4 import androidx.core.content.FileProvider;
  5  
  6 import android.content.Intent;
  7 import android.graphics.Bitmap;
  8 import android.graphics.BitmapFactory;
  9 import android.net.Uri;
 10 import android.os.Build;
 11 import android.os.Bundle;
 12 import android.provider.MediaStore;
 13 import android.view.View;
 14 import android.widget.Button;
 15 import android.widget.ImageView;
 16  
 17 import java.io.File;
 18 import java.io.FileNotFoundException;
 19 import java.io.IOException;
 20  
 21 public class MainActivity extends AppCompatActivity {
 22  
 23     public static final int TAKE_PHOTO=1;
 24  
 25     private ImageView picture;
 26  
 27     private Uri imageUri;
 28  
 29     @Override
 30     protected void onCreate(Bundle savedInstanceState) {
 31         super.onCreate(savedInstanceState);
 32         setContentView(R.layout.activity_main);
 33  
 34         //获取实例
 35         Button takePhoto=(Button) findViewById(R.id.take_photo);
 36         picture =(ImageView) findViewById(R.id.picture);
 37  
 38         takePhoto.setOnClickListener(new View.OnClickListener() {
 39             @Override
 40             public void onClick(View v) {
 41                 //创建file对象,用于存储拍照后的图片
 42                 File outputImage=new File(getExternalCacheDir(),"output_image.jpg");//把图片进行命名
 43                 //调用getExternalCacheDir()可以得到手机SD卡的应用关联缓存目录
 44                 //所谓的应用关联缓存目录,就是指SD卡中专门用于存放当前应用缓存数据的位置
 45                 //具体的路径是/sdcard/Android/data/<package name>/cache
 46  
 47                 //因为从Android 6.0系统开始,读写SD卡被列为了危险权限,
 48                 // 如果将图片存放在SD卡的任何其他目录,都要进行运行时权限处理才行,而使用应用关联目录则可以跳过这一步。
 49                 try {
 50                     if (outputImage.exists()) {//如果已经存在了图片,则删掉,
 51                         outputImage.delete();
 52                     }
 53                     outputImage.createNewFile();//将图片放入
 54                 }catch (IOException e){
 55                     e.printStackTrace();
 56                 }
 57  
 58                 //获取Uri对象
 59                 //这个Uri对象标识着output_image.jpg这张图片的本地真实路径。
 60                 if (Build.VERSION.SDK_INT >= 24) {
 61                     //调用FileProvider的getUriForFile() 方法将File 对象转换成一个封装过的Uri对象
 62                     imageUri = FileProvider.getUriForFile(MainActivity.this,"com.example.cameraalbumtest.fileprovider", outputImage);
 63                     //FileProvider则是一种特殊的内容提供器,它使用了和内容提供器类似的机制来对数据进行保护,
 64                     // 可以选择性地将封装过的Uri共享给外部,从而提高了应用的安全性。
 65                     //第一个参数要求传入Context 对象
 66                     //第二个参数可以是任意唯一的字符串 (需要在AndroidManifest.xml中声明)
 67                     //第三个参数则是我们刚刚创建的File 对象
 68  
 69                 } else {//若系统的版本低于Android7.0,则调用下面的方法将File对象转换为Uri对象
 70                     imageUri = Uri.fromFile(outputImage);
 71                 }
 72  
 73                 //启动相机程序
 74                 Intent intent= new Intent("android.media.action.IMAGE_CAPTURE");
 75                 intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);//指定图片的输出地址
 76                 startActivityForResult(intent,TAKE_PHOTO);//调用startActivityForResult() 来启动活动。
 77             }
 78         });
 79  
 80     }
 81  
 82     //使用startActivityForResult() 来启动活动的,
 83     // 因此拍完照后会有结果返回到onActivityResult() 方法中。
 84     @Override
 85     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 86         super.onActivityResult(requestCode, resultCode, data);
 87         switch (requestCode) {
 88             case TAKE_PHOTO:
 89                 if (resultCode == RESULT_OK) {//如果拍照成功
 90                     try {
 91                         // 将拍摄的照片显示出来
 92                         //可以调用BitmapFactory的decodeStream() 方法将output_image.jpg这张照片解析成Bitmap 对象
 93                         Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
 94                         picture.setImageBitmap(bitmap);//将Bitmap对象,设置到ImageView中显示出来。
 95                     } catch (FileNotFoundException e) {
 96                         e.printStackTrace();
 97                     }
 98                 }
 99                 break;
100             default:
101                 break;
102         }
103     }
104 }

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

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.example.cameraalbumtest">
 4  
 5     <application
 6         android:allowBackup="true"
 7         android:icon="@mipmap/ic_launcher"
 8         android:label="@string/app_name"
 9         android:roundIcon="@mipmap/ic_launcher_round"
10         android:supportsRtl="true"
11         android:theme="@style/AppTheme">
12  
13         <provider
14             android:name="android.support.v4.content.FileProvider"
15             android:authorities="com.example.cameraalbumtest.fileprovider"
16             android:exported="false"
17             android:grantUriPermissions="true">
18             <meta-data
19                 android:name="android.support.FILE_PROVIDER_PATHS"
20                 android:resource="@xml/file_paths" />
21         </provider>
22  
23         <activity android:name=".MainActivity">
24             <intent-filter>
25                 <action android:name="android.intent.action.MAIN" />
26  
27                 <category android:name="android.intent.category.LAUNCHER" />
28             </intent-filter>
29         </activity>
30     </application>
31  
32 </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后有

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.example.cameraalbumtest">
 4  
 5     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 6  
 7     <application
 8         android:allowBackup="true"
 9         android:icon="@mipmap/ic_launcher"
10         android:label="@string/app_name"
11         android:roundIcon="@mipmap/ic_launcher_round"
12         android:supportsRtl="true"
13         android:theme="@style/AppTheme">
14  
15         <activity android:name=".MainActivity">
16             <intent-filter>
17                 <action android:name="android.intent.action.MAIN" />
18  
19                 <category android:name="android.intent.category.LAUNCHER" />
20             </intent-filter>
21         </activity>
22  
23         <provider
24             android:name="androidx.core.content.FileProvider"
25             android:authorities="***.fileProvider"
26             android:exported="false"
27             android:grantUriPermissions="true"
28             xmlns:tools="http://schemas.android.com/tools"
29             tools:replace="android:authorities">
30             <meta-data
31                 android:name="android.support.FILE_PROVIDER_PATHS"
32                 android:resource="@xml/file_paths" />
33         </provider>
34  
35  
36     </application>
37  
38 </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>
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.example.cameraalbumtest">
 4  
 5     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 6  
 7     <application
 8         android:allowBackup="true"
 9         android:icon="@mipmap/ic_launcher"
10         android:label="@string/app_name"
11         android:roundIcon="@mipmap/ic_launcher_round"
12         android:supportsRtl="true"
13         android:theme="@style/AppTheme">
14  
15         <activity android:name=".MainActivity">
16             <intent-filter>
17                 <action android:name="android.intent.action.MAIN" />
18  
19                 <category android:name="android.intent.category.LAUNCHER" />
20             </intent-filter>
21         </activity>
22  
23         <provider
24             android:name="androidx.core.content.FileProvider"
25             android:authorities="com.example.cameraalbumtest.fileprovider"
26             android:exported="false"
27             android:grantUriPermissions="true"
28             xmlns:tools="http://schemas.android.com/tools"
29             tools:replace="android:authorities">
30             <meta-data
31                 android:name="android.support.FILE_PROVIDER_PATHS"
32                 android:resource="@xml/file_paths" />
33         </provider>
34  
35  
36     </application>
37  
38 </manifest>
原文地址:https://www.cnblogs.com/znjy/p/14908506.html