精华内容
下载资源
问答
  • Android 11 拍照选择相册适配
    千次阅读
    2022-01-18 12:06:32

    拍照

    Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    
    String timeStamp = new SimpleDateFormat("yyyyMMddmmss").format(new Date());
    String imgFileName = "IMG_" + timeStamp;
    
    //核心 不可使用 Environment.getExternalStorageDirectory()
    String path = context.getExternalCacheDir().getAbsolutePath() + File.separator + "images" + File.separator+ "photos";
    
    File file = new File(path);
    if (!file.exists()) {
       file.mkdirs();
    }
    
    File cameraFile = new File(file.getPath(),imgFileName)
    
    Uri fileUri;
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
        fileUri = Uri.fromFile(cameraFile);
    } else {
       fileUri = FileProvider.getUriForFile(context,
       context.getPackageName() + ".update.provider", cameraFile);
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    //添加这一句表示对目标应用临时授权该Uri所代表的文件
        takeIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
    
    takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
    mContext.startActivityForResult(takeIntent, 100);
    

    相册

    Intent intentPhoto = new Intent(Intent.ACTION_PICK);
    intentPhoto.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
    mContext.startActivityForResult(intentPhoto, 100);
    
    更多相关内容
  • Google发行Android Q版本也有很长一段时间了,华为应用市场已经要求要适配Android Q版本了,所以,我们也要去对Android Q进行适配。 先讲一下咱们这节用到的新特性 Android Q文件存储机制修改成了沙盒模式,类似于...
  • 兼容android 11 兼容android 10 支持复杂选择情况,如当用户可选视频和图片多类型时,可以设定选择视频后不可以选择图片,反之亦然。也可以设定视频和图片各自类型的选择数。 支持绑定Glide、Picasso、Imageloader等...
  • 适配二: intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri) android 11以后强制分区存储,外部资源无法访问,所以添加一个输出保存位置photoUri,然后取值操作 [](()回调 override Android开源项目《ali1024....

    doCrop(data?.data!!)

    data?.data!!即是选择图片返回的Uri,可以直接使用,这里进行了下一步操作,剪裁

    [](()剪裁

    private fun doCrop(sourceUri: Uri) {

    Intrinsics.checkParameterIsNotNull(sourceUri, “资源为空”)

    UCrop.of(sourceUri, getDestinationUri())//当前资源,保存目标位置

    .withAspectRatio(1f, 1f)//宽高比

    .withMaxResultSize(500, 500)//宽高

    .start(this)

    }

    为了方便,这里使用了一个三方库[UCrop]((),使用简单方便。

    getDestinationUri()是当前资源裁剪后保存的目标位置

    private fun getDestinationUri(): Uri {

    val fileName = String.format(“fr_crop_%s.jpg”, System.currentTimeMillis())

    val cropFile = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName)

    return Uri.fromFile(cropFile)

    }

    UCrop的回调同样也在onActivityResult

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

    super.onActivityResult(requestCode, resultCode, data)

    if (resultCode == RESULT_OK) {

    when (requestCode) {

    REQUEST_CODE_ALBUM -> {

    doCrop(data?.data!!)

    }

    UCrop.REQUEST_CROP -> {

    val resultUri: Uri = UCrop.getOutput(data!!)!!

    val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(resultUri))

    // todo

    }

    UCrop.RESULT_ERROR -> {

    val error: Throwable = UCrop.getError(data!!)!!

    ToastUtil.show(“图片剪裁失败” + error.message)

    }

    }

    }

    }

    UCrop.getOutput(data!!)!!,即是返回的Uri,可以直接操作,也可以转成bitmap

    ok,到这里打开相册就介绍完了。

    接下来看重点,打开相机。

    author:[yechaoa](()

    [](()打开相机

    ===============================================================

    打开相机的流程就要稍微复杂一点了。

    [](()权限

    第一步不是打开,而是先检查是否有相机权限,这个在某些手机上是必须的,比如华为。

    • 配置文件添加:
    • 代码:

    private fun checkPermission() {

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

    openCamera()

    } else {

    ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CODE_PERMISSIONS)

    }

    }

    • 回调:

    override fun onRequestPermission 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》开源 sResult(requestCode: Int, permissions: Array, grantResults: IntArray) {

    super.onRequestPermissionsResult(requestCode, permissions, grantResults)

    if (requestCode == REQUEST_CODE_PERMISSIONS) {

    if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

    openCamera()

    } else {

    ToastUtil.show(“拒绝会导致无法使用相机”)

    }

    }

    }

    openCamera方法就是打开相机了。

    [](()打开前适配

    private fun openCamera() {

    val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)

    photoUri = getDestinationUri()

    photoUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

    //适配Android 7.0文件权限,通过FileProvider创建一个content类型的Uri

    FileProvider.getUriForFile(this, “$packageName.fileProvider”, File(photoUri.path!!))

    } else {

    getDestinationUri()

    }

    //android11以后强制分区存储,外部资源无法访问,所以添加一个输出保存位置,然后取值操作

    intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)

    startActivityForResult(intent, REQUEST_CODE_CAMERA)

    }

    • 适配一:

    FileProvider.getUriForFile(this, “$packageName.fileProvider”, File(photoUri.path!!))

    7.0以上,使用fileProvider的方式共享文件。

    • 适配二:

    intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)

    android 11以后强制分区存储,外部资源无法访问,所以添加一个输出保存位置photoUri,然后取值操作

    [](()回调

    override Android开源项目《ali1024.coding.net/public/P7/Android/git》 fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

    super.onActivityResult(requestCode, resultCode, data)

    if (resultCode == RESULT_OK) {

    when (requestCode) {

    REQUEST_CODE_ALBUM -> {

    doCrop(data?.data!!)

    最后

    下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。希望能够帮助到大家提升技术

    高级UI,自定义View

    UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

    不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

    Code) {

    REQUEST_CODE_ALBUM -> {

    doCrop(data?.data!!)

    最后

    下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。希望能够帮助到大家提升技术

    [外链图片转存中…(img-i62lZEGM-1650259643098)]

    高级UI,自定义View

    UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

    不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

    [外链图片转存中…(img-psS0eaj7-1650259643099)]

    展开全文
  • 由于是调用系统功能,因此不需权限 PhotoUtils.camera(activity,你定义的FileProvider的authority){ uri, success, msg -> if(success) Glide.with(this).load(uri).into(binding.ivImage) ...
  • 适配android11的选择和拍照的功能

    千次阅读 2021-11-02 16:05:54
    1.根据android11版本的升级,android在在拍照和选择照片上面有一些改动,公司的工具类不能适配所有的手机,所以花了一点时间整理了下,后面会把项目demo共享出来,方便大家使用 2.文档参考拍照 | Android 开发者 | ...

    1.根据android11版本的升级,android在在拍照和选择照片上面有一些改动,公司的工具类不能适配所有的手机,所以花了一点时间整理了下,后面会把项目demo共享出来,方便大家使用

    2.文档参考拍照  |  Android 开发者  |  Android Developers

    FileProvider  |  Android Developers

    3.注意的点:

    <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/Theme.Practice"
        android:requestLegacyExternalStorage="true"
        >
        <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.hb.myphoto.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true"
            >
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"
                >
            </meta-data>
        </provider>
    </application>
    

    android10系统要添加android:requestLegacyExternalStorage="true" 否则会选择照片时,能正确获取图片地址,但是不能显示,报错如下:Unable to decode stream: java.io.FileNotFoundException: /storage/emulated/0/DCIM/Camera/IMG_20211029_100907.jpg: open failed: EACCES (Permission denied)

    2.功能介绍:file_paths.xml如下:适配FileProvider获取文件目录:

    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <!--
            external-path 用来指定Uri共享的,
            name数据随便填写, path属性的值表示共享的具体路径
            .表示把整个sd卡进行共享
        -->
        <cache-path name="name" path="path" />  <!--该方式提供在应用的内部存储区的缓存子目录的文件。它对应getCacheDir返回的路径:-->
    
        <external-path name="name" path="path" />  <!--它对应Environment.getExternalStorageDirectory返回的路径:-->
    
        <external-files-path name="name" path="path" /> <!--"/storage/emulated/0/Android/data/com.jph.simple/files"-->
    
        <external-cache-path name="name" path="path" /> <!--Context.getExternalCacheDir()返回的路径。 eg:"/storage/emulated/0/Android/data/com.jph.simple/cache"。-->
    
        <root-path path="" name="camera_photos" />
    
    </paths>
    

    3.MainActivity.class类:

    package com.hb.myphoto;
    
    import androidx.annotation.Nullable;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.app.ActivityCompat;
    import androidx.core.content.ContextCompat;
    
    import android.Manifest;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Bundle;
    import android.os.Environment;
    import android.text.TextUtils;
    import android.util.Log;
    import android.view.View;
    import android.widget.ImageView;
    
    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "MainActivity";
        private ImageView iv_picture;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            iv_picture = findViewById(R.id.iv_picture);
        }
    
        public void startSelect(View view) {
            if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){
                PhotoQUtil.getInstance().dispatchSelectPictureIntent(this);
            }else{
                ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA},123);
            }
        }
    
        public void startCamera(View view) {
            PhotoQUtil.getInstance().dispatchTakeLargePictureIntent(this);
        }
    
        public void filePath(View view) {
            Log.d(TAG, "filePath: " + getExternalFilesDir(Environment.DIRECTORY_MOVIES) + "--filesDir:" + getFilesDir());
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if(requestCode == PhotoQUtil.REQUEST_CAMERA_THUMB_CAPTURE && resultCode == RESULT_OK){      //获取拍照的缩略图
                Bundle extras = data.getExtras();
                Bitmap imageBitmap = (Bitmap) extras.get("data");
                iv_picture.setImageBitmap(imageBitmap);
            }else if(requestCode == PhotoQUtil.REQUEST_CAMERA_CAPTURE && resultCode == RESULT_OK){
                if(!TextUtils.isEmpty(PhotoQUtil.getInstance().currentPhotoPath)){
                    PhotoQUtil.getInstance().setPic(iv_picture,true);
                }
            }else if(requestCode == PhotoQUtil.REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK){
                String imagePath = PhotoQUtil.getInstance().parseApiImagePath(this,data);
                if(!TextUtils.isEmpty(imagePath)){
                    iv_picture.setImageBitmap(BitmapFactory.decodeFile(imagePath));
                }
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            PhotoQUtil.getInstance().clear();
        }
    }

    只有俩个按钮:一个选择相册,一个时拍照按钮

    4.工具类:

    package com.hb.myphoto;
    
    
    import android.annotation.SuppressLint;
    import android.annotation.TargetApi;
    import android.app.Activity;
    import android.content.ContentUris;
    import android.content.Context;
    import android.content.Intent;
    import android.database.Cursor;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Environment;
    import android.provider.DocumentsContract;
    import android.provider.MediaStore;
    import android.text.TextUtils;
    import android.util.Log;
    import android.widget.ImageView;
    
    import androidx.core.content.FileProvider;
    
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * create by hb
     */
    public class PhotoQUtil {
        private static final String TAG = "PhotoQUtil";
        private static PhotoQUtil mInstance;
        public static final int REQUEST_IMAGE_CAPTURE = 1;
        public static final int REQUEST_CAMERA_CAPTURE = 2;
        public static final int REQUEST_CAMERA_THUMB_CAPTURE = 3;  //拍照获取缩略图
        String currentPhotoPath;
    
        public static PhotoQUtil getInstance(){
            if(mInstance == null){
                mInstance = new PhotoQUtil();
            }
            return mInstance;
        }
    
        /**
         * 拍照
         * @param activity
         * 返回是缩略图
         */
        public void dispatchTakePictureIntent(Activity activity){
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    //        if(intent.resolveActivity(activity.getPackageManager()) != null){
    //
    //        }
            activity.startActivityForResult(intent,REQUEST_CAMERA_THUMB_CAPTURE);
        }
    
        /**
         * 拍照
         * 返回大图,直接返回目录
         */
        public void dispatchTakeLargePictureIntent(Activity activity){
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    //        if(takePictureIntent.resolveActivity(activity.getPackageManager()) != null){  //官方添加这个判断,但是在华为android11 此方法为空,不知道为啥
    //
    //        }
            try {
                File photoFile = null;
                photoFile = createImageFile(activity);
                if(photoFile != null){
                    Uri photoURI = FileProvider.getUriForFile(activity,
                            "com.hb.myphoto.fileprovider",
                            photoFile);
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                    activity.startActivityForResult(takePictureIntent,REQUEST_CAMERA_CAPTURE);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public File createImageFile(Context context) throws IOException {
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHss").format(new Date());
            String imageFileName = "JPEG_" + timeStamp + "_";
            File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
            File image = File.createTempFile(
                    imageFileName,
                    ".jpg",
                    storageDir
            );
            currentPhotoPath = image.getAbsolutePath();
            return image;
        }
    
        /**
         * 选择照片
         */
        public void dispatchSelectPictureIntent(Activity activity){
            Log.i(TAG,"选择照片");
            Intent intent = new Intent(Intent.ACTION_PICK);
            intent.setType("image/*");
            activity.startActivityForResult(intent,REQUEST_IMAGE_CAPTURE);
        }
    
        public String parseApiImagePath(Context context,Intent intent){
            String result = "";
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
                result = handleImageOnKitkat(context,intent);
            }else{
                result = handleImageBeforeKitkat(intent);
            }
            Log.i(TAG,"选择照片路径:" + result);
            return result;
        }
    
        /**
         * 获取大于19版本的图片
         * @param data
         */
        @TargetApi(19)
        private String handleImageOnKitkat(Context context,Intent data){
            String imagePath = "";
            Uri uri = data.getData();
            if(DocumentsContract.isDocumentUri(context,uri)){
                String docId = DocumentsContract.getDocumentId(uri);
                if("com.android.providers.media.documents".equals(uri.getAuthority())){
                    String id = docId.split(":")[1];
                    //解析出数字格式的id
                    String selection = MediaStore.Images.Media._ID + "=" + id;
                    imagePath = getImagePath(context,uri,selection);
                }else if("com.android.providers.downloads.documents".equals(uri.getAuthority())){
                    Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),Long.valueOf(docId));
                    imagePath = getImagePath(context,contentUri,null);
                }
            }else if("content".equalsIgnoreCase(uri.getScheme())){
                imagePath = getImagePath(context,uri,null);
            }else if("file".equalsIgnoreCase(uri.getScheme())){
                imagePath = uri.getPath();
            }
            return imagePath;
        }
    
        private String handleImageBeforeKitkat(Intent data){
            String imagePath = "";
            Uri uri = data.getData();
            imagePath = uri.getPath();
            return imagePath;
        }
    
        @SuppressLint("Range")
        public String getImagePath(Context context, Uri uri, String selection){
            String path = null;
            /**
             * 通过uri和seletion来获取真实的图片路径
             */
            Cursor cursor = context.getContentResolver().query(uri,null,selection,null,null);
            if(cursor != null){
                if(cursor.moveToFirst()){
                    path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
                }
                cursor.close();
            }
            return path;
        }
    
        /*
        * 将照片添加到图库
        * */
        private void galleryAddPic(Context context){
            Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            if(TextUtils.isEmpty(currentPhotoPath)){
                File f = new File(currentPhotoPath);
                Uri contentUri = Uri.fromFile(f);
                mediaScanIntent.setData(contentUri);
                context.sendBroadcast(mediaScanIntent);
            }
        }
    
        public void setPic(ImageView imageView,boolean isGallery){
            if(isGallery){
                galleryAddPic(imageView.getContext());
            }
            if(!TextUtils.isEmpty(currentPhotoPath)){
                int targetW = imageView.getWidth();
                int targetH = imageView.getHeight();
                BitmapFactory.Options bmOptions = new BitmapFactory.Options();
                bmOptions.inJustDecodeBounds = true;
    
                int photoW = bmOptions.outWidth;
                int photoH = bmOptions.outHeight;
                int scaleFactor = Math.min(photoW/targetW,photoH/targetH);
                Log.i(TAG,"photoW:" + photoW + "-photoH:" + photoH + "-scaleFactor:" + scaleFactor);
    
                bmOptions.inJustDecodeBounds = false;
                bmOptions.inSampleSize = scaleFactor;
                bmOptions.inPurgeable = true;
                Bitmap bitmap = BitmapFactory.decodeFile(currentPhotoPath,bmOptions);
                imageView.setImageBitmap(bitmap);
            }
        }
    
        public void clear() {
            currentPhotoPath = "";
        }
    }
    
    

    5.项目下载地址

    https://download.csdn.net/download/xiaoze_1987/36473720 只需要一积分,欢迎讨论

    展开全文
  • Android 10/11 存储适配 ok,接下来以一个更换头像的小例子来讲解一下。 示例 ============================================================= 点击头像,然后弹窗,给出不同的选项,执行不同的操作。 mBinding....
    • Android 6 权限适配

    • Android 7 文件适配

    • Android 10/11 存储适配

    ok,接下来以一个更换头像的小例子来讲解一下。

    示例

    =============================================================

    在这里插入图片描述

    点击头像,然后弹窗,给出不同的选项,执行不同的操作。

    mBinding.llImg.setOnClickListener {

    TakeImage

    《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

    开源分享完整内容戳这里

    Dialog {

    when (it) {

    TakeImageDialog.ALBUM -> {

    openAlbum()

    }

    TakeImageDialog.CAMERA -> {

    checkPermission()

    }

    }

    }.show(supportFragmentManager, “TakeImageDialog”)

    }

    定义后面会用到的一些参数变量

    //相机拍照保存的位置

    private lateinit var photoUri: Uri

    companion object {

    private const val REQUEST_CODE_PERMISSIONS = 1000 //权限

    private const val REQUEST_CODE_ALBUM = 1001 //相册

    private const val REQUEST_CODE_CAMERA = 1002 //相机

    }

    打开相册

    ===============================================================

    选择图片

    private fun openAlbum() {

    val intent = Intent()

    intent.type = “image/*”

    intent.action = “android.intent.action.GET_CONTENT”

    intent.addCategory(“android.intent.category.OPENABLE”)

    startActivityForResult(intent, REQUEST_CODE_ALBUM)

    }

    固定写法,大差不差。

    既然是startActivityForResult启动方式,来看看onActivityResult回调

    回调

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

    super.onActivityResult(requestCode, resultCode, data)

    if (resultCode == RESULT_OK) {

    when (requestCode) {

    REQUEST_CODE_ALBUM -> {

    doCrop(data?.data!!)

    }

    }

    }

    }

    requestCodeREQUEST_CODE_ALBUM的情况下:

    doCrop(data?.data!!)

    data?.data!!即是选择图片返回的Uri,可以直接使用,这里进行了下一步操作,剪裁

    剪裁

    private fun doCrop(sourceUri: Uri) {

    Intrinsics.checkParameterIsNotNull(sourceUri, “资源为空”)

    UCrop.of(sourceUri, getDestinationUri())//当前资源,保存目标位置

    .withAspectRatio(1f, 1f)//宽高比

    .withMaxResultSize(500, 500)//宽高

    .start(this)

    }

    为了方便,这里使用了一个三方库UCrop,使用简单方便。

    getDestinationUri()是当前资源裁剪后保存的目标位置

    private fun getDestinationUri(): Uri {

    val fileName = String.format(“fr_crop_%s.jpg”, System.currentTimeMillis())

    val cropFile = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName)

    return Uri.fromFile(cropFile)

    }

    UCrop的回调同样也在onActivityResult

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

    super.onActivityResult(requestCode, resultCode, data)

    if (resultCode == RESULT_OK) {

    when (requestCode) {

    REQUEST_CODE_ALBUM -> {

    doCrop(data?.data!!)

    }

    UCrop.REQUEST_CROP -> {

    val resultUri: Uri = UCrop.getOutput(data!!)!!

    val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(resultUri))

    // todo

    }

    UCrop.RESULT_ERROR -> {

    val error: Throwable = UCrop.getError(data!!)!!

    ToastUtil.show(“图片剪裁失败” + error.message)

    }

    }

    }

    }

    UCrop.getOutput(data!!)!!,即是返回的Uri,可以直接操作,也可以转成bitmap

    ok,到这里打开相册就介绍完了。

    接下来看重点,打开相机。

    author:yechaoa

    打开相机

    ===============================================================

    打开相机的流程就要稍微复杂一点了。

    权限

    第一步不是打开,而是先检查是否有相机权限,这个在某些手机上是必须的,比如华为。

    • 配置文件添加:
    • 代码:

    private fun checkPermission() {

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

    openCamera()

    } else {

    ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CODE_PERMISSIONS)

    }

    }

    • 回调:

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {

    super.onRequestPermissionsResult(requestCode, permissions, grantResults)

    if (requestCode == REQUEST_CODE_PERMISSIONS) {

    if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

    openCamera()

    } else {

    ToastUtil.show(“拒绝会导致无法使用相机”)

    }

    }

    }

    openCamera方法就是打开相机了。

    打开前适配

    private fun openCamera() {

    val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)

    photoUri = getDestinationUri()

    photoUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

    //适配Android 7.0文件权限,通过FileProvider创建一个content类型的Uri

    FileProvider.getUriForFile(this, “$packageName.fileProvider”, File(photoUri.path!!))

    } else {

    getDestinationUri()

    }

    //android11以后强制分区存储,外部资源无法访问,所以添加一个输出保存位置,然后取值操作

    intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)

    startActivityForResult(intent, REQUEST_CODE_CAMERA)

    }

    • 适配一:

    FileProvider.getUriForFile(this, “$packageName.fileProvider”, File(photoUri.path!!))

    7.0以上,使用fileProvider的方式共享文件。

    展开全文
  • android studio android7.0 6.0 拍照适配 头像上传功能
  • 主要介绍了Android 7.0中拍照和图片裁剪适配的相关问题,文中通过示例代码介绍的很详细,对大家具有一定的参考价值,有需要的朋友们下面来一起学习学习吧。
  • Android CameraX适配Android11的踩坑之路

    千次阅读 2021-12-29 17:45:12
    11月份Google发通知应用必须适配到30,要不然提交到google play的app不能发布更新,用户就只能使用旧版本。 1.我们来看看Google的通知说明: 自 2021 年 11 月 1 日起,针对 Google Play 上的应用和游戏的更新...
  • 1、在Android7.0上调用系统相机拍照,裁切照片的适配Android7.0以前,若是你想调用系统相机拍照能够经过如下代码来进行:javaFile file = new File(Environment.getExternalStorageDirectory(), "/pic/" + System...
  • uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 动态验证和申请权限的方式和之前一致 申请之后系统弹框的文案较之前有了变化,会凸显出 access photos and media 转存失败重新...
  • Android 11 适配

    千次阅读 2020-10-23 11:48:04
    与早期版本一样,Android 11 包含一些行为变更,这些变更可能会影响您的应用。以下行为变更仅影响以 Android11 或更高版本为目标平台的应用。如果您的应用将targetSdkVersion设置为30,您应酌情修改自己的应用,以便...
  • Android Q中引入了分区储存功能,在外部存储设备中为每个应用提供了一个“隔离存储沙盒”。其他应用无法直接访问应用的沙盒文件。由于文件是应用的私有文件,不再需要任何权限即可访问和保存自己的文件。此变更并...
  • 问题九:Android4.4以上版本从图库选择图片返回的路径不正确 详见参考链接1 问题十:Android 7.0调用系统相机崩溃 详见参考链接2 问题十一: Android 6.0 以上SecurityException 由于Android 6.0 以上的权限变成了...
  • Android11的包可见性 我们的应用常常会碰到与其他应用交互,比如登录功能,我们可能希望使用微信登录或者QQ登录,再比如分享,我们先判断是否安装了微信,然后决定是否展示微信的分享图标等等。这里我们有一个需求...
  • 关于Android 11(R)适配指南

    万次阅读 多人点赞 2020-09-11 18:15:50
    文章来自 ... 前言 最近看到一条新闻,Android 11(version 30,Andorid R)最终Beta版 如期发布,看到这个新闻我知道我不能再拖了,再不好好准备好迎...
  • 调用相机只需要调用startActivityForResult传一个Intent就可以了,但是这个Intent需要传递一个uri,用于保存拍出来的图片,创建这个uri时,各个Android版本有所不同,需要进行版本兼容。 //用于保存拍照图片的uri ...
  • android 11 关键变更 一:分区存储 1:已改为强制 android 10 关键变更 官方文档 一:分区存储 针对外部存储的过滤视图,可提供对特定于应用的文件和媒体集合的访问权限 受影响的应用:访问和共享外部存储中的文件的...
  • 前言最近一直被Android10相关的适配搞得焦头烂额,之前也听说过android10中的所有的视频,音频以及图片等资源为了统一的管理,统一放在一个共有的文件下,也就是所谓的沙箱。看了一下其他人写的文章,也提供了一种...
  • 前言没错!Android 11(version 30,Andorid R)正式发布了!看到这个新闻我知道我不能再拖了,再不好好准备好迎接Android11的到来,到时候迎接我的就是客户...
  • 3、我们使用android:requestLegacyExternalStorage=“true”,这样子Android10和11都可以使用File访问 4、 5、保存图片到相册,version大于30时,把原图片拷贝一份保存到相册,代码如下: @RequiresApi(api = Build....
  • 最近在项目遇到拍照上传的功能,才知道Android7.0之后直接使用本地真实路径的Uri会抛出FileExposedExceptiond?异常。才知道7.0之后需要用FileProvider才行。找了网上很多都不能用!直接上代码吧??第一步,在...
  • Android动态权限适配

    2021-06-08 15:13:51
    一 各大手机厂商的适配依据各大手机Rom的不同表现,可以分为三种不同的模式:标准模式,默认开启模式,特殊权限模式。1 标准模式:代表华为Mate8,三星S6。基本流程如下:用户启动APP后,第一次需要权限的时候,判断...
  • Android11 最全适配实践指南

    千次阅读 2021-01-21 15:59:44
    今天就和大家一起看看Android 11到底改了些什么,以及最重要的,我们需要怎么适配?targetversion 不改到 30,是不是就不用适配了呢?以下我分为两部分讲述,分别是 以Android 11为目标版本的应用 (targetSdk...
  • Android 头像适配6.0、 7.0、 8.0
  • Android 12应用适配指南

    千次阅读 2021-05-20 15:05:27
    Android 12应用适配指南1.Android 12上的主要变更1.1 兼容性1.1.1 前台服务启动限制1.1.2 前台服务通知延迟1.1.3 待处理 intent 必须声明可变性1.1.4 非SDK接口名单更新1.2 用户体验1.2.1 接收内容的统一API1.2.2 ...
  • 兼容android 11 唤起系统相机拍照并显示

    千次阅读 热门讨论 2021-02-02 14:31:11
    兼容android 11 唤起系统相机拍照并显示 本文是记录兼容android 11的唤起系统相机拍照并正常显示,此处我默认已经获取到相机和读写的权限。 打开相机 /** * 保存 photoUri */ private Uri photoUri; /** * ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,488
精华内容 2,195
关键字:

android11拍照适配