您的位置:首页 > 移动开发 > Android开发

Android调用手机相机和相册

2018-01-04 12:49 246 查看

 


上面就是我的小项目的界面图,因为这里我主要写的调用手机相机和相册,所有我的圆形头像是我用的一个框架,就不用我们自己去写一个圆形的头像,地址如下:https://github.com/lopspower/CircularImageView

第一步:首先在你的gradle/app里加入依赖的库(最新版本就看上面的地址):

compile'com.mikhaellopez:circularimageview:3.0.2'
布局activity_main.xml布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
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"
tools:context="com.example.example.MainActivity">

<com.mikhaellopez.circularimageview.CircularImageView
android:id="@+id/headimageview"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@mipmap/ic_launcher"
android:layout_centerHorizontal="true"
app:civ_border_color="#000000"   //头像边框的颜色
app:civ_border_width="1dp"	//头像边框的宽度
app:civ_shadow="true"		//头像是否有阴影
app:civ_shadow_radius="5"	//阴影部分的大小
app:civ_shadow_color="#8BC34A"   //阴影的颜色
/>

<Button
android:id="@+id/button01"
android:layout_below="@+id/headimageview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="照相(button01)" />

<Button
android:id="@+id/button02"
android:layout_below="@+id/button01"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="相册(button02)" />

</RelativeLayout>


第二步:在你的AndroidManifest.xml加入访问权限以及内容器(内容器作用下面代码有注解)

//这访问SD卡的权限,因为Android 4.4之前访问需要权限问题 4.4开始就不需要,这里是为了兼容老版本的手机
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<provider
android:authorities="com.example.cameraalbumtest.fileprovider"
android:name="android.support.v4.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>




以及一个内容器provider(如上图),这因为在Android 7.0开始直接读取Uri是不安全,必须通过官方给的特定的内容器转换成封装的Uri对象。

第三步:在这我们的创建我项目目录里的xml下的file_paths资源如下:



<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path=""/>  //path代表共享路径,空值代表整个SD卡都可以共享。name可以随便取。
</paths>

最后一步

注意:Android 4.4及以上是先通过图库再来选图片,并不是真实图片路径,而4.4是直接选图片

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.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.Toast;
import com.mikhaellopez.circularimageview.CircularImageView;
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 Button button_01,button_02;
private Uri imageUri;
private CircularImageView headimageView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();//控件的初始化
initTakePhoto();//手机拍照
initChoosePhoto();//相册调用
}

private void initView() {
button_01=(Button)findViewById(R.id.button01);
button_02=(Button)findViewById(R.id.button02);
headimageView=(CircularImageView)findViewById(R.id.headimageview);
}

//照相按钮设置
private void initTakePhoto() {
button_01.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//创建File(路径,文件名字)对象,用于储存拍照后的图片
/*
getExternalCacheDir获取SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
getExternalFilesDir()获取SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据
*/
File outputImage=new File(getExternalCacheDir(),"output_iamge.jpg");
try{
//判断outputImage是否文件存在
if(outputImage.exists()){
outputImage.delete();
}
outputImage.createNewFile();
}catch(IOException e){
e.printStackTrace();
}

//不同Android版本进行处理
/*
* Android 7.0开始,直接读取本地Uri被认为是不安全的.
* 低于 Android 7.0只需要将File对象转换成Uri对象,而Uri就是标识output_iamge.jpg的路径
* 高于等于Android 7.0需要通过特定的内容容器FileProvider的getUriForFile()将File对象转换成封装的Uri对象
* getUriForFile()需要三个参数,第一个Context对象,第二个任意且唯一的字符串(自己随便取)但必须保持与你注册里表一致,第三个就是创建的File对象
* 别忘了在AdnroidManifest.xml进行内容容器FileProvider的注册,以及SD卡访问权限
* */

if(Build.VERSION.SDK_INT>=24){
imageUri = FileProvider.getUriForFile(MainActivity.this,"com.example.cameraalbumtest.fileprovider",outputImage);
}else {
imageUri = Uri.fromFile(outputImage);
}

//启动照相机
/*通过隐式Intent启动,并且给上个界面返回一个结果码TAKE_PHOTO=1
* 传递时最好传路径,直接传File,内存太大,并且Intent传值是有内存限制大小的*/
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
startActivityForResult(intent,TAKE_PHOTO);
}
});
}

//相册选择图片
private void initChoosePhoto() {
button_02.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,String[] permissions,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;
}
}

//在这里接收相册和照相产生不同的结果码,进行不同的操作
@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));
headimageView.setImageBitmap(bitmap);
}catch (FileNotFoundException e){
e.printStackTrace();
}
}
break;
case CHOOSE_PHOTO:
if(resultCode == RESULT_OK){
//判断手机系统版本号
if(Build.VERSION.SDK_INT >= 19){
//Android 4.4或以上处理图片方法
handleImageOnKitKat(data);
} else {
//Android 4.4以下处理图片方法
handleImageBeforeKitKat(data);
}
}
break;
}
}

//Android 4.4以上处理图片方法
@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以下处理图片方法
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 coursor = getContentResolver().query(uri,null,selection,null,null);
if(coursor != null){
if(coursor.moveToFirst()){
path = coursor.getString(coursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
coursor.close();
}
return path;
}

//展示图片
private void displayImage(String imagePath) {
if(imagePath != null){
Bitmap bitmap = BitmapFactory.de
8f9a
codeFile(imagePath);
headimageView.setImageBitmap(bitmap);
}else {
Toast.makeText(this,"获取图片失败",Toast.LENGTH_SHORT).show();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐