概述
这里主要介绍如何调用系统的手机进行拍照,或者直接从相册中找图片。
学习使用系统自带的相机
权限
在Android4.4系统之前,访问SD卡的应用关联目录要声明权限,之后就可以不用声明了,为了兼容老版本,还是声明权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
代码一:准备工作
public static final int TAKE_PHOTO =1; //表示打开相机的标识符,知己定义的
private ImageView picture; //用来展示最后的图片
private Uri imageUri; //表示图片文件的真实路径
---------------接下来是打开相机前的准备工作------------------
File outputImage = new File(getExternalCacheDir(),"output_image.jpg");
//创建File对象,用于存贮拍照后的照片
//上述文件路径打印出来如下:
// /storage/emulated/0/Android/data/com.yuyi.viewevent/cache/output_image.jpg
try {
if (outputImage.exists()){
outputImage.delete();//如果已经有这个对象了,则删除。
}
outputImage.createNewFile();//在指定的路径下创建一个新的空文件
} catch (IOException e) {
e.printStackTrace();
}
if (Build.VERSION.SDK_INT >= 24){
imageUri=FileProvider
.getUriForFile(MainActivity.this,"com.yuyi.viewevent",outputImage);
//参数一是:Context对象,参数二:任意的字符串,参数三:file对象
//详细介绍,在最后面。
}else {
imageUri = Uri.fromFile(outputImage);
/**前面那个版本判断如果运行低于7.0的就直接把file对象转换成Uri对象,
得到一个本地真实路径,如果7.0以上,直接使用本地真实路径会认为不安全,
所以使用了FileProvider这个特殊的内容提供器,可以选择性地将封装过得
Uri共享给外部。
*/
}
//打印出imageUri的log如下: file:///storage/emulated/0/Android/data/com.yuyi.viewevent/cache/output_image.jpg
//隐世意图启动相机
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);//将uri传递进去
startActivityForResult(intent,TAKE_PHOTO);
代码二:对于拍照结果的处理
case TAKE_PHOTO:
if (resultCode == RESULT_OK){
try {
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
//将存在本地的图片进行读取成为bitmap
picture.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
break;
学习读取相册中的图片
代码一
public static final int CHOOSE_PHOTO=2; //作为从相册选取的标识符
private ImageView picture; //表示用于展示的图片
private Uri imageUri; //表示文件的真实路径
代码二
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_DENIED){
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);//动态获取权限
}else {
openAlbum();//此方法表示主动去打开相册
}
/**在这里面完成的是先进行运行时权限处理,动态去获取权限,因为相册中的照片都是存储
在SD卡上,我们要从SD卡中读取照片就要这个权限,表示授予了程序对SD卡读和写的能力。*/
获取运行时权限之后,再走这个重写的方法:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull
String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case 1:
if (grantResults.length > 0 &&grantResults[0] ==
PackageManager.PERMISSION_GRANTED){
openAlbum();//表示用户最后给了权限,可以去打开相册
}else {
Toast.makeText(this,"未获取权限",Toast.LENGTH_SHORT).show();
}
break;
}
}
接下来会走打开相册的方法:
private void openAlbum() {
Intent intent = new Intent("android.intent.action.GET_CONTENT");
intent.setType("image/*");
startActivityForResult(intent,CHOOSE_PHOTO);
}
当选择了照片之后,走下列方法:
case CHOOSE_PHOTO:
if (resultCode == RESULT_OK){
if (Build.VERSION.SDK_INT >=19){
handleImageOnkitKat(data);
//上述方法表示:4.4及以上系统使用这个方法处理图片
}else {
handleImageBeforKitKat(data);
//上述方法表示:4.4及以下系统使用这个方法处理图片
}
}
break;
//因为4.4以上系统的手机,选中相册的图片不再返回图片真实的Uri了,而是一个封装过的Uri,因此要对于这个Uri进行解析才可以,
先看看在4.4以上系统使用时候,如何处理图片:
将从相册得到的数据进行解析结果进行转换
/**因为返回的Uri是doucument类型的话,得到doucument id,如过这个uri的authority是
media格式的话,还需通过字符串分割方式取出后半部分才能得到真的数字id,取出的id用于构建新的Uri的条件语句,然后将值传入getImagePath(),就可以得到真实路径,最后进行展示就可以,别的类型的比如file和content类型的可以直接进行解析。
*/
private String getImagePath(Uri uri,String selection){
String path = null;
Cursor cursor = 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;
}
针对与4.4一下的版本
private void handleImageBeforKitKat(Intent data) {
Uri uri = data.getData();
String imagepath = getImagePath(uri,null);
displayImage(imagepath);
}
//由于没有封装过,可以直接进行解析。
展示图片的方法
private void displayImage(String imagePath){
if (imagePath != null){
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
picture.setImageBitmap(bitmap);
}else {
Toast.makeText(this,"失败了",Toast.LENGTH_SHORT).show();
}
}
//核心思想就是根据路径转换成为Bitmap图片
关于内容提供器的配置
首先:在清单文件中
<provider
android:authorities="com.yuyi.viewevent.fileprocider"
//authorities 属性的值必须和刚才FileProvider.getUriForFile()方法中的第二个参数一致
android:name="android.support.v4.content.FileProvider"
//name 的值是固定的
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
//内部使用的<mete_data>用来指定Uri的共享路径,并引用了一个@xml/file_paths的资源
</provider>
new->xml(文件夹名字)->file_paths.xml文件
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name = "my_images" path=""/>
</paths>
总结
这里只是讲了对于图片的获取,没有涉及对于图片裁剪的处理,内容主要是自学自《第一行代码》,感谢郭霖老师。