
上面就是我的小项目的界面图,因为这里我主要写的调用手机相机和相册,所有我的圆形头像是我用的一个框架,就不用我们自己去写一个圆形的头像,地址如下: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>

第三步:在这我们的创建我项目目录里的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();
- }
- }
- }
本文详细介绍了在Android应用中实现相机拍照和从相册选取图片的功能,包括使用CircularImageView库实现圆形头像,以及在不同Android版本下处理图片路径的复杂性。通过实例代码展示了如何适配Android7.0及以上的安全Uri读取方式。

7981

被折叠的 条评论
为什么被折叠?



