在Android原生态开发过程中,往往会设计到用户头像的设置问题,一般来讲设置头像需要用到拍照、获取照片、存储照片、裁剪照片、显示照片等问题,本文将一步一步的进行说明讲解。
首先需要强调几点我在开发过程中遇到的问题。
- 权限问题,在Android6.0以后,Android的权限获取不再是通过AndroidManifest.xml文件中声明获取,为了安全行,APP获取Android的高位权限需要动态获取。系统权限默认是禁止的,需要申请。动态申请权限的说明见该文章
- 调用顺序问题,在开发过程中一定要注意代码的执行顺序,一定要在用户获取指定权限之后再调用相关功能,注意权限的调用和授权是异步于主线程的,也就是说,如果你在调用权限后紧跟着调用相机的操作的还,系统会导致闪退,因为调用权限后主线程并没有等待授权完成而继续执行,这就导致在调用相机时没有权限。
- Uri和Bitmap的区别以及使用,在使用裁剪功能时,我们通常使用Uri对象来指明资源,Bitmap占用内存而且效率低下,但是使用Uri的过程中需要注意,如果我们在调用裁剪功能前就指明了Uri参数,那么返回的Intent对象中的getData方法将返回为null。
- Android系统路径及存储空间问题,Android分为内部存储和外部存储,而且在Android开发过程中设计到大量路径问题,Android内外部存储及路径问题见该文章
下面进行具体的功能实现。
1.权限设置
在该功能的开发过程中需要使用到相机权限、存储空间读写权限。
权限获取可以大致分为两部:在manifest文件中声明权限,在activity中动态获取权限。
- manifest文件的设置
<!-- 读写权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 相机权限 -->
<uses-permission android:name="android.permission.CAMERA"/>
- 在Java代码中动态申请权限
动态申请权限代码一般放在程序运行的首界面,在首界面运行时就向用户申请需要的各种权限,而在动态申请的过程中,又需要实现两步:申请权限和处理用户授权信息。
申请权限的代码
//一下代码可以直接在首页面中的onCreate方法中调用requestPermission()
//申请权限返回码
private final int REQUEST_PERMISSION_CODE = 0x01;
//可以使用Manifest.permission.***表示
private final String[] permissions = new String[]{
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.CAMERA"};
/**
* 动态申请权限
*/
private void requestPermission() {
List<String> requestPermissions = new ArrayList<>();
for (String permission:permissions) {
//判断用户是否已经授权
if (ContextCompat.checkSelfPermission(this,
permission) != PackageManager.PERMISSION_GRANTED){
//如果用户没有授权
requestPermissions.add(permission);
}
}
/**
* 用户动态授权
* 执行该代码后,将进入授权界面,此时主线程继续执行
* 用户授权结果将被onRequestPermissionsResult方法接受,如果需要处理则重写该方法
*/
if(requestPermissions.size() != 0){
String[] strs = requestPermissions.toArray(new String[requestPermissions.size()]);
ActivityCompat.requestPermissions(this, strs, REQUEST_PERMISSION_CODE);
}
}
处理授权结果
/**
* @param requestCode The request code passed in {@link #requestPermissions(String[], int)}.
* @param permissions The requested permissions. Never null.
* @param grantResults The grant results for the corresponding permissions
*/
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//授权结果的处理逻辑
}
上述过程完成了权限申请过程,如果用户授权允许调用相机,则后续可以直接调用相机进行相关操作。