从相册或拍照更换图片功能的实现:(取图无裁剪功能)

获取图片方式: (类似更换头像的效果)

1、手机拍照 选择图片;

2、相册选取图片;

本文只是简单实现该功能,页面展示有些简陋,运行效果图如下:

创建xml布局文件(activity_main.xml ): 头部两个Button按钮,一个控制从相册选择照片,一个控制启动相册拍照选择图片。底部为一个ImageVIew,用于展示刚刚选择的图片。

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:padding="16dp"

tools:context=".MainActivity">

android:layout_width="match_parent"

android:layout_height="wrap_content">

android:id="@+id/btn_photo"

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_weight="1"

android:background="@android:color/holo_red_light"

android:text="相册选取"

android:textColor="#FFF"

android:textSize="16sp" />

android:id="@+id/btn_camera"

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_marginLeft="16dp"

android:layout_weight="1"

android:background="@android:color/holo_red_light"

android:text="拍照"

android:textColor="#FFF"

android:textSize="16sp" />

android:id="@+id/image_show"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_gravity="center_horizontal"

android:layout_margin="6dp" />

Android 4.4系统之前, 访问SD卡的应用关联目录需要声明权限的,从4.4系统开始不再需要权限声明。相关权限变成动态申请。

第一部分:拍照获取图片

我们将拍照的图片放在SD卡关联缓存目录下。调用getExternalCacheDir()方法得到关联缓存目录, 具体的路径是/sdcard/Android/data//cache。 那么为什么要使用应用关联缓目录来存放图片呢?因为从Android 6.0系统开始, 读写SD卡被列为了危险权限, 如果将图片存放在SD卡的任何其他目录, 都要进行运行时权限处理, 使用应用关联

目录则可以跳过这一步。

**

* 拍照 或 从相册获取图片

*/

public class MainActivity extends AppCompatActivity {

private Button btn_camera;

private ImageView imageView;

public static final int TAKE_CAMERA = 101;

private Uri imageUri;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

btn_camera = (Button) findViewById(R.id.btn_camera);

imageView = (ImageView) findViewById(R.id.image_show);

//通过摄像头拍照

btn_camera.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

// 创建File对象,用于存储拍照后的图片

//存放在手机SD卡的应用关联缓存目录下

File outputImage = new File(getExternalCacheDir(), "output_image.jpg");

/* 从Android 6.0系统开始,读写SD卡被列为了危险权限,如果将图片存放在SD卡的任何其他目录,

都要进行运行时权限处理才行,而使用应用关联 目录则可以跳过这一步

*/

try {

if (outputImage.exists()) {

outputImage.delete();

}

} catch (Exception e) {

e.printStackTrace();

}

/*

7.0系统开始,直接使用本地真实路径的Uri被认为是不安全的,会抛 出一个FileUriExposedException异常。

而FileProvider则是一种特殊的内容提供器,它使用了和内 容提供器类似的机制来对数据进行保护,

可以选择性地将封装过的Uri共享给外部,从而提高了 应用的安全性

*/

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

//大于等于版本24(7.0)的场合

imageUri = FileProvider.getUriForFile(MainActivity.this, "com.feige.pickphoto.fileprovider", outputImage);

} else {

//小于android 版本7.0(24)的场合

imageUri = Uri.fromFile(outputImage);

}

//启动相机程序

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

//MediaStore.ACTION_IMAGE_CAPTURE = android.media.action.IMAGE_CAPTURE

intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

startActivityForResult(intent, TAKE_CAMERA);

}

});

@Override

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {

switch (requestCode) {

case TAKE_CAMERA:

if (resultCode == RESULT_OK) {

try {

// 将拍摄的照片显示出来

Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));

imageView.setImageBitmap(bitmap);

} catch (FileNotFoundException e) {

e.printStackTrace();

}

}

break;

default:

break;

}

}

}

从Android 7.0开始, 直接使用本地真实路径的Uri被认为是不安全的, 会抛出一个FileUriExposedException异常。 FileProvider则是一种特殊的内容提供器, 它使用了和内容提供器类似的机制来对数据进行保护, 可以选择性地将封装过的Uri共享给外部, 从而提高了应用的安全性。

首先要在AndroidManifest.xml中对内容提供器进行注册了:

package="com.feige.pickphoto">

android:allowBackup="true"

android:icon="@mipmap/ic_launcher"

android:label="@string/app_name"

android:roundIcon="@mipmap/ic_launcher_round"

android:supportsRtl="true"

android:theme="@style/AppTheme">

android:name="android.support.v4.content.FileProvider"

android:authorities="com.feige.pickphoto.fileprovider"

android:exported="false"

android:grantUriPermissions="true">

android:name="android.support.FILE_PROVIDER_PATHS"

android:resource="@xml/file_paths" />

创建file_paths 资源文件:在res目录上右击——> new ——> Directory创建xml文件夹,然后在xml文件夹里新建file_paths.xml文件:

name="my_images"

path="." />

第二部分:从相册获取图片

/**

* 拍照 或 从相册获取图片

*/

public class MainActivity extends AppCompatActivity {

private Button choose_photo;

private ImageView imageView;

public static final int PICK_PHOTO = 102;

private Uri imageUri;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

choose_photo = (Button) findViewById(R.id.btn_photo);

imageView = (ImageView) findViewById(R.id.image_show);

//从相册选择图片

choose_photo.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}, 101);

} else {

//打开相册

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);

//Intent.ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT"

intent.setType("image/*");

startActivityForResult(intent, PICK_PHOTO); // 打开相册

}

}

});

}

@Override

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {

switch (requestCode) {

case PICK_PHOTO:

if (resultCode == RESULT_OK) { // 判断手机系统版本号

if (Build.VERSION.SDK_INT >= 19) {

// 4.4及以上系统使用这个方法处理图片

handleImageOnKitKat(data);

} else {

// 4.4以下系统使用这个方法处理图片

handleImageBeforeKitKat(data);

}

}

break;

default:

break;

}

}

@TargetApi(19)

private void handleImageOnKitKat(Intent data) {

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);

}

/**

* android 4.4以前的处理方式

* @param data

*/

private void handleImageBeforeKitKat(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);

imageView.setImageBitmap(bitmap);

} else {

Toast.makeText(this, "获取相册图片失败", Toast.LENGTH_SHORT).show();

}

}

}

共用拍照取图的FileProvider内容提供器。

*********完整MainActivity代码:

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.Nullable;

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;

/**

* 拍照 或 从相册获取图片

*/

public class MainActivity extends AppCompatActivity {

private Button choose_photo;

private Button btn_camera;

private ImageView imageView;

public static final int TAKE_CAMERA = 101;

public static final int PICK_PHOTO = 102;

private Uri imageUri;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

choose_photo = (Button) findViewById(R.id.btn_photo);

btn_camera = (Button) findViewById(R.id.btn_camera);

imageView = (ImageView) findViewById(R.id.image_show);

//通过摄像头拍照

btn_camera.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

// 创建File对象,用于存储拍照后的图片

//存放在手机SD卡的应用关联缓存目录下

File outputImage = new File(getExternalCacheDir(), "output_image.jpg");

/** 从Android 6.0系统开始,读写SD卡被列为了危险权限,如果将图片存放在SD卡的任何其他目录,

*都要进行运行时权限处理才行,而使用应用关联 目录则可以跳过这一步

*/

try {

if (outputImage.exists()) {

outputImage.delete();

}

} catch (Exception e) {

e.printStackTrace();

}

/**

*7.0系统开始,直接使用本地真实路径的Uri被认为是不安全的,会抛 出一个FileUriExposedException异常。

*而FileProvider则是一种特殊的内容提供器,它使用了和内 容提供器类似的机制来对数据进行保护,

*可以选择性地将封装过的Uri共享给外部,从而提高了 应用的安全性

*/

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

//大于等于版本24(7.0)的场合

imageUri = FileProvider.getUriForFile(MainActivity.this, "com.feige.pickphoto.fileprovider", outputImage);

} else {

//小于android 版本7.0(24)的场合

imageUri = Uri.fromFile(outputImage);

}

//启动相机程序

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

//MediaStore.ACTION_IMAGE_CAPTURE = android.media.action.IMAGE_CAPTURE

intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

startActivityForResult(intent, TAKE_CAMERA);

}

});

//从相册选择图片

choose_photo.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}, 101);

} else {

//打开相册

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);

//Intent.ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT"

intent.setType("image/*");

startActivityForResult(intent, PICK_PHOTO); // 打开相册

}

}

});

}

@Override

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {

switch (requestCode) {

case TAKE_CAMERA:

if (resultCode == RESULT_OK) {

try {

// 将拍摄的照片显示出来

Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));

imageView.setImageBitmap(bitmap);

} catch (FileNotFoundException e) {

e.printStackTrace();

}

}

break;

case PICK_PHOTO:

if (resultCode == RESULT_OK) { // 判断手机系统版本号

if (Build.VERSION.SDK_INT >= 19) {

// 4.4及以上系统使用这个方法处理图片

handleImageOnKitKat(data);

} else {

// 4.4以下系统使用这个方法处理图片

handleImageBeforeKitKat(data);

}

}

break;

default:

break;

}

}

@TargetApi(19)

private void handleImageOnKitKat(Intent data) {

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);

}

/**

* android 4.4以前的处理方式

* @param data

*/

private void handleImageBeforeKitKat(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);

imageView.setImageBitmap(bitmap);

} else {

Toast.makeText(this, "获取图片失败", Toast.LENGTH_SHORT).show();

}

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

android内容提供器读取图片,android实现拍照或从相册选取图片相关推荐

  1. Android 内容提供器---简介

    内容提供器管理结构化的数据集的访问.它们封装数据.提供定义数据安全的机制.内容提供器是用运行在另一个进程中的代码连接另一个进程中的数据的标准接口. 当你想要访问内容提供器中的数据时,使用应用程序的Co ...

  2. Android 内容提供器---内容提供器基础(内容的统一资源标识(URIs))

    内容URI是在提供器中标识数据统一资源标识.内容的统一资源标识包括完整的提供器的符号名和所指向的一个表名.当你调用一个客户端方法来访问提供器中的一个表时,这个表的内容的统一资源标识就应该是参数之一. ...

  3. Android内容提供器——运行权限

    程序运行是的权限分为两种,一种是普通权限,一种是危险权限.普通权限的话可以直接使用,只有危险权限需要询问用户的同意. 危险权限分组以及组内权限如下: 注:危险权限同一组内有一项权限被授权,则一组权限都 ...

  4. Android内容提供器的应用,基于Android的智能终端应用防护系统短信过滤子模块的设计与实现...

    摘要: 智能终端随着3G业务的推广而普及,在各种平台的竞争中,Android逐渐占据了主流,谷歌学习苹果的应用商店模式,推出了自己的应用商城.面对应用市场的繁荣,用户的终端安装了形形色色的应用,许多安 ...

  5. 第七章:跨程序共享数据-探究内容提供器

    运行时权限 Android 6.0 之后的系统提供了两种权限: 普通权限.例如:访问网络状态.监控开机是否完成等.这种权限会在安装 APP 时询问用户是否同意. 危险权限,也就是说运行时权限,需要在程 ...

  6. Android入门(13)| Android权限 与 内容提供器

    文章目录 普通权限与危险权限 运行时申请权限 内容提供器 运用安卓封装好的内容提供器 自实现的内容提供器 概念 实现 普通权限与危险权限 主要用于不同应用程序之间在保证被访数据的安全性的基础上,实现数 ...

  7. 系出名门Android(9) - 数据库支持(SQLite), 内容提供器(ContentProvider)

    [索引页] [×××] 系出名门Android(9) - 数据库支持(SQLite), 内容提供器(ContentProvider) 作者:webabcd 介绍 在 Android 中使用 SQLit ...

  8. android 提供的方法,Android编程之创建自己的内容提供器实现方法

    本文实例讲述了Android编程之创建自己的内容提供器实现方法.分享给大家供大家参考,具体如下: 我们学习了如何在自己的程序中访问其他应用程序的数据.总体来说思 路还是非常简单的,只需要获取到该应用程 ...

  9. Android Studio调用python读取图片(使用服务器paddlehub处理图片)

    Android Studio调用python读取图片 一.主要任务 二.环境配置 1.创建一个android studio项目 2.配置项目gradle 3.配置app下的gradle 三.demo测 ...

最新文章

  1. PacBio SMRT Sequencing
  2. 对于python来说、一个模块就是一个文件-PYTHON中的包和模块
  3. office2007安装提示“Windows Installer 服务不能更新一个或多个受保护的Windows文件...
  4. 写给初学者的Tensorflow介绍
  5. WPF 路由事件初步
  6. 阿里云服务器Svn-Server无法连接,阿里云服务器SVNServer配置
  7. 用qss 来控制qlabel显示字体的位置_Word表格总填不好,这些技巧轻松来拯救
  8. ionic集成jPush极光推送
  9. Linux操作系统笔记——Shell变量
  10. 就业形势如此的严峻,你为何不努力?
  11. MYSQL的COMMIT和ROLLBACK
  12. 我以为内卷是外包的反义词!
  13. SpringCloud高级应用(OpenFeign Ribbon Steam Sleuth+Zipkin)
  14. C语言:判断对错(简化版)
  15. 老徐WEB:js入门学习 - javascript语句
  16. NetApp FAS混合式Flash Array
  17. windows环境下利用python进行CGI配置
  18. 简述LoRa和NB-IoT的技术特点,他们有哪些共同点和差异点,在生活中LoRa和NB-IoT各有哪些适合的应用场景?
  19. 一个简单的2022春节倒计时
  20. linux 远程连接工具——MTPuTTY

热门文章

  1. 【转】Linux的僵尸进程解决攻略
  2. 电大计算机考试将网页保存到桌面,电大计算机网考小抄.pdf
  3. 台湾域名总量一周统计:9月第一周新增59个
  4. Stanford Parser的学习之开篇(一)
  5. mysql-------视图
  6. adaptec SCSI卡管理和配置选项
  7. 树莓派Python 3.x+TensorFlow 1.9.0
  8. GDAL C#版本 安全透明方法问题解决方案
  9. JavaScript(四)字符串类型
  10. 详解:Oracle数据库的分区表