前言: 在开发中有个需求需要访问本地图片和视屏进行上传,所以尝试了以下访问本地的图片和视屏并利用gridView展示出来。
正文
一、先创建一个异步任务用于查询数据库中图片、相册、视屏等数据,代码如下:
package com.example.test1.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.example.test1.R;
import com.example.test1.bean.PhotoUpImageBucket;
import com.example.test1.bean.PhotoUpImageItem;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.os.AsyncTask;
import android.provider.MediaStore;
import android.provider.MediaStore.Audio.Albums;
import android.provider.MediaStore.Images.Media;
import android.provider.MediaStore.Images.Thumbnails;
import android.util.Log;
public class PhotoUpAlbumHelper extends AsyncTask
其中用到了两个工具实体类:
PhotoUpImageBucket类
package com.example.test1.bean;
import java.io.Serializable;
import java.util.List;
/**
* 一个目录下的相册对象
*/
public class PhotoUpImageBucket implements Serializable{
public int count = 0;//相册中的图片数量
public String bucketName;//相册名
public List imageList;//相册中的图片集合
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public String getBucketName() {
return bucketName;
}
public void setBucketName(String bucketName) {
this.bucketName = bucketName;
}
public List getImageList() {
return imageList;
}
public void setImageList(List imageList) {
this.imageList = imageList;
}
}
PhotoUpImageItem类
package com.example.test1.bean;
import java.io.Serializable;
/**
* 相册下的图片或视屏对象
*/
public class PhotoUpImageItem implements Serializable {
//图片ID
private String imageId;
//原图路径
private String imagePath;
//是否被选择
private boolean isSelected = false;
//图片还是视屏 true为图片 false为视屏
private boolean isPhoto = true;
public String getImageId() {
return imageId;
}
public void setImageId(String imageId) {
this.imageId = imageId;
}
public String getImagePath() {
return imagePath;
}
public void setImagePath(String imagePath) {
this.imagePath = imagePath;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean isSelected) {
this.isSelected = isSelected;
}
public boolean isPhoto() {
return isPhoto;
}
public void setPhoto(boolean isPhoto) {
this.isPhoto = isPhoto;
}
}
二、新建一个activity,在其中放置一个GridView用于存放相册集合
package com.example.test1;
import java.util.HashMap;
import java.util.List;
import com.example.test1.adpater.AlbumsAdapter;
import com.example.test1.bean.PhotoUpImageBucket;
import com.example.test1.util.PhotoUpAlbumHelper;
import com.example.test1.util.PhotoUpAlbumHelper.GetAlbumList;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.ThumbnailUtils;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.view.Window;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
public class AlbumsActivity extends Activity implements OnScrollListener{
private GridView gridView;
private AlbumsAdapter adapter;
private PhotoUpAlbumHelper photoUpAlbumHelper;
private List list;
public static HashMap bitmaps = new HashMap();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.albums_gridview);
init();
loadData();
onItemClick();
}
private void init(){
gridView = (GridView) findViewById(R.id.album_gridv);
adapter = new AlbumsAdapter(AlbumsActivity.this);
gridView.setAdapter(adapter);
}
private void loadData(){
photoUpAlbumHelper = PhotoUpAlbumHelper.getHelper();
photoUpAlbumHelper.init(AlbumsActivity.this);
photoUpAlbumHelper.setGetAlbumList(new GetAlbumList() {
@Override
public void getAlbumList(List list) {
adapter.setArrayList(list);
adapter.notifyDataSetChanged();
AlbumsActivity.this.list = list;
}
});
photoUpAlbumHelper.execute(false);
}
//设置gridView的item点击事件
private void onItemClick(){
gridView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view,
int position, long id) {
Intent intent = new Intent(AlbumsActivity.this,AlbumItemActivity.class);
intent.putExtra("imagelist", list.get(position));
startActivity(intent);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
}
//释放图片的函数
private void recycleBitmapCaches(int fromPosition,int toPosition){
Bitmap delBitmap = null;
for(int del=fromPosition;delbitmap的映射
bitmaps.remove(list.get(del).getBucketName());
delBitmap.recycle();
delBitmap = null;
}
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//注释:firstVisibleItem为第一个可见的Item的position,从0开始,随着拖动会改变
//visibleItemCount为当前页面总共可见的Item的项数
//totalItemCount为当前总共已经出现的Item的项数
recycleBitmapCaches(0,firstVisibleItem);
recycleBitmapCaches(firstVisibleItem+visibleItemCount,totalItemCount);
}
}
为GridView定义适配器AlbumsAdapter
package com.example.test1.adpater;
import java.util.ArrayList;
import java.util.List;
import com.example.test1.AlbumsActivity;
import com.example.test1.R;
import com.example.test1.bean.PhotoUpImageBucket;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.media.ThumbnailUtils;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class AlbumsAdapter extends BaseAdapter {
Context mContext;
private List arrayList;
private LayoutInflater layoutInflater;
private ImageLoader imageLoader = ImageLoader.getInstance();
private DisplayImageOptions options;
private String TAG = AlbumsAdapter.class.getSimpleName();
public AlbumsAdapter(Context context){
mContext = context;
layoutInflater = LayoutInflater.from(context);
arrayList = new ArrayList();//初始化集合
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.tasksProcessingOrder(QueueProcessingType.LIFO)
.memoryCacheExtraOptions(96, 120)
.build();
// Initialize ImageLoader with configuration.
imageLoader.init(config);
// 使用DisplayImageOption.Builder()创建DisplayImageOptions
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.album_default_loading_pic) // 设置图片下载期间显示的图片
.showImageForEmptyUri(R.drawable.album_default_loading_pic) // 设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.album_default_loading_pic) // 设置图片加载或解码过程中发生错误显示的图片
.cacheInMemory(true) // 设置下载的图片是否缓存在内存中
.cacheOnDisc(true) // 设置下载的图片是否缓存在SD卡中
// .displayer(new RoundedBitmapDisplayer(20)) // 设置成圆角图片
.bitmapConfig(Config.RGB_565)
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)
.build(); // 创建配置过的DisplayImageOption对象
};
@Override
public int getCount() {
return arrayList.size();
}
@Override
public Object getItem(int position) {
return arrayList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final Holder holder;
if (convertView == null) {
holder = new Holder();
convertView = layoutInflater.inflate(R.layout.ablums_adapter_item, parent, false);
holder.image = (ImageView) convertView.findViewById(R.id.image);
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.count = (TextView) convertView.findViewById(R.id.count);
convertView.setTag(holder);
}else {
holder = (Holder) convertView.getTag();
}
holder.count.setText(""+arrayList.get(position).getCount());
holder.name.setText(arrayList.get(position).getBucketName());
Log.e("aaaaaaaaaaaaaaaaaaaaaa", "con:"+mContext.getString(R.string.video_file_name)+" list:"+arrayList.get(position).getBucketName()+" position:"+position);
if ((mContext.getString(R.string.video_file_name)).equals(
arrayList.get(position).getBucketName())) {//如果是视屏,则起一个线程获取缩略图
holder.image.setImageDrawable(mContext.getResources().getDrawable(R.drawable.album_default_loading_pic));
final Handler mhHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 111:
Bitmap bitmap = (Bitmap) msg.obj;
holder.image.setImageBitmap(bitmap);
AlbumsActivity.bitmaps.put(arrayList.get(position).getBucketName(), bitmap);
break;
default:
break;
}
super.handleMessage(msg);
}
};
new Thread(new Runnable() {
@Override
public void run() {
String videoPath = arrayList.get(position).getImageList().get(0).getImagePath();
Bitmap bitmap= ThumbnailUtils.createVideoThumbnail(
videoPath,MediaStore.Video.Thumbnails.MINI_KIND);
Message msg = new Message();
msg.what=111;
msg.obj=bitmap;
mhHandler.sendMessage(msg);
}
}).start();
//
}else {
imageLoader.displayImage("file://"+arrayList.get(position).getImageList().get(0).getImagePath(),
holder.image, options);
}
return convertView;
}
class Holder{
ImageView image;
TextView name;
TextView count;
}
public void setArrayList(List arrayList) {
this.arrayList = arrayList;
}
}
在这里加载图片使用的时imageloader实现加载,以解决GridView加载图片卡顿及内存问题
三、然后是进入相册后图片列表的activity
首先是albm_item_images.xml
AlbumItemActivity,显示图片的界面
import com.example.test1.bean.PhotoUpImageBucket;
import com.example.test1.bean.PhotoUpImageItem;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
public class AlbumItemActivity extends Activity implements OnClickListener, OnScrollListener{
private GridView gridView;
private TextView back,ok;
private PhotoUpImageBucket photoUpImageBucket;
private ArrayList selectImages;
private AlbumItemAdapter adapter;
public static HashMap bitmaps = new HashMap();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.album_item_images);
init();
setListener();
}
private void init(){
gridView = (GridView) findViewById(R.id.album_item_gridv);
back = (TextView) findViewById(R.id.back);
ok = (TextView) findViewById(R.id.sure);
selectImages = new ArrayList();
Intent intent = getIntent();
photoUpImageBucket = (PhotoUpImageBucket) intent.getSerializableExtra("imagelist");
adapter = new AlbumItemAdapter(photoUpImageBucket.getImageList(), AlbumItemActivity.this);
gridView.setAdapter(adapter);
}
private void setListener(){
back.setOnClickListener(this);
ok.setOnClickListener(this);
gridView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view,
int position, long id) {
if (photoUpImageBucket.getImageList().get(position).isPhoto()) {//如果是图片的话
CheckBox checkBox = (CheckBox) view.findViewById(R.id.check);
photoUpImageBucket.getImageList().get(position).setSelected(
!checkBox.isChecked());
adapter.notifyDataSetChanged();
Toast.makeText(AlbumItemActivity.this, "postion="+position,
Toast.LENGTH_SHORT).show();
// photoUpImageBucket.getImageList().get(position).setSelected(
// !photoUpImageBucket.getImageList().get(position).isSelected());
// adapter.notifyDataSetChanged();
if (photoUpImageBucket.getImageList().get(position).isSelected()) {
if (selectImages.contains(photoUpImageBucket.getImageList().get(position))) {
}else {
selectImages.add(photoUpImageBucket.getImageList().get(position));
}
}else {
if (selectImages.contains(photoUpImageBucket.getImageList().get(position))) {
selectImages.remove(photoUpImageBucket.getImageList().get(position));
}else {
}
}
}else {//如果是视屏的话
Toast.makeText(AlbumItemActivity.this, "跳转页面,展示视屏", Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.back:
finish();
break;
case R.id.sure:
// Intent intent = new Intent(AlbumItemActivity.this,SelectedImagesActivity.class);
// intent.putExtra("selectIma", selectImages);
// startActivity(intent);
break;
default:
break;
}
}
//释放图片的函数
private void recycleBitmapCaches(int fromPosition,int toPosition){
Bitmap delBitmap = null;
for(int del=fromPosition;delbitmap的映射
bitmaps.remove(photoUpImageBucket.getImageList().get(del).getImageId());
delBitmap.recycle();
delBitmap = null;
}
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//注释:firstVisibleItem为第一个可见的Item的position,从0开始,随着拖动会改变
//visibleItemCount为当前页面总共可见的Item的项数
//totalItemCount为当前总共已经出现的Item的项数
recycleBitmapCaches(0,firstVisibleItem);
recycleBitmapCaches(firstVisibleItem+visibleItemCount,totalItemCount);
}
}
具体的图片或者视屏的GridView的适配器
package com.example.test1.adpater;
import java.util.HashMap;
import java.util.List;
import com.example.test1.AlbumsActivity;
import com.example.test1.R;
import com.example.test1.bean.PhotoUpImageItem;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.media.ThumbnailUtils;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
public class AlbumItemAdapter extends BaseAdapter {
private List list;
private LayoutInflater layoutInflater;
private ImageLoader imageLoader;
private DisplayImageOptions options;
private Context mContext;
private HashMap holderMaps = new HashMap();
public AlbumItemAdapter(List list,Context context){
this.list = list;
mContext = context;
layoutInflater = LayoutInflater.from(context);
imageLoader = ImageLoader.getInstance();
// 使用DisplayImageOption.Builder()创建DisplayImageOptions
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.album_default_loading_pic) // 设置图片下载期间显示的图片
.showImageForEmptyUri(R.drawable.album_default_loading_pic) // 设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.album_default_loading_pic) // 设置图片加载或解码过程中发生错误显示的图片
.cacheInMemory(true) // 设置下载的图片是否缓存在内存中
.cacheOnDisc(true) // 设置下载的图片是否缓存在SD卡中
// .displayer(new RoundedBitmapDisplayer(20)) // 设置成圆角图片
.bitmapConfig(Config.ARGB_8888)
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)
.build(); // 创建配置过的DisplayImageOption对象
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final Holder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.album_item_images_item_view, parent, false);
holder = new Holder();
holder.imageView = (ImageView) convertView.findViewById(R.id.image_item);
holder.checkBox = (CheckBox) convertView.findViewById(R.id.check);
holder.videPlay = (ImageView) convertView.findViewById(R.id.video_play);
convertView.setTag(holder);
holderMaps.put(position, holder);
}else {
holder = (Holder) convertView.getTag();
holderMaps.put(position, holder);
}
if (list.get(position).isPhoto()) {
//图片加载器的使用代码,就这一句代码即可实现图片的加载。请注意
//这里的uri地址,因为我们现在实现的是获取本地图片,所以使
//用"file://"+图片的存储地址。如果要获取网络图片,
//这里的uri就是图片的网络地址。
imageLoader.displayImage("file://"+list.get(position).getImagePath(), holder.imageView, options);
holder.checkBox.setChecked(list.get(position).isSelected());
holder.videPlay.setVisibility(View.GONE);
}else {
holder.imageView.setImageDrawable(mContext.getResources().getDrawable(R.drawable.album_default_loading_pic));
final Handler mhHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 111:
Bitmap bitmap = (Bitmap) msg.obj;
int num = msg.arg1;
Holder mHolder= holderMaps.get(num);
if (bitmap!=null) {
mHolder.imageView.setImageBitmap(bitmap);
AlbumsActivity.bitmaps.put(list.get(position).getImageId(), bitmap);
}
mHolder.videPlay.setVisibility(View.VISIBLE);
mHolder.checkBox.setVisibility(View.GONE);
break;
default:
break;
}
super.handleMessage(msg);
}
};
new Thread(new Runnable() {
@Override
public void run() {
String videoPath = list.get(position).getImagePath();
Bitmap bitmap= ThumbnailUtils.createVideoThumbnail(
videoPath,MediaStore.Video.Thumbnails.MINI_KIND);
// if (bitmap!=null) {
// holder.imageView.setImageBitmap(bitmap);
// AlbumsActivity.bitmaps.put(list.get(position).getImageId(), bitmap);
// }
// holder.videPlay.setVisibility(View.VISIBLE);
// holder.checkBox.setVisibility(View.GONE);
Message msg = new Message();
msg.what=111;
msg.obj=bitmap;
msg.arg1=position;
mhHandler.sendMessage(msg);
}
}).start();
}
return convertView;
}
class Holder{
ImageView imageView;
CheckBox checkBox;
ImageView videPlay;
}
}
需要注意的是,在数据库中查询道德视屏时没有缩略图的uri的,所以我们适配时的适配展示图需要用
Bitmap bitmap= ThumbnailUtils.createVideoThumbnail(
videoPath,MediaStore.Video.Thumbnails.MINI_KIND);
来获取缩略图,但因为imageloader加载图片时用url进行记载的。
我们加载视屏缩略图时要使用setImageBitmap(Bitmap)方法,那么我们就还需要释放我们的资源:
AlbumsActivity.bitmaps.put(arrayList.get(position).getBucketName(), bitmap);
//释放图片的函数
private void recycleBitmapCaches(int fromPosition,int toPosition){
Bitmap delBitmap = null;
for(int del=fromPosition;delbitmap的映射
bitmaps.remove(list.get(del).getBucketName());
delBitmap.recycle();
delBitmap = null;
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//注释:firstVisibleItem为第一个可见的Item的position,从0开始,随着拖动会改变
//visibleItemCount为当前页面总共可见的Item的项数
//totalItemCount为当前总共已经出现的Item的项数
recycleBitmapCaches(0,firstVisibleItem);
recycleBitmapCaches(firstVisibleItem+visibleItemCount,totalItemCount);
}
总结:
在实现获取相册中的图片或视频时需要注意的几点是:
- 在加载时要放在异步线程中执行,否在可能会导致ART。
- 加载图片使用imageloader以解决缓存及卡顿问题。
- 当要展示视频缩略图时需要自己生成Bitmap对象并加载,这是要注意释放资源。