第三节 适配Android10的拍照、从相册获取代码,包括完整的权限申请和图片地址获取

专栏目录

  1. 第一节 自定义轮播图的制作
  2. 第二节 底部导航栏菜单,炫酷菜单动画,背景变暗、按钮焦点获取
  3. 第三节 适配Android10的拍照、从相册获取代码,包括完整的权限申请和图片地址获取
  4. 第四节 百度定位、地图SDK,和风天气获取教程
  5. 第五节 微信朋友圈式九宫格添加图片展示(待更新)
  6. 第六节 第三方api获取淘宝数据,用RecyclerView进行商品展示、刷新和搜索(待更新)

引言

通过拍照和相册获取图片是App中常用的功能,而随着安卓版本的更新,在最新安卓系统上开发总是会出现各种各样的问题,所以我总结了适配Android10的拍照、从相册获取代码,包括完整的权限申请和图片地址获取,减少大家的工作量,同时进一步学习安卓开发。

效果图

在这里插入图片描述
注:因为用的虚拟机,所以拍照显示是乱的,真机运行正常。

Java代码

public class MainActivity extends AppCompatActivity {
    //打开图片标记
    private final int IMAGE_OPEN = 2;
    //相机启动请求码
    private static final int CAMERA_REQUEST_CODE = 1;
    // 是否是Android 10以上手机
    private boolean isAndroidQ = Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q;
    // 用于保存图片的文件路径,Android 10以下使用图片路径访问图片
    private String mCameraImagePath;
    //用于保存拍照图片的uri
    private Uri mCameraUri;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(null);
        setContentView(R.layout.activity_main);
        //第一步 测试权限并请求权限
        PermissionUtil.checkPermission(this,null);
        //相机点击事件
        ImageView camera = findViewById(R.id.button_camera);
        camera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //动态权限:点击相机时获取相机权限
                if (Build.VERSION.SDK_INT >= 23) {
                    String[] mPermissionList = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_EXTERNAL_STORAGE,  Manifest.permission.CAMERA};
                    ActivityCompat.requestPermissions(MainActivity.this, mPermissionList, 123);
                }
                //从相机获取图片
                openCamera();
            }
        });
        //相册点击事件
        ImageView album = findViewById(R.id.button_album);
        album.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //从相册获取图片
                if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
                }
                Intent photoPickerIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(photoPickerIntent, IMAGE_OPEN);
            }
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        //第二步 申请权限结果用户禁用引到系统设置
        PermissionUtil.onRequestPermissionsResult(this,requestCode,permissions,grantResults);
    }

    /**
     * 调起相机拍照
     */
    private void openCamera() {
        //使用MediaStore.ACTION_IMAGE_CAPTURE,拍照到指定目录
        Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // 判断是否有相机
        if (captureIntent.resolveActivity(getPackageManager()) != null) {
            File photoFile = null;
            Uri photoUri = null;
            if (isAndroidQ) {
                // 适配android 10
                photoUri = createImageUri();
            } else {
                try {
                    // android 10 以下版本
                    photoFile = createImageFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (photoFile != null) {
                    //获取绝对路径
                    mCameraImagePath = photoFile.getAbsolutePath();
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        //适配Android 7.0文件权限,通过FileProvider创建一个content类型的Uri
                        photoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile);
                    } else {
                        photoUri = Uri.fromFile(photoFile);
                    }
                }
            }
            //得到照片的Uri
            mCameraUri = photoUri;
            if (photoUri != null) {
                //以下两行代码是将图片保存到本地,可以看情况删掉
                //照片原来存储的地方输出保存
                captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
                //表示添加写入权限。
                captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                startActivityForResult(captureIntent, CAMERA_REQUEST_CODE);
            }
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        switch (requestCode) {
            // 调用相机后返回
            case 1:
                //打开相机
                if (resultCode == RESULT_OK) {
                    if (isAndroidQ) {
                        // Android 10 使用图片uri加载
                        final Bitmap photo = getBitmapFromUri(MainActivity.this, mCameraUri);
                        ImageView Camera = findViewById(R.id.camera);
                        Camera.setImageBitmap(photo);
                    } else {
                        // 使用图片路径加载
                        final Bitmap photo = BitmapFactory.decodeFile(mCameraImagePath);
                        ImageView Camera = findViewById(R.id.camera);
                        Camera.setImageBitmap(photo);
                    }
                } else {
                    Toast.makeText(this,"取消",Toast.LENGTH_LONG).show();
                }
                break;
            //调用相册后返回
            case 2:
                //打开图片
                if (resultCode == RESULT_OK) {
                    Uri uri = intent.getData();
                    if (!TextUtils.isEmpty(uri.getAuthority())) {
                        ImageView Album = findViewById(R.id.album);
                        //将Uri转成Bitmap
                        Album.setImageBitmap(getBitmapFromUri(this,uri));
                        //在真机上可以调用裁剪图片
                        //cropPhoto(uri);
                    }
                }else {
                    Toast.makeText(this,"取消",Toast.LENGTH_LONG).show();
                }
                break;
            //调用剪裁后返回
            case 3:
                Bundle bundle = intent.getExtras();
                if (bundle != null) {
                    //在这里获得了剪裁后的Bitmap对象,可以用于上传
                    Bitmap image = bundle.getParcelable("data");
                    //设置到ImageView上
                    ImageView Album = findViewById(R.id.album);
                    Album.setImageBitmap(image);
                }
                break;
        }
    }

    /**
     * 裁剪图片
     */
    private void cropPhoto(Uri uri) {
        //使用com.android.camera.action.CROP 则直接打开裁剪照片的activity
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        //设置在开启的Intent中设置显示的view可裁剪
        /*这段注释掉就不会跳转到裁剪的activity*/
        intent.putExtra("crop", "true");
        //设置x,y的比例,截图方框就按照这个比例来截 若设置为0,0,或者不设置 则自由比例截图
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 2);
        // 裁剪区的宽和高 其实就是裁剪后的显示区域 若裁剪的比例不是显示的比例,则自动压缩图片填满显示区域。若设置为0,0 就不显示。若不设置,则按原始大小显示
        intent.putExtra("outputX", 150);
        intent.putExtra("outputY", 300);
        // true的话直接返回bitmap
        intent.putExtra("return-data", true);
        // 上面设为false的时候将MediaStore.EXTRA_OUTPUT即"output"关联一个Uri
        //intent.putExtra("output", Uri);
        // 看参数即可知道是输出格式
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        // 想从Activity中获得返回数据,在启动Activity时候使用startActivityForResult方法
        //3为请求代码,可以是任意值
        startActivityForResult(intent, 3);
    }

    /**
     * 创建图片地址uri,用于保存拍照后的照片 Android 10以后使用这种方法
     */
    private Uri createImageUri() {
        String status = Environment.getExternalStorageState();
        // 判断是否有SD卡,优先使用SD卡存储,当没有SD卡时使用手机存储
        if (status.equals(Environment.MEDIA_MOUNTED)) {
            return getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
        } else {
            return getContentResolver().insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, new ContentValues());
        }
    }

    /**
     * 创建保存图片的文件,Android10之前使用
     */
    private File createImageFile() throws IOException {
        String imageName = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        if (!storageDir.exists()) {
            storageDir.mkdir();
        }
        File tempFile = new File(storageDir, imageName);
        if (!Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(tempFile))) {
            return null;
        }
        return tempFile;
    }

    // 通过uri加载图片
    public static Bitmap getBitmapFromUri(Context context, Uri uri) {
        try {
            ParcelFileDescriptor parcelFileDescriptor =
                    context.getContentResolver().openFileDescriptor(uri, "r");
            FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
            Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
            parcelFileDescriptor.close();
            return image;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    //将图片路径转为Uri
    public static Uri getImageContentUri(Context context, String path) {
        Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                new String[] { MediaStore.Images.Media._ID }, MediaStore.Images.Media.DATA + "=? ",
                new String[] { path }, null);
        if (cursor != null && cursor.moveToFirst()) {
            int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
            Uri baseUri = Uri.parse("content://media/external/images/media");
            return Uri.withAppendedPath(baseUri, "" + id);
        } else {
            // 如果图片不在手机的共享图片数据库,就先把它插入。
            if (new File(path).exists()) {
                ContentValues values = new ContentValues();
                values.put(MediaStore.Images.Media.DATA, path);
                return context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            } else {
                return null;
            }
        }
    }
}

PermissionUtil工具类代码

/**
 * 权限管理工具,快速解决系统功能权限申请问题
 * 一个个权限申请也太麻烦,这个批量申请能满足你的需求。
 * 程序在android 6  版本大于 23 时,权限需要申请,在配置表中设置的权限当拒绝后,导至功能失常,或闪退现象
 * 调用checkPermission申请权限回时调用 onRequestPermissionsResult
 */
public class PermissionUtil {

    static String[] permissions;
    /**
     *
     * 检测权限是否己申请,通过在启动应用程序时检测,当需要时,会自动弹出提示请求权限
     * @param context 请求的 Activity
     * @param pms 关键的权限,也就是必须要的权限 当为null 时,申请的全部权限都是必需的
     * @return 需要请求返回 false,返回true时全部权限都已获取
     */
    static  public boolean checkPermission(Activity context,String[] pms){
        int permissionCode=0;
        int decode=0;

        try {
            // APP 权限
              permissions = (pms!=null)?pms:context.getPackageManager().getPackageInfo(context.getPackageName(),PackageManager.GET_PERMISSIONS).requestedPermissions;
            for(int i=0;i<permissions.length;i++){
                System.out.println("PermissionUtil: " +permissions[i] );
                //判断用户是否给这些权限授权
               if(ContextCompat.checkSelfPermission(context, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
                   permissionCode+=1;
                   //判断是否拒绝过
                   decode += ActivityCompat.shouldShowRequestPermissionRationale(context, permissions[i]) ? 1 : 0;
               }
            }

        }catch (Exception e){
             System.out.println("PermissionUtil checkPermission error :"+e.getMessage());
        }

       if(permissionCode>0) {
           if(decode>0)
               requestTip(context);
           else
           requestPermissions(context,permissions);
           return false;
       }
       return true;
    }

    /**
     * 请求获取权限 当权限需要申请时调用
     * @param context 请求的 Activity
     * @param perms 需要请求的权限
     */
    static  public  void requestPermissions(Activity context,String[] perms){
        ActivityCompat.requestPermissions(context,  perms,  1);
    }

    /**
     * 引导用户到设置权限
     * @param context 请求的 Activity
     */
    static public void toSetting(Context context){
        Intent intent = new Intent();
        intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
        intent.setData(Uri.fromParts("package", context.getPackageName(), null));
        context.startActivity(intent);
    }

    /**
     *  提示请求权限 当拒绝了授权后,为提升用户体验,可以以弹窗的方式引导用户到设置中去进行设置
     * @param context  请求的 Activity
     */
    static  public void  requestTip(final Activity context){
        new AlertDialog.Builder(context)
                .setMessage("为更好体验,需要开启权限才能使用此功能!")
                .setPositiveButton("设置", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        toSetting(context);
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        context.finish();
                    }
                })
                .create()
                .show();
    }

    /**
     * 请求权限回调检测 如有拒绝 将直接引导到系统设置要求打开
     * @param context  请求的 Activity
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    static public void onRequestPermissionsResult(Activity context,int requestCode, String[] permissions,  int[] grantResults) {
         if(requestCode!=1)return;
         int code=0;
         if (grantResults.length <1)return;
        //用户是否拒绝了权限
         for (int i=0;i<grantResults.length;i++)
             code+=(grantResults[i]!= PackageManager.PERMISSION_GRANTED)?1:0;
        if(code==0)return;
        requestTip(context);
    }

    /**
     *  设置中打开权限管理界面
     *  跟据不同厂商进行快捷目录界面
     * @param context
     */
    public static void gotoPermissionManager(Context context) {
        String brand = Build.BRAND;//手机厂商
        if (TextUtils.equals(brand.toLowerCase(), "redmi")
                || TextUtils.equals(brand.toLowerCase(), "xiaomi")) {
            gotoMiuiPermissionManager(context);//小米
            return;
        }
         if (TextUtils.equals(brand.toLowerCase(), "meizu")) {
            gotoMeizuPermissionManager(context);
             return;
        }
         if (TextUtils.equals(brand.toLowerCase(), "huawei")
                    || TextUtils.equals(brand.toLowerCase(), "honor")) {
           gotoHuaweiPermissionManager(context);
           return;
        }
        toSetting(context);
    }

    /**
     * 跳转到魅族的权限管理系统
     */
    private static void gotoMeizuPermissionManager(Context context) {
        try {
            Intent intent = new Intent();
            intent.setAction("com.meizu.safe.security.SHOW_APPSEC");
            intent.addCategory(Intent.CATEGORY_DEFAULT);
            intent.putExtra("packageName", context.getPackageName());
            context.startActivity(intent);
        } catch (Exception e) {
            toSetting(context);
        }
    }

    /**
     * 跳转到miui的权限管理页面
     */
    private static void gotoMiuiPermissionManager(Context context) {
        try { // MIUI 8
            Intent localIntent = new Intent();
            localIntent.setAction("miui.intent.action.APP_PERM_EDITOR");
            localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
            localIntent.putExtra("extra_pkgname", context.getPackageName());
            context.startActivity(localIntent);
        } catch (Exception e) {
            try { // MIUI 5/6/7
                Intent localIntent = new Intent("miui.intent.action.APP_PERM_EDITOR");
                localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
                localIntent.putExtra("extra_pkgname", context.getPackageName());
                context.startActivity(localIntent);
            } catch (Exception e1) { // 否则跳转到应用详情
                toSetting(context);
            }
        }
    }

    /**
     * 华为的权限管理页面
     */
    private static void gotoHuaweiPermissionManager(Context context) {
        try {
            Intent intent = new Intent();
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            ComponentName comp = new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity");//华为权限管理
            intent.setComponent(comp);
            context.startActivity(intent);
        } catch (Exception e) {
            toSetting(context);
        }
    }

}

Layout xml 代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal">
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:orientation="horizontal"
        android:gravity="center_horizontal">
        <ImageView
            android:id="@+id/button_camera"
            android:src="@drawable/icon_photo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <ImageView
            android:id="@+id/button_album"
            android:src="@drawable/icon_album"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <LinearLayout
        android:background="#000"
        android:layout_marginBottom="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/camera"
            android:layout_width="150dp"
            android:layout_height="250dp"/>
    </LinearLayout>
    <LinearLayout
        android:background="#000"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/album"
            android:layout_width="150dp"
            android:layout_height="250dp"/>
    </LinearLayout>
</LinearLayout>

AndroidManifest.xml中权限申请

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

权限申请流程

在这里插入图片描述
整理不易,还望有收获的同时点赞、收藏,谢谢。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

特立独行の猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值