首页 > 其他分享 >Android应用中是怎么调用系统相册中的照片的

Android应用中是怎么调用系统相册中的照片的

时间:2024-01-19 14:32:58浏览次数:25  
标签:String 相册 中是 路径 uri path Android null


Android应用中是怎么调用系统相册中的照片的_harmonyos

Android应用中是怎么调用系统相册中的照片的?相信很多没有经验的人对此束手无策,
为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
使用步骤

这里我是通过一个简单的demo来讲解怎么去实现这个功能。首先看布局:

<Button
  android:id="@+id/button2"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginTop="5dp"
  android:layout_marginEnd="52dp"
  android:layout_marginRight="52dp"
  android:text="choose"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintTop_toTopOf="parent" />

 <ImageView
  android:id="@+id/imageView"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginTop="29dp"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintStart_toStartOf="parent"
  app:layout_constraintTop_toBottomOf="@+id/button"
  app:srcCompat="@mipmap/ic_launcher_round" />

很简单,就是一个按钮和一个imageView。然后接下来让我们想想这个功能怎么去实现:

首先打开相册,那么肯定要通过隐式启动相册activity;然后相册返回一个路径,我们就拿这个路径把路径上对应的照片展示出来。思路挺简单的,让我们写写看: 首先看代码:

private Uri imageUri;
 private ImageView imageView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  imageView = findViewById(R.id.imageView);
  Button button1 = findViewById(R.id.button2);
  button1.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();
    }
   }
  });
  }
//获取权限的结果
@Override
 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  if (requestCode == 1){
   if (grantResults.length>0&&grantResults[0] == PackageManager.PERMISSION_GRANTED) openAlbum();
   else Toast.makeText(MainActivity.this,"你拒绝了",Toast.LENGTH_SHORT).show();
  }
 }

//启动相册的方法
private void openAlbum(){
  Intent intent = new Intent("android.intent.action.GET_CONTENT");
  intent.setType("image/*");
  startActivityForResult(intent,2);
 }

这里先初始化控件,然后动态申请权限,因为我们要读取照片肯定是要读取内存的权限,记得在AndroidManifest中要写明权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

获取权限后就打开相册选择。相册对应的action是android.intent.action.GET_CONTENT,setType(“image/*”)这个方法表示把所有照片显示出来,然后开启活动。启动活动选择完照片后就会返回一个intent到onActivityResult方法中,所以接下来的主要工作就是如果获取到返回的路径。

我们知道在安卓4.4以后是不能把文件的真实路径直接给别的应用的,所以返回的uri是经过封装的,所以我们要进行解析取出里面的路径。所以这里我们要进行判断安卓版本来进行不同的逻辑,先看代码:

@Override
 protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
 if (requestCode == 2){
 //判断安卓版本
    if (resultCode == RESULT_OK&&data!=null){
    if (Build.VERSION.SDK_INT>=19)
    handImage(data);
    else handImageLow(data);
   }
  }
 }

//安卓版本大于4.4的处理方法
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
 private void handImage(Intent data){
  String path =null;
  Uri uri = data.getData();
  //根据不同的uri进行不同的解析
  if (DocumentsContract.isDocumentUri(this,uri)){
   String docId = DocumentsContract.getDocumentId(uri);
   if ("com.android.providers.media.documents".equals(uri.getAuthority())){
    String id = docId.split(":")[1];
    String selection = MediaStore.Images.Media._ID+"="+id;
    path = 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));
    path = getImagePath(contentUri,null);
   }
  }else if ("content".equalsIgnoreCase(uri.getScheme())){
   path = getImagePath(uri,null);
  }else if ("file".equalsIgnoreCase(uri.getScheme())){
   path = uri.getPath();
  }
  //展示图片
  displayImage(path);
 }


//安卓小于4.4的处理方法
private void handImageLow(Intent data){
  Uri uri = data.getData();
  String path = getImagePath(uri,null);
  displayImage(path);
 }

//content类型的uri获取图片路径的方法
private String getImagePath(Uri uri,String selection) {
  String path = null;
  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,"fail to set image",Toast.LENGTH_SHORT).show();
  }
 }

上面的代码很多但是不要慌,咱们一个一个来,不难理解的。首先我们知道不同的版本有两个不同的方法来展示图片,就是:handImage和handImageLow。content类型的uri通过getImagePath这个方法来获取真实路径,真实路径通过displayImage这个方法就可以展示出来了。所以主要的工作就是怎么拿到真实路径。现在思路清晰了,让我们一个个来看:

首先来看一下两个工具方法:getImagePath和displayImage。

  • getImagePath学过内容提供器会知道这个就是通过内容提供器来获取数据。通过这个uri以及selection获取到一个Cursor对象。Cursor是什么呢?不了解的读者可以查看这篇博客Android中的Cursor。然后通过这个Cursor对象的MediaStore.Images.Media.DATA这个参数就可以获取到真实路径了。
  • displayImage这个方法收一个真实路径字符串,直接通过BitmapFactory.decodeFile这个方法获取到Bitmap再显示出来就行了

了解了工具方法后,我们的目的就很明确啦:content类型的uri或者真实路径的String。 首先是版本低于4.4的,因为返回的是真实的uri,也就是content开头的那个,所以直接通过getImagePath获取真实路径再通过displayImage展示即可。

接下来这个可能看起来有点头疼,因为要解析不同类型的Uri。我们一个个来看:

  • 第一种是document类型的uri。至于什么是document类型的uri这里就不深入了,只要知道有这种类型的uri,要怎么处理就好了。首先我们要获取一个DocumentId,然后再分两种情况处理:

第一种的是media格式的,然后我们要取出后半截字符串我们才能获取到真正的id,这里就真正的id指的是对应数据库表中的id,用于selection的。MediaStore.Images.Media.EXTERNAL_CONTENT_URI就是这个照片的content类型uri,再把selection放进去即可。 第二种通过ContentUris.withAppendedId这个方法即可获取到content类型的uri,这个方法负责把id和contentUri连接成一个新的Uri。这个方法在这里也不详细讲解。

  • 第二种的是content类型的,那不用说直接用就行了
  • 第三种的是file类型的,这个就是真实路径了,直接getPath就可以获取到了。

看完上述内容,你们掌握Android应用中是怎么调用系统相册中的照片的的方法了吗?

更多Android进阶指南 可以扫码 解锁 《Android十大板块文档》

1.Android车载应用开发系统学习指南(附项目实战)

2.Android Framework学习指南,助力成为系统级开发高手

3.2023最新Android中高级面试题汇总+解析,告别零offer

4.企业级Android音视频开发学习路线+项目实战(附源码)

5.Android Jetpack从入门到精通,构建高质量UI界面

6.Flutter技术解析与实战,跨平台首要之选

7.Kotlin从入门到实战,全方面提升架构基础

8.高级Android插件化与组件化(含实战教程和源码)

9.Android 性能优化实战+360°全方面性能调优

10.Android零基础入门到精通,高手进阶之路

敲代码不易,关注一下吧。ღ( ´・ᴗ・` )

标签:String,相册,中是,路径,uri,path,Android,null
From: https://blog.51cto.com/u_16163480/9329629

相关文章

  • 优化风潮下的Android开发者:如何保持竞争力?
    作为一名曾在知名大厂和腾讯工作的程序员,我想分享一下对于职场焦虑的看法。很多程序员都会在职场中遇到焦虑,这不仅来自工作环境,也与个人心态有关。焦虑的原因主要有两个方面:精神压力和竞争压力。我的一个朋友就是这样的,普通本科的学历,去年6月份进的大厂,刚刚开始的时候因为不熟悉工......
  • Android studio 集成Copilot
    AndroidStudio集成CopilotCopilot是一款由OpenAI开发的人工智能代码助手,它可以通过学习海量代码库,为开发者提供智能提示和代码补全功能。在AndroidStudio中集成Copilot,可以极大地提高开发效率和准确性。本文将介绍如何在AndroidStudio中集成Copilot,并提供一些代码示......
  • Android setStatusBarDisable
    Android中的setStatusBarDisable方法详解在Android开发中,我们经常需要定制状态栏的显示效果,有时甚至需要禁用状态栏。Android提供了setStatusBarDisable方法来实现禁用状态栏的功能。什么是状态栏状态栏是Android设备上显示系统状态信息的区域,通常位于屏幕的顶部。状态栏显示包......
  • android navigationBarDividerColor 无效
    AndroidnavigationBarDividerColor无效问题解析与解决1.问题背景在开发Android应用程序时,我们经常会使用导航栏(NavigationBar)来提供用户导航和操作的功能。导航栏中的分割线(divider)是一种常见的设计元素,用于分隔不同的导航按钮或操作按钮。在Android中,我们可以使用navigationB......
  • Android studio 集成github copilot
    AndroidStudio集成GitHubCopilot引言在软件开发的过程中,编写代码是一个不可避免的环节。而对于一些常见的代码块,我们可能已经写了很多次。在这种情况下,GitHubCopilot可以成为我们的好帮手。GitHubCopilot是由GitHub开发的人工智能代码助手,它通过学习开源代码库中的代码......
  • Android navigationBarDividerColor
    实现AndroidnavigationBarDividerColor的步骤流程图flowchartTDA(开始)B(查找navigationBar对象)C(创建dividerDrawable对象)D(设置dividerDrawable为navigationBar的dividerDrawable属性)E(结束)A-->B-->C-->D-->E介绍在Android开发......
  • Android 配置https抓包
    在Android中抓包常用fidder或者Charles,http可以直接抓去到请求信息,https抓取不到下面介绍两种抓包方案,可以轻松的获取请求的信息。一、使用用户证书1、application中android:networkSecurityConfig="@xml/network_security_config"android:usesCleartextTraffic="true"2......
  • Android RECYCLEVIEWscrollbarDefaultDelayBeforeFade 源码
    AndroidRecyclerViewscrollbarDefaultDelayBeforeFade源码实现简介在Android开发中,RecyclerView是一个常用的控件,用于展示大数据集合的列表或网格。RecyclerView提供了一些自定义的属性和方法,方便开发者根据需求进行定制。其中一个常用的属性是scrollbarDefaultDelayBefo......
  • Android平台Unity下如何通过WebCamTexture采集摄像头数据并推送至RTMP服务器或轻量级R
    技术背景我们在对接Unity下推送模块的时候,遇到这样的技术诉求,开发者希望在Android的Unity场景下,获取到前后摄像头的数据,并投递到RTMP服务器,实现低延迟的数据采集处理。在此之前,我们已经有了非常成熟的RTMP推送模块,也实现了Android平台Unity环境下的Camera场景采集,针对这个技术需求,......
  • android下progressBarDialog
    实现Android下ProgressBarDialog作为一名经验丰富的开发者,我很乐意教会你如何实现Android下的ProgressBarDialog。在本文中,我将分为以下几个步骤来详细介绍这个过程:确定需求创建ProgressBarDialog设置ProgressBar样式和属性显示和隐藏ProgressBarDialog接下来,让我们逐步进......