一、序言
在安卓开发过程中,有时候我们的应用需要使用手机本地图片,这就需要本地图片访问权限以及相关的获取方法,本文将手机本地图片的获取流程和代码做了一个总结,希望能够对大家有一定帮助;
二、功能分析
2.1 获取图片信息
首先要获取本地图片的相关信息,如:存储路径、名称等,这里就要用到ContentResolver;
private void initImages() {
int count = 0;
imageList = new ArrayList();
@SuppressLint("Recycle") Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
null, null, null, null);
while (cursor.moveToNext()) {
//获取图片的名称
String name = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
Log.d("ImgActivity: ", "initImages: " + "imageName: " + name);
//获取图片的路径
byte[] data = cursor.getBlob(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
String location = new String(data, 0, data.length - 1);
Log.d("ImgActivity: ", "initImages: " + "imageLocation: " + location);
//根据路径获取图片
Bitmap bm = getImgFromDesc(location);
//获取图片的详细信息
String desc = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DESCRIPTION));
Log.d("ImgActivity", "initImages: " + "ImageDesc: " + desc);
Image image = new Image(bm, name, location);
imageList.add(image);
count++;
if(count > 3) break;
}
Log.d("ImgActivity: ", "initImage: " + "imageList.size: " + imageList.size());
}
2.2 获取图片资源
要将图片显示出来,就要获取图片资源,这里采用BitmapFactory类对相应路径下的位图资源;
//根据路径获取图片
private Bitmap getImgFromDesc(String path) {
Bitmap bm = null;
File file = new File(path);
// 动态申请权限
String[] permissions = {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA};
final int REQUEST_CODE = 10001;
// 版本判断。当手机系统大于 23 时,才有必要去判断权限是否获取
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// 检查该权限是否已经获取
for (String permission : permissions) {
// GRANTED---授权 DINIED---拒绝
if (ContextCompat.checkSelfPermission(getApplicationContext(), permission) == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE);
}
}
}
boolean permission_readStorage = (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
boolean permission_camera = (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED);
Log.d("ImgActivity:", "getImageFromDesc: \n");
Log.d("ImgActivity: ", "readPermission: " + permission_readStorage + "\n");
Log.d("ImgActivity: ", "cameraPermission: " + permission_camera + "\n");
if(file.exists()) {
bm = BitmapFactory.decodeFile(path);
} else {
ToastUtil.showLong("该图片不存在!");
Log.d("ImgActivity ", "getImgFromDesc: 该图片不存在!");
}
return bm;
}
三、完整代码
整个代码包括:静态\动态权限申请、Activity注册与定义、视图的定义(包括activity_img.xml和item_listview.xml)、图片实体类的定义、ImageAdapter适配器定义;
3.1 AndroidManafest.xml
添加手机文件读写权限,注册Activity;
<!-- 获取手机外部存储读写权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- 手机照片访问权限 -->
<uses-permission android:name="android.permission.CAMERA"/>
<application
<activity
android:name=".activity.ImgActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
3.2 activity_img.xml
使用ListView列表显示图片,ScrollView滚动列表可滚动显示更多的图片;
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<ListView
android:id="@+id/img_list"
android:layout_width="match_parent"
android:layout_height="650dp"
android:layout_weight="1"/>
</LinearLayout>
</ScrollView>
3.3 定义item_listview.xml
定义ListView子项的布局,即:图片资源、图片名称、图片路径这样一个结构;
<?xml version="1.0" encoding="utf-8"?>
<!-- 显示查询到的手机本地图片 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<!-- 图片显示 -->
<ImageView
android:id="@+id/image_img"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="10dp"/>
<!-- 图片名称显示 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="图片名称: " />
<TextView
android:id="@+id/image_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<!-- 图片路径显示 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="图片路径: " />
<TextView
android:id="@+id/image_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
3.3 定义图片实体类
定义Image类,用于存储图片信息;
package com.android.androidpractice0824.bean;
import android.graphics.Bitmap;
/** 图像信息类 */
public class Image {
private Bitmap image;
private String name;
private String location;
public Image(Bitmap image, String name, String location) {
this.image = image;
this.name = name;
this.location = location;
}
public Bitmap getImage() {
return image;
}
public void setImage(Bitmap image) {
this.image = image;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
3.4 定义ListView的适配器
定义ImageAdapter类,用于适配ArrayList<Image>和视图ListView;
package com.android.androidpractice0824.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.androidpractice0824.R;
import com.android.androidpractice0824.bean.Image;
import java.util.List;
public class ImageAdapter extends ArrayAdapter<Image> {
private int resourceId;
public ImageAdapter(Context context, int textViewResourceId,
List<Image> objects) {
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Image image = getItem(position);
View view;
ViewHolder viewHolder;
if(convertView == null) {
view = LayoutInflater.from(getContext())
.inflate(resourceId, parent, false);
viewHolder = new ViewHolder();
viewHolder.imageImage = view.findViewById(R.id.image_img);
viewHolder.imageName = view.findViewById(R.id.image_name);
viewHolder.imageLocation = view.findViewById(R.id.image_location);
view.setTag(viewHolder); //将ViewHolder储存在View中
} else {
view = convertView;
viewHolder = (ViewHolder) view.getTag(); //重新获取ViewHolder
}
viewHolder.imageImage.setImageBitmap(image.getImage());
viewHolder.imageName.setText(image.getName());
viewHolder.imageLocation.setText(image.getLocation());
return view;
}
class ViewHolder {
ImageView imageImage;
TextView imageName, imageLocation;
}
}
3.5 定义Activity类
定义ImageActivity类,用于处理UI的后端逻辑,以及本地图片查询等操作方法的定义;
package com.android.androidpractice0824.activity;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.android.androidpractice0824.R;
import com.android.androidpractice0824.Util.ToastUtil;
import com.android.androidpractice0824.adapter.ImageAdapter;
import com.android.androidpractice0824.bean.Image;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author Karson Tiger
*/
//获取本地图片并显示
//参考:https://www.jb51.net/article/81948.htm
public class ImgActivity extends Activity implements View.OnClickListener{
private List<Image> imageList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_img);
initImages(); //初始化图片数据
ImageAdapter adapter = new ImageAdapter(ImgActivity.this,
R.layout.item_listview, imageList);
ListView listView = findViewById(R.id.img_list);
listView.setAdapter(adapter);
///list的点击事件
listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick (AdapterView < ? > parent, View view,int position, long id){
Image image = imageList.get(position);
ToastUtil.showLong("你点击了图片" + image.getName());
}
});
}
//查询图片信息
private void initImages() {
/* 因为手机本地图片过多,若将其全部查询出来并显示,需要耗费过多时间,
这里定义一个count变量用于控制显示出的图片数目 */
int count = 0;
imageList = new ArrayList();
@SuppressLint("Recycle") Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
null, null, null, null);
while (cursor.moveToNext()) {
//获取图片的名称
String name = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
Log.d("ImgActivity: ", "initImages: " + "imageName: " + name);
//获取图片的路径
byte[] data = cursor.getBlob(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
String location = new String(data, 0, data.length - 1);
Log.d("ImgActivity: ", "initImages: " + "imageLocation: " + location);
//根据路径获取图片
Bitmap bm = getImgFromDesc(location);
//获取图片的详细信息
String desc = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DESCRIPTION));
Log.d("ImgActivity", "initImages: " + "ImageDesc: " + desc);
Image image = new Image(bm, name, location);
imageList.add(image);
count++;
//显示出3张图片,可改变该数字,控制显示出的图片数目
if(count >= 3) break;
}
Log.d("ImgActivity: ", "initImage: " + "imageList.size: " + imageList.size());
}
//根据路径获取图片
private Bitmap getImgFromDesc(String path) {
Bitmap bm = null;
File file = new File(path);
// 动态申请权限
String[] permissions = {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA};
final int REQUEST_CODE = 10001;
// 版本判断。当手机系统大于 23 时,才有必要去判断权限是否获取
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// 检查该权限是否已经获取
for (String permission : permissions) {
// GRANTED---授权 DINIED---拒绝
if (ContextCompat.checkSelfPermission(getApplicationContext(), permission) == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE);
}
}
}
boolean permission_readStorage = (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
boolean permission_camera = (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED);
Log.d("ImgActivity:", "getImageFromDesc: \n");
Log.d("ImgActivity: ", "readPermission: " + permission_readStorage + "\n");
Log.d("ImgActivity: ", "cameraPermission: " + permission_camera + "\n");
if(file.exists()) {
bm = BitmapFactory.decodeFile(path);
} else {
ToastUtil.showLong("该图片不存在!");
Log.d("ImgActivity ", "getImgFromDesc: 该图片不存在!");
}
return bm;
}
}