Android从相册获取图片

摘要:
在应用程序中,通常需要转到相册获取图片。每次,我都会忘记。现在我将做一个记录,以供将来参考。

应用中经常会有去相册获取图片的需求,每次总是会忘,现在这做个记录,以便以后查阅。

从应用去相册获取图片主要有以下几个步骤:

1、设置intent调用系统相册

2、进入相册选取图片,如果相册没有满意的图片,可以使用相机照相获取,最后返回数据到应用

3、应用获取图片后,调用裁剪程序对图片进行裁剪

4、返回裁剪的图片并显示出来

一、设置intent调用系统相册,并进入相册选取图片

/**
 * 调用相册
 */
private void goAlbums() {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("image/*");
        startActivityForResult(intent, SELECT_PIC);
 }

通过以上设置进入相册,返回的图片数据交由Activity的onActivityResult方法处理,请求码是SELECT_PIC,请求码为int型,可以随意设置

获取到返回的图片之后,下面便进入裁剪的步骤了

二、调用裁剪程序对图片进行裁剪

/**
     * 裁剪大图
     * @param context
     * @param uri
     */
    private void clipperBigPic(Context context, Uri uri) {
        if (null == uri) {
            return;
        }
        Intent intent = new Intent("com.android.camera.action.CROP");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            String url = PhotoClipperUtil.getPath(context, uri);
            intent.setDataAndType(Uri.fromFile(new File(url)), "image/*");
        }
        //发送裁剪命令
        intent.putExtra("crop", true);
        //X方向上的比例
        intent.putExtra("aspectX", 1);
        //Y方向上的比例
        intent.putExtra("aspectY", 1);
        //裁剪区的宽
        intent.putExtra("outputX", 124);
        //裁剪区的高
        intent.putExtra("outputY", 124);
        //是否保留比例
        intent.putExtra("scale", true);
        //返回数据
        intent.putExtra("return-data", true);
        //输出图片格式
        intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());
        //裁剪图片保存位置
        intent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
        startActivityForResult(intent, SELECT_CLIPPER_PIC);
    }

上面代码中的Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT,是因为KITKAT以上版本中返回的data数据和KITKAT以下版本的data数据可能不同,需要单独处理。

下面的代码便是正常处理,设置裁剪的参数,请求的数据同样交由onActivityResult处理

getTempUri为设置临时图片存储目录,代码如下:

private Uri getTempUri() {
        return Uri.fromFile(getTempFile());
    }

    /**
     * 临时图片保存路径
     * @return
     */
    private File getTempFile() {
        File file = new File(Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME);
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }

上面代码中中的IMAGE_FILE_NAME需要自己指定

上面代码中的PhotoClipperUtil类代码如下:

package tmg.gotoalarm;

import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;

public class PhotoClipperUtil {

    @SuppressLint("NewApi")
    public static String getPath(final Context context, final Uri uri) {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }

            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[] {
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context The context.
     * @param uri The Uri to query.
     * @param selection (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {
        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }


    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }
}

总的获取相册图片的流程如下:

mGoAlarmIv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //调用系统相册,进入相册获取图片
                goAlbums();
            }
        });    

进入相册后,应用的中转工作交由onActivityResult处理

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (data == null) {
            return;
        }
        switch (requestCode) {
            case SELECT_PIC:
               //获取图片后裁剪图片
                clipperBigPic(this, data.getData());
                break;
            case SELECT_CLIPPER_PIC:
               //获取图片后保存图片到本地,是否需要保存看情况而定
                saveBitmap(data);
                //显示图片
                showImage(mGoAlarmIv);
                break;
        }
    }

保存图片的代码如下:

/**
     * 保存图片
     * @param data
     */
    private void saveBitmap(Intent data) {
        Bundle bundle = data.getExtras();
        if (bundle != null) {
            Bitmap bitmap = bundle.getParcelable("data");
            File file = new File(Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME);
            try {
                file.createNewFile();
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
                fileOutputStream.flush();
                fileOutputStream.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

OK,以上便是第三方应用调用相册获取图片的整个流程。

免责声明:文章转载自《Android从相册获取图片》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇使用Python读写Kafka解决 Idea 下 Lombok 无法使用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

KVO的底层实现原理?如何取消系统默认的KVO并手动触发?

KVO是基于runtime机制实现的 当某个类的属性对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类(该类的子类),在这个派生类中重写基类中任何被观察属性的setter 方法。派生类在被重写的setter方法内实现真正的通知机制 如果原类为Person,那么生成的派生类名为NSKVONotifying_Person 每个类对象中都有一个...

[转]CURL常用命令

From:http://www.cnblogs.com/gbyukg/p/3326825.html 常用参数 -v/--verbose 小写的v参数,用于打印更多信息,包括发送的请求信息,这在调试脚本是特别有用。 -m/--max-time <seconds> 指定处理的最大时长 -H/--header <header> 指定请求头...

ASP.NET Core 认证与授权[1]:初识认证 (笔记)

原文链接:  https://www.cnblogs.com/RainingNight/p/introduce-basic-authentication-in-asp-net-core.html 在ASP.NET 4.X 中,我们最常用的是Forms认证,它既可以用于局域网环境,也可用于互联网环境,有着非常广泛的使用。但是它很难进行扩展,更无法与第三方认证...

Android系统编程入门系列之广播接收者BroadcastReceiver实现进程间通信

在前边几篇关于Android系统两个重要组件的介绍中,界面Activity负责应用程序与用户的交互,服务Service负责应用程序内部线程间的交互或两个应用程序进程之间的数据交互。看上去这两大组件就能满足日常应用程序的开发需求了,可是应用程序之间的交互,如果都使用服务Service中的AIDL规范,那每个应用程序本身岂不是要声明其他应用程序中的一些接口?这...

docker 挂载实现容器配置更改为外部文件

docker安装镜像后,每个服务都是独立的容器,容器与容器之间可以说是没关系,隔离独立的。 而且虚拟出来的这些容器里面的基本安装工具都是没有的,比如vi,vim等等。需要使用,还得安装处理。 那么我们安装的容器后我们怎么去修改配置文件。比如nginx我们安装好了之后,而且安装在多个容器实现主从后,我们不可能每台服务器的配置文件都去修改一下,这样就太麻烦了。...

HTTP1.1初识

Http(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议。   Http1.1版中,有一个持续连接(Persistent Connections)机制,其作为Http1.1中建立连接的缺省行为。通过这种连接,浏览器可以在建立一个连接之后,发送请求并得到回应,然后继续发送请求并再次得到回应(不用断开连接)。且客户端可以连续发送多个请求,而...