Android 拍照适配到7.0,并进行动态权限授权(教学)

版权声明:转载请说明出处 https://blog.csdn.net/qq_42046338/article/details/86480399

 在Android 6.0的时候我们进行拍照 需要动态权限不然会报错, 有的也就直接崩溃,都没有错误日志,今天先说动态授权,并介入到拍照,拍照的话在7.0 的时候使用直接的包名储存会进行报错,就需要一个共享地址去储存砸门的图片,大致的问题就这些,接下来我们进行代码实现并进行讲解。

  我们使用摄像头所以第一步现在我们的清单文件也就是AndroidManifest中添加

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

       


public class MainActivity extends AppCompatActivity {

    private Button viewById;
    private final int MIME = 5; //权限回调参数
    private final int CAMERA_DATA = 6;//摄像头回调
    private Uri uriForFile;
    private ImageView image;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewById = findViewById(R.id.butt);
        image = findViewById(R.id.imageView);
        viewById.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, MIME);
                } else {
                    call();
                }
            }
        });
    }
    public void call() {
        File outImage = new File(getExternalCacheDir(), "outputimage.jpg");
        if (outImage.exists()) {
            outImage.delete();
        }
        try {
            outImage.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (Build.VERSION.SDK_INT >= 24) {
            uriForFile = FileProvider.getUriForFile(MainActivity.this, "com.example.jing.myapplication,fileprovider", outImage);
        } else {
            uriForFile = Uri.fromFile(outImage);
        }
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uriForFile);
        startActivityForResult(intent, CAMERA_DATA);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case MIME:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    call();
                } else {
                    Toast.makeText(this, "您尚未打开摄像头的权限", Toast.LENGTH_SHORT).show();
                }
                break;

        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        switch (requestCode) {
            case CAMERA_DATA:
                if (resultCode==Activity.RESULT_OK){
                    try {
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uriForFile));
                        image.setImageBitmap(bitmap);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }

                }
                break;
        }
    }
}

看完以上代码如果是一脸懵逼的话,OK 接下来就看详细的解释

   首先  viewById   是我们的按钮我通过匿名点击的方法进行申请权限和打开摄像头,这个就不多解释了

 if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)

 在这需要看的是 此方法  ContextCompat.checkSelfPermission 是我们进行权限 判断 是否有此权限 又 Android 提供的方法、

checkSelfPermission 的第一个参数是Context 第二个参数是具体的权限名 Manifest.permission.CAMERA PackageManager.PERMISSION_GRANTED 此常量为0  进行判断是否已经申请  如果已经申请过那就会走else  的方法直接调用  call();打开摄像头

OK  ContextCompat.checkSelfPermission(Context,String manager)参数说完我们说一下 当没有权限的时候要调用

 ActivityCompat.requestPermissions();此方法的第一个参数是Activity的实例,第二个是String 数组 , 我们把我们的权限申请写道此数组中,第三个参数是一个int 值,此值就好比状态码,只要是唯一的int 值就行

 调完ActivityCompat.requestPermissions(); 系统就会弹出权限申请的对话框,用户进行选择是或否,不管是什么结果都会回调到onRequestPermissionsResult();   方法中授权的结果就是 grantResults参数我们对grantResults进行判断并调用 call();方法。

   到这我们的 权限申请已经写完了,接下来我们解析call();方法进行打开摄像头。

    首先创建了File对象,用来储存摄像头的图片,并把图片命名为output.jpg,并储存到手机SD 的应用下不应该是缓存目录下,

getExternalCacheDir();为缓存目录要这个目录下去找到它是/Android/data/包名/cache,使用此目录是因为从Android6.0开始读写权限已经被列为了危险权限,如果放在别的路径下那我们就要运行时权限,当然运行权限我们已经学习过了。Build.VERSION.SDK_INT >= 24 要判断手机是否是大于7.0 因为从Android7.0 就要使用Uri不然会出问题因为我们要使用了一个共享目录才行 大于7.0 就调用FilePrvider的getUriForFile();如果小于就直接调用formFile();接下在构建了意图也就是Intent并启动,启动是通过startAcivityForResult();这样拍照完毕后我们回调到onActivityResult();方法中如果发现拍照成功那么就调用BitmapFactory()方法中的人codeStream();将图片解析成Bitmap并进行展示。

以为这样就完了?

不一你错我们上边说过,我们有一个共享目录没有创建接下来我们创建共享目录。

AndroidManifest.xml中进行注册

        <provider
            android:authorities="com.example.jing.myapplication,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>

此时有人说android:authorities:"";中的属性是什么我告诉你只需要和我们FileProvider():中方法一样就行 。

接下在创建,file_paths文件右击res-new-Directory,创建xml目录在xml目录new-File,创建file_pats.xml文件,

<?xml version="1.0" encoding="utf-8"?>
<paths >
    <external-path
        name="name"
        path="."/>


</paths>

external-path 中的name 可以随意写,path 中就是我们的地址有的人不写   点不会报错,  如果不写就写一个点,  他代表任意。

猜你喜欢

转载自blog.csdn.net/qq_42046338/article/details/86480399