7.0以上版本(包括7.0)实现拍照功能有两个需要注意的地方
注意⚠️:如果是调用系统相机,是不用动态申请相机权限的!但是如果AndroidManifest.xml里面写了相机权限声明,那么就需要动态申请权限了
在6.0系统之前,需要指定的权限可以在AndroidManifest.xml文件中进行权限声明
例如:
<user-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
但是这样会涉及到一个安全性问题,在6.0系统之前通过此方法声明的权限会在安装app的时候告诉用户该app需要的所有权限,一旦安装就表示授权,用户没有选择的余地。因此6.0后android将权限分级,不重要的权限可以在AndroidManifest.xml文件中
声明,等级较高(比如涉及到相机,电话等权限)权限则需要动态授权,并且用户可以随时在设置中取消授权。
重要权限可以查阅相关文档
官方说明
调用ActivityComapt的requestPermissions的方法
public static void requestPermissions(@NonNull final Activity activity, @NonNull final String[] permissions, @IntRange(from = 0L) final int requestCode)
实例
ActivityCompat.requestPermissions(MainActivity.this,new String [] {permission},1);
调用这个方法获取权限后,将会回调MainActivity中的onRequestPermissionsResult()方法,在此方法中可以通过requestCode来判断是否获得到了权限进而进行下一步操作。
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
swich(requestCode){
case 1:
if(grantResults.length > 0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
// to do
}else{
Toast.makeText(this,"You denied the permission",Toast.LENGTH_SHORT).show();
}
break;
default:
}
}
在实际开发中,为了程序能适应多个版本的系统,需要对系统版本进行检测,从而来执行不同的操作
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// 7.0 以上
}else {
// 7.0 以下
}
if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.CAMERA)!=PackageManager.PERMISSION_GRANTED){
//to do
}
PackageManager.PERMISSION_DENIED 表示没有权限
PackageManager.PERMISSION_GRANTED 有权限
详细参考内容提供器 content provider
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA"/>
if (ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String [] {Manifest.permission.CAMERA},1);
}
在application标签中添加
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.baiduocr.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
provider>
在res下创建一个xml文件夹再创建一个file_paths.XML 文件
file_paths.XML文件内容
<Paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="camera_photos" path=""/>
Paths>
public class MainActivity extends AppCompatActivity {
private ImageView imageView=null;
private Uri imageUri;
private Button button=null;
private static final int TAKE_PHOTO = 1;
private File outputFile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
setListener();
}
/**
* 如果用户拒绝相机权限就再次获取
**/
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
} else {
requestPermission(Manifest.permission.CAMERA);
}
}
protected void init(){
button=(Button)findViewById(R.id.button);
imageView=(ImageView)findViewById(R.id.imageView);
requestPermission(Manifest.permission.CAMERA);
}
private void setListener(){
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
takePhoto();
}
});
}
public void takePhoto(){
outputFile = new File(MainActivity.this.getExternalCacheDir(),"output.jpg");
try{
if (outputFile.exists()){
outputFile.delete();
}
outputFile.createNewFile();
}catch (Exception e){
}
if (Build.VERSION.SDK_INT>=24){
imageUri=FileProvider.getUriForFile(MainActivity.this,"com.example.baiduocr.fileprovider",outputFile);
}else{
imageUri=Uri.fromFile(outputFile);
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
startActivityForResult(intent,TAKE_PHOTO);
}
public void requestPermission(String permission){
if (ContextCompat.checkSelfPermission(this,permission)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String [] {permission},1);
}
}
public void startPhotoZoom(Uri uri) {
Log.e("uri=====", "" + uri);
//com.android.camera.action.CROP,这个action是调用系统自带的图片裁切功能
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");//裁剪的图片uri和图片类型
intent.putExtra("crop", "true");//设置允许裁剪,如果不设置,就会跳过裁剪的过程,还可以设置putExtra("crop", "circle")
intent.putExtra("aspectX", 4);//裁剪框的 X 方向的比例,需要为整数
intent.putExtra("aspectY", 1);//裁剪框的 Y 方向的比例,需要为整数
intent.putExtra("outputX", 100*4);//返回数据的时候的X像素大小。
intent.putExtra("outputY", 100);//返回数据的时候的Y像素大小。
//uritempFile为Uri类变量,实例化uritempFile
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (TAKE_PHOTO == 1) {//如果是7.0的拍照
//开启临时访问的读和写权限
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
//针对7.0以上的操作
intent.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, uri));
imageUri = uri;
} else {//如果是7.0的相册
//设置裁剪的图片地址Uri
imageUri = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + "clip.jpg");
}
} else {
imageUri = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + "clip.jpg");
Toast.makeText(this,imageUri.toString(),Toast.LENGTH_SHORT).show();
}
Log.e("uriClipUri=====", "" + imageUri);
//Android 对Intent中所包含数据的大小是有限制的,一般不能超过 1M,否则会使用缩略图 ,所以我们要指定输出裁剪的图片路径
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.putExtra("return-data", false);//是否将数据保留在Bitmap中返回
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());//输出格式,一般设为Bitmap格式及图片类型
startActivityForResult(intent, PHOTO_PHOTOCLIP);//裁剪完成的标识
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
switch (requestCode){
case TAKE_PHOTO:
//to do
break;
}
}catch (FileNotFoundException e){
}
}
}