虽然调⽤摄像头拍照既⽅便⼜快捷,但我们并不是每次都需要去当场拍⼀张照⽚的。因为每个⼈的⼿机相册⾥应该都会存有许许多多张照⽚,直接从相册⾥选取⼀张现有的照⽚会⽐打开相机拍⼀张照⽚更加常⽤。⼀个优秀的应⽤程序应该将这两种选择⽅式都提供给⽤户,由⽤户来决定使⽤哪⼀种。下⾯我们就来看⼀下,如何才能实现从相册中选择照⽚的功能。
还是在CameraAlbumTest项⽬的基础上进⾏修改,编辑l⽂件,在布局中添加⼀个按钮⽤于从相册中选择照⽚,代码如下所⽰:<LinearLayout xmlns:android="schemas.android/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/take_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Take Photo"
/>
<ImageView
android:id="@+id/picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
/>
<Button
android:id="@+id/choose_from_album"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Choose from Album"
/>
</LinearLayout>
ample.cameraalbumtest;
import androidx.appcompat.app.AppCompatActivity;
app.ActivityCompat;
ontent.ContextCompat;
ontent.FileProvider;
import android.Manifest;
import android.annotation.TargetApi;
t.ContentUris;
t.Intent;
t.pm.PackageManager;
import android.database.Cursor;
aphics.Bitmap;
aphics.BitmapFactory;
import android.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
public static final int TAKE_PHOTO=1;//拍照
public static final int CHOOSE_PHOTO=2;//从相册取照⽚
private ImageView picture;
private Uri imageUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
//获取实例
takePhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/
/创建file对象,⽤于存储拍照后的图⽚
File outputImage=new File(getExternalCacheDir(),"output_image.jpg");//把图⽚进⾏命名
//调⽤getExternalCacheDir()可以得到⼿机SD卡的应⽤关联缓存⽬录
//所谓的应⽤关联缓存⽬录,就是指SD卡中专门⽤于存放当前应⽤缓存数据的位置
//具体的路径是/sdcard/Android/data/<package name>/cache
//因为从Android 6.0系统开始,读写SD卡被列为了危险权限,
// 如果将图⽚存放在SD卡的任何其他⽬录,都要进⾏运⾏时权限处理才⾏,⽽使⽤应⽤关联⽬录则可以跳过这⼀步。
try {
if (ists()) {//如果已经存在了图⽚,则删掉,
outputImage.delete();
}
}catch (IOException e){
e.printStackTrace();
}
//获取Uri对象
//这个Uri对象标识着output_image.jpg这张图⽚的本地真实路径。
if (Build.VERSION.SDK_INT >= 24) {
//调⽤FileProvider的getUriForFile() ⽅法将File 对象转换成⼀个封装过的Uri对象
imageUri = UriForFile(MainActivity.this,"ample.cameraalbumtest.fileprovider", outputImage);
//FileProvider则是⼀种特殊的内容提供器,它使⽤了和内容提供器类似的机制来对数据进⾏保护,
// 可以选择性地将封装过的Uri共享给外部,从⽽提⾼了应⽤的安全性。
//第⼀个参数要求传⼊Context 对象
//第⼆个参数可以是任意唯⼀的字符串(需要在l中声明)
//第三个参数则是我们刚刚创建的File 对象
} else {//若系统的版本低于Android7.0,则调⽤下⾯的⽅法将File对象转换为Uri对象
imageUri = Uri.fromFile(outputImage);
}
//启动相机程序
Intent intent= new Intent("dia.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);//指定图⽚的输出地址
startActivityForResult(intent,TAKE_PHOTO);//调⽤startActivityForResult() 来启动活动。
}
});
//从相册中取图⽚
Button chooseFromAlbum=(Button) findViewById(R.id.choose_from_album);
chooseFromAlbum.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {//定义该按钮点击事件
//申请⼀个运⾏时权限处理
//权限WRITE_EXTERNAL_STORAGE表⽰同时授予程序对SD卡读和写的能⼒。
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {
NAL_STORAGE},1);
}else {//授予了权限后,则调⽤openAlbum⽅法来获取图⽚
openAlbum();
}
}
});
}
//定义openAlbum()⽅法来获取图⽚
private void openAlbum(){
Intent intent =new Intent("android.intent.action.GET_CONTENT");//构建⼀个intent对象,并将它的action指定
intent.setType("image/*");
startActivityForResult(intent, CHOOSE_PHOTO);//打开相册程序,选择照⽚
//给第⼆个参数传⼊的值变成了CHOOSE_PHOTO
// 这样当从相册选择完图⽚回到onActivityResult() ⽅法时
// 就会进⼊CHOOSE_PHOTO 的case 来处理图⽚。
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,int[] grantResults){
switch (requestCode){
case 1:
if (grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
openAlbum();
}else {
Toast.makeText(this,"You denied the permission",Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
//使⽤startActivityForResult() 来启动活动的,
// 因此拍完照后会有结果返回到onActivityResult() ⽅法中。
//在此函数中显⽰图像
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case TAKE_PHOTO://拍照
if (resultCode == RESULT_OK) {//如果拍照成功
try {
// 将拍摄的照⽚显⽰出来
//可以调⽤BitmapFactory的decodeStream() ⽅法将output_image.jpg这张照⽚解析成Bitmap 对象
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
picture.setImageBitmap(bitmap);//将Bitmap对象,设置到ImageView中显⽰出来。
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
break;
case CHOOSE_PHOTO://打开相册
if (resultCode == RESULT_OK){
//判断⼿机的系统的版本号
if (Build.VERSION.SDK_INT>=19){
//4.4及以上系统使⽤这个⽅法处理图⽚
handleImageOnKitKat(data);
} else {
/
/ 4.4以下系统使⽤这个⽅法处理图⽚
handleImageBeforeKitKat(data);
}
}
default:
break;
}
}
//因为Android系统从4.4版本开始,选取相册中的图⽚不再返回图⽚真实的Uri了,⽽是⼀个封装过的Uri
// 因此如果是4.4版本以上的⼿机就需要对这个Uri进⾏解析才⾏。
@TargetApi(19)
private void handleImageOnKitKat(Intent data) {//⽤于解析Android4.4版本以上的封装过的Uri
String imagePath = null;
Uri uri = Data();
相册里图片怎么合并成一张图if (DocumentsContract.isDocumentUri(this, uri)) {
// 如果是document类型的Uri,则通过document id处理
String docId = DocumentId(uri);
if("com.dia.documents".Authority())) {
//如果Uri的authority是media格式的话,document id 还需要再进⾏⼀次解析
//要通过字符串分割的⽅式取出后半部分才能得到真正的数字id
String id = docId.split(":")[1]; // 解析出数字格式的id
String selection = MediaStore.Images.Media._ID + "=" + id;
imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_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(contentUri, null);
}
} else if ("content".Scheme())) {
// 如果是content类型的Uri,则使⽤普通⽅式处理
imagePath = getImagePath(uri, null);
} else if ("file".Scheme())) {
// 如果是file类型的Uri,直接获取图⽚路径即可
imagePath = Path();
}
displayImage(imagePath); // 根据图⽚路径显⽰图⽚
}
//它的Uri是没有封装过的,不需要任何解析
private void handleImageBeforeKitKat(Intent data) {
Uri uri = Data();
String imagePath = getImagePath(uri, null);//直接将Uri传⼊到getImagePath() ⽅法当中就能获取到图⽚的真实路径了
displayImage(imagePath);//让图⽚显⽰到界⾯上
}
//获取到图⽚的真实路径了
private String getImagePath(Uri uri, String selection) {
String path = null;
// 通过Uri和selection来获取真实的图⽚路径
Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
if (cursor != null) {
if (veToFirst()) {
path = ColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
}
return path;
//将图⽚显⽰到界⾯上
private void displayImage(String imagePath) {
if (imagePath != null) {
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
picture.setImageBitmap(bitmap);
} else {
Toast.makeText(this, "failed to get image", Toast.LENGTH_SHORT).show(); }
}
}
发布评论