Android调用手机相机和相册

 

上面就是我的小项目的界面图,因为这里我主要写的调用手机相机和相册,所有我的圆形头像是我用的一个框架,就不用我们自己去写一个圆形的头像,地址如下: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.decodeFile(imagePath);
            headimageView.setImageBitmap(bitmap);
        }else {
            Toast.makeText(this,"获取图片失败",Toast.LENGTH_SHORT).show();
        }
    }
}


  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值