Android调用手机相机和相册

 

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

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

compile'com.mikhaellopez:circularimageview:3.0.2'

布局activity_main.xml布局文件如下:


 
 
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app= "http://schemas.android.com/apk/res-auto"
  4. xmlns:tools= "http://schemas.android.com/tools"
  5. android:layout_width= "match_parent"
  6. android:layout_height= "match_parent"
  7. tools:context= "com.example.example.MainActivity">
  8. <com.mikhaellopez.circularimageview.CircularImageView
  9. android:id= "@+id/headimageview"
  10. android:layout_width= "80dp"
  11. android:layout_height= "80dp"
  12. android:src= "@mipmap/ic_launcher"
  13. android:layout_centerHorizontal= "true"
  14. app:civ_border_color= "#000000" //头像边框的颜色
  15. app:civ_border_width= "1dp" //头像边框的宽度
  16. app:civ_shadow= "true" //头像是否有阴影
  17. app:civ_shadow_radius= "5" //阴影部分的大小
  18. app:civ_shadow_color="#8BC34A" //阴影的颜色
  19. />
  20. <Button
  21. android:id= "@+id/button01"
  22. android:layout_below= "@+id/headimageview"
  23. android:layout_width= "match_parent"
  24. android:layout_height= "wrap_content"
  25. android:text= "照相(button01)" />
  26. <Button
  27. android:id= "@+id/button02"
  28. android:layout_below= "@+id/button01"
  29. android:layout_width= "match_parent"
  30. android:layout_height= "wrap_content"
  31. android:text= "相册(button02)" />
  32. </RelativeLayout>

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


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

   
   
  1. <provider
  2. android:authorities= "com.example.cameraalbumtest.fileprovider"
  3. android:name= "android.support.v4.content.FileProvider"
  4. android:exported= "false"
  5. android:grantUriPermissions= "true">
  6. <meta-data
  7. android:name= "android.support.FILE_PROVIDER_PATHS"
  8. android:resource= "@xml/file_paths"/>
  9. </provider>


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

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



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

最后一步

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


MainActivity代码如下

  
  
  1. import android.Manifest;
  2. import android.annotation.TargetApi;
  3. import android.content.ContentUris;
  4. import android.content.Intent;
  5. import android.content.pm.PackageManager;
  6. import android.database.Cursor;
  7. import android.graphics.Bitmap;
  8. import android.graphics.BitmapFactory;
  9. import android.net.Uri;
  10. import android.os.Build;
  11. import android.provider.DocumentsContract;
  12. import android.provider.MediaStore;
  13. import android.support.v4.app.ActivityCompat;
  14. import android.support.v4.content.ContextCompat;
  15. import android.support.v4.content.FileProvider;
  16. import android.support.v7.app.AppCompatActivity;
  17. import android.os.Bundle;
  18. import android.view.View;
  19. import android.widget.Button;
  20. import android.widget.Toast;
  21. import com.mikhaellopez.circularimageview.CircularImageView;
  22. import java.io.File;
  23. import java.io.FileNotFoundException;
  24. import java.io.IOException;
  25. public class MainActivity extends AppCompatActivity {
  26. public static final int TAKE_PHOTO = 1;
  27. public static final int CHOOSE_PHOTO = 2;
  28. private Button button_01,button_02;
  29. private Uri imageUri;
  30. private CircularImageView headimageView;
  31. @Override
  32. protected void onCreate(Bundle savedInstanceState) {
  33. super.onCreate(savedInstanceState);
  34. setContentView(R.layout.activity_main);
  35. initView(); //控件的初始化
  36. initTakePhoto(); //手机拍照
  37. initChoosePhoto(); //相册调用
  38. }
  39. private void initView() {
  40. button_01=(Button)findViewById(R.id.button01);
  41. button_02=(Button)findViewById(R.id.button02);
  42. headimageView=(CircularImageView)findViewById(R.id.headimageview);
  43. }
  44. //照相按钮设置
  45. private void initTakePhoto() {
  46. button_01.setOnClickListener( new View.OnClickListener() {
  47. @Override
  48. public void onClick(View v) {
  49. //创建File(路径,文件名字)对象,用于储存拍照后的图片
  50. /*
  51. getExternalCacheDir获取SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
  52. getExternalFilesDir()获取SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据
  53. */
  54. File outputImage= new File(getExternalCacheDir(), "output_iamge.jpg");
  55. try{
  56. //判断outputImage是否文件存在
  57. if(outputImage.exists()){
  58. outputImage.delete();
  59. }
  60. outputImage.createNewFile();
  61. } catch(IOException e){
  62. e.printStackTrace();
  63. }
  64. //不同Android版本进行处理
  65. /*
  66. * Android 7.0开始,直接读取本地Uri被认为是不安全的.
  67. * 低于 Android 7.0只需要将File对象转换成Uri对象,而Uri就是标识output_iamge.jpg的路径
  68. * 高于等于Android 7.0需要通过特定的内容容器FileProvider的getUriForFile()将File对象转换成封装的Uri对象
  69. * getUriForFile()需要三个参数,第一个Context对象,第二个任意且唯一的字符串(自己随便取)但必须保持与你注册里表一致,第三个就是创建的File对象
  70. * 别忘了在AdnroidManifest.xml进行内容容器FileProvider的注册,以及SD卡访问权限
  71. * */
  72. if(Build.VERSION.SDK_INT>= 24){
  73. imageUri = FileProvider.getUriForFile(MainActivity. this, "com.example.cameraalbumtest.fileprovider",outputImage);
  74. } else {
  75. imageUri = Uri.fromFile(outputImage);
  76. }
  77. //启动照相机
  78. /*通过隐式Intent启动,并且给上个界面返回一个结果码TAKE_PHOTO=1
  79. * 传递时最好传路径,直接传File,内存太大,并且Intent传值是有内存限制大小的*/
  80. Intent intent = new Intent( "android.media.action.IMAGE_CAPTURE");
  81. intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
  82. startActivityForResult(intent,TAKE_PHOTO);
  83. }
  84. });
  85. }
  86. //相册选择图片
  87. private void initChoosePhoto() {
  88. button_02.setOnClickListener( new View.OnClickListener() {
  89. @Override
  90. public void onClick(View v) {
  91. if(ContextCompat.checkSelfPermission(MainActivity. this,
  92. Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
  93. ActivityCompat.requestPermissions(MainActivity. this,
  94. new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
  95. } else {
  96. openAlbum();
  97. }
  98. }
  99. });
  100. }
  101. //打开相册
  102. private void openAlbum(){
  103. Intent intent = new Intent( "android.intent.action.GET_CONTENT");
  104. intent.setType( "image/*");
  105. startActivityForResult(intent, CHOOSE_PHOTO);
  106. }
  107. @Override
  108. public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults) {
  109. switch (requestCode){
  110. case 1:
  111. if(grantResults.length > 0 && grantResults[ 0] == PackageManager.PERMISSION_GRANTED){
  112. openAlbum();
  113. } else {
  114. Toast.makeText( this, "相册打开失败",Toast.LENGTH_SHORT).show();
  115. }
  116. break;
  117. }
  118. }
  119. //在这里接收相册和照相产生不同的结果码,进行不同的操作
  120. @Override
  121. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  122. switch (requestCode){
  123. case TAKE_PHOTO:
  124. if (resultCode == RESULT_OK){
  125. try{
  126. //显示拍摄照片
  127. Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
  128. headimageView.setImageBitmap(bitmap);
  129. } catch (FileNotFoundException e){
  130. e.printStackTrace();
  131. }
  132. }
  133. break;
  134. case CHOOSE_PHOTO:
  135. if(resultCode == RESULT_OK){
  136. //判断手机系统版本号
  137. if(Build.VERSION.SDK_INT >= 19){
  138. //Android 4.4或以上处理图片方法
  139. handleImageOnKitKat(data);
  140. } else {
  141. //Android 4.4以下处理图片方法
  142. handleImageBeforeKitKat(data);
  143. }
  144. }
  145. break;
  146. }
  147. }
  148. //Android 4.4以上处理图片方法
  149. @TargetApi( 19)
  150. private void handleImageOnKitKat(Intent data) {
  151. String imagePath = null;
  152. Uri uri = data.getData();
  153. if(DocumentsContract.isDocumentUri( this, uri)){
  154. //如果document类型Uri,则通过document id处理
  155. String docId = DocumentsContract.getDocumentId(uri);
  156. if( "com.android.providers.media.documents".equals(uri.getAuthority())){
  157. String id = docId.split( ":")[ 1]; //解析数字格式的id
  158. String selection = MediaStore.Images.Media._ID + "=" + id;
  159. imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection);
  160. } else if( "com.android.providers.downloads.documents".equals(uri.getAuthority())){
  161. Uri contentUri= ContentUris.withAppendedId(Uri.parse( "content://downloads/public_downloads"),Long.valueOf(docId));
  162. imagePath = getImagePath(contentUri, null);
  163. }
  164. } else if( "content".equalsIgnoreCase(uri.getScheme())){
  165. //如果content类型的Uri,则使用普通的方式处理
  166. imagePath = getImagePath(uri, null);
  167. } else if ( "file".equalsIgnoreCase(uri.getScheme())){
  168. //如果是file类型的Uri,直接获取图片的路径即可
  169. imagePath = uri.getPath();
  170. }
  171. displayImage(imagePath); //根据图片路径显示图片
  172. }
  173. //Android 4.4以下处理图片方法
  174. private void handleImageBeforeKitKat(Intent data) {
  175. Uri uri = data.getData();
  176. String imagePath = getImagePath(uri, null);
  177. displayImage(imagePath);
  178. }
  179. private String getImagePath(Uri uri, String selection) {
  180. String path = null;
  181. //通过Uri和selection来获取真实的图片的路径
  182. Cursor coursor = getContentResolver().query(uri, null,selection, null, null);
  183. if(coursor != null){
  184. if(coursor.moveToFirst()){
  185. path = coursor.getString(coursor.getColumnIndex(MediaStore.Images.Media.DATA));
  186. }
  187. coursor.close();
  188. }
  189. return path;
  190. }
  191. //展示图片
  192. private void displayImage(String imagePath) {
  193. if(imagePath != null){
  194. Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
  195. headimageView.setImageBitmap(bitmap);
  196. } else {
  197. Toast.makeText( this, "获取图片失败",Toast.LENGTH_SHORT).show();
  198. }
  199. }
  200. }


[转载自](https://blog.csdn.net/qq_37238649/article/details/78969720)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值