android相机拍照直接选取图片固然方便,但是更多的时候,我们需要从手机已有的图片中选择一张来使用。这次就练习如何从相册中选择图片吧。
首先在 activity_main.xml 文件中增加一个 Button,用来触发从相册中选择图片的功能。

<?xml version="1.0" encoding="utf-8"?>    

这段代码中的 android:id="@+id/button_choose_from_album" 按钮就是我们的主角了。
然后要在MainActivity.java中,加入从相册选图片的逻辑。
声明 Button 按钮

Button btnChooseFromAlbum = (Button)findViewById(R.id.button_choose_from_album);//相册选择图片按钮

添加按钮的点击事件

//打开相册选择图片        btnChooseFromAlbum.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);                }else{                    openAlbum();                }            }        });

这段代码中,先要判断 PackageManager.PERMISSION_GRANTED 权限的情况,如果没有权限就需要添加,有的话直接 openAlbum(); 打开相册。
ActivityCompat.requestPermissions 执行获取权限的操作,然后由用户选择是否给予权限,根据用户的选择,系统来决定是否可以继续执行 openAlbum()功能。这个就需要用到 onRequestPermissionsResult 了。代码的逻辑是,如果给了权限就执行 openAlbum(),如果不给权限就返回给用户没有此权限的提示即可。("You denied the permision.")

@Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {//        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        switch (requestCode){            case 1:                if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){                    openAlbum();                }else{                    Toast.makeText(this, "You denied the permision.", Toast.LENGTH_LONG).show();                }                break;            default:        }    }

openAlbum() 就是打开相册,代码逻辑很清晰吧?但是,还没完呢。因为如何打开还需要一些逻辑。先看 openAlbum() 的代码。

private void openAlbum() {        Intent intent = new Intent("android.intent.action.GET_CONTENT");        intent.setType("image/*");        startActivityForResult(intent, CHOOSE_PHOTO);//打开相册    }

这里的 Intent 是给相册准备的,然后调用 startActivityForResult() 才打开相册。这时出现的 CHOOSE_PHOTO 是给 onActivityResult 中判断走那个分支的条件参数。我们应该在 MainActivity.java 中增加一个全局变量声明

public static final int CHOOSE_PHOTO = 2;

在 onActivityResult 中增加switch case的 CHOOSE_PHOTO 分支。分之内根据不同的系统版本执行不同的代码逻辑。因为 android 4.4 是一个文件访问安全处理方式的分水岭,4.4以下的系统使用直接文件地址,4.4 及以上系统使用不再返回真实的图片地址了。所以,代码的处理方法就有所不同。4.4及以上系统需要对相册返回的图片地址进行解析。这里确定分作两个方法来分别处理 handleImageOnKitKat(data) 和 handeleImageBeforeKitKat(data)。

case CHOOSE_PHOTO:                if(resultCode == RESULT_OK){                    //判断手机系统版本号                    if(Build.VERSION.SDK_INT >= 19){                        //4.4及以上系统使用这个方法处理图片                        handleImageOnKitKat(data);                    }else{                        //4.4以下系统使用这个方法处理图片                        handeleImageBeforeKitKat(data);                    }                }                break;

在 handleImageOnKitKat(data) 中对地址进行解析,根据三种不同的提供Uri方式采用不同的方法。
document 类型的 Uri
content 类型的 uri
file 类型的 Uri

    @TargetApi(19)    private void handleImageOnKitKat(Intent data) {//        Toast.makeText(this,"到了handleImageOnKitKat(Intent data)方法了", Toast.LENGTH_LONG).show();        String imagePath = null;        Uri uri = data.getData();        if(DocumentsContract.isDocumentUri(this, uri)){            //如果是 document 类型的 Uri,则通过 document id 处理            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(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".equalsIgnoreCase(uri.getScheme())){            //如果是 content 类型的 uri , 则使用普通方式处理            imagePath = getImagePath(uri, null);        }else if("file".equalsIgnoreCase(uri.getScheme())){            //如果是 file 类型的 Uri,直接获取图片路径即可            imagePath = uri.getPath();        }        displayImage(imagePath);//显示选中的图片    }

注意那个 @TargetApi(19) ,因为我们的项目最小兼容系统设置的是 15,而代码中的 DocumentsContract.isDocumentUri 和 DocumentsContract.getDocumentId 有系统兼容性需要处理。
当我们通过各个途径,已经获取到图片路径的之后,自然就是显示图片了。于是最后一句代码就是调用 displayImage 方法来实现图片的显示了。
对于 handeleImageBeforeKitKat 就要简单的多了。直接取得地址显示。

    private void handeleImageBeforeKitKat(Intent data){        Uri uri = data.getData();        String imagePath = getImagePath(uri, null);        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(cursor.moveToFirst()){                path = cursor.getString(cursor.getColumnIndex(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_LONG).show();        }    }

MainActivity.java完整代码:

package com.cofox.mycameraalbum;import android.Manifest;import android.annotation.TargetApi;import android.content.ContentUris;import android.content.Intent;import android.content.pm.PackageManager;import android.database.Cursor;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.net.Uri;import android.os.Build;import android.provider.DocumentsContract;import android.provider.MediaStore;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.support.v4.content.FileProvider;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;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) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button btnTakePhoto = (Button) findViewById(R.id.button_take_photo);    //拍照按钮        Button btnChooseFromAlbum = (Button)findViewById(R.id.button_choose_from_album);//相册选择图片按钮        picture = (ImageView) findViewById(R.id.photo_pictrue);                 //图片控件,用来显示照片的。        //打开相机拍照        btnTakePhoto.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //创建File对象,用于存储拍照后的图片                File outputImage = new File(getExternalCacheDir(), "output_image.jpg");                try {                    if (outputImage.exists()) {                        outputImage.delete();                    }                    outputImage.createNewFile();                } catch (IOException e) {                    e.printStackTrace();                }                //android 7.0版本以下的系统,直接Uri.fromFile取得真实文件路径;7.0及以上版本的系统,使用fileprovider封装过的Uri再提供出去。                if (Build.VERSION.SDK_INT >= 24) {                    imageUri = FileProvider.getUriForFile(MainActivity.this, "com.cofox.mycameraalbum.fileprovider", outputImage);                } else {                    imageUri = Uri.fromFile(outputImage);                }                //启动相机程序                Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");                intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);                startActivityForResult(intent, TAKE_PHOTO);     //启动Intent活动,拍完照会有结果返回到onActivityResult()方法中。            }        });        //打开相册选择图片        btnChooseFromAlbum.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);                }else{                    openAlbum();                }            }        });    }    private void openAlbum() {        Intent intent = new Intent("android.intent.action.GET_CONTENT");        intent.setType("image/*");        startActivityForResult(intent, CHOOSE_PHOTO);//打开相册    }    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {//        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        switch (requestCode){            case 1:                if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){                    openAlbum();                }else{                    Toast.makeText(this, "You denied the permision.", Toast.LENGTH_LONG).show();                }                break;            default:        }    }    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        switch (requestCode) {            case TAKE_PHOTO:                if(resultCode == RESULT_OK){                    try {                        //将拍摄的照片显示出来                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));                        picture.setImageBitmap(bitmap);                    } 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以下系统使用这个方法处理图片                        handeleImageBeforeKitKat(data);                    }                }                break;            default:                break;        }    }    @TargetApi(19)    private void handleImageOnKitKat(Intent data) {//        Toast.makeText(this,"到了handleImageOnKitKat(Intent data)方法了", Toast.LENGTH_LONG).show();        String imagePath = null;        Uri uri = data.getData();        if(DocumentsContract.isDocumentUri(this, uri)){            //如果是 document 类型的 Uri,则通过 document id 处理            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(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".equalsIgnoreCase(uri.getScheme())){            //如果是 content 类型的 uri , 则使用普通方式处理            imagePath = getImagePath(uri, null);        }else if("file".equalsIgnoreCase(uri.getScheme())){            //如果是 file 类型的 Uri,直接获取图片路径即可            imagePath = uri.getPath();        }        displayImage(imagePath);//显示选中的图片    }    private void handeleImageBeforeKitKat(Intent data){        Uri uri = data.getData();        String imagePath = getImagePath(uri, null);        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(cursor.moveToFirst()){                path = cursor.getString(cursor.getColumnIndex(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_LONG).show();        }    }}

看一下AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>                                                                                                                

运行效果图片如下:


主界面 选择从哪里打开文件 选择图片 确认图片 图片正常显示

更多相关文章

  1. Android(安卓)Audio System
  2. android widget开发点滴
  3. Android(安卓)图片文件读取
  4. Android(安卓)模拟系统事件(三)
  5. 系统角度解读Android(安卓)P新特性
  6. Android中Service与Thread的区别
  7. Android开发之imageView图片按比例缩放的实现方法
  8. 手机Android系统有那些优势?
  9. Android屏幕分辨率占有率分析及应用

随机推荐

  1. Android(安卓)Studio failed to open by
  2. android内核编译方法
  3. 如何在android 中编译alsa-utils工具
  4. Ubuntu下搭建Android(安卓)NDK开发环境
  5. Android(安卓): 隐藏软键盘
  6. Android之Handler用法总结
  7. android下不规则多边形填充位图
  8. Android: Android(安卓)Light Sensor HOW
  9. Android(安卓)SplashActivity启动时黑屏
  10. Android包(android.view.animation)的简介