Android网络获取图片保存到本地,并在ViewPager中显示图片


本文章提供的技术有:网络获取图片并保存到SD卡、网络或本地图片展示到ViewPager中、判断网络状态(是否联网)。

自己写了一个demo,提供demo下载 点击打开链接    效果如图

      


网络获取的主要思路是,根据url地址获取图片的数据流,继而将数据流转换为bitmap,在imageview中展示bitmap。需要注意的一个问题是,图片可能会很大,容易造成OutOfMemery错误,所以需要根据自己的设备屏幕的尺寸对原图片进行缩放。下载图片的一系列函数如下:

/**
* 获取文件大小
* @param f
* @return
* @throws Exception
*/
@SuppressWarnings("resource")
private long getFileSizes(File f) throws Exception
{
long s = 0;
if (f.exists())
{
FileInputStream fis = null;
fis = new FileInputStream(f);
s = fis.available();
}
else
{
f.createNewFile();
System.out.println("文件不存在");
}
return s;
}
private void DownloadImage(String imguri,String imgname)
{
URL url;
byte[] b=null;
try {
url = new URL(imguri); //设置URL
HttpURLConnection con;
con = (HttpURLConnection)url.openConnection(); //打开连接
con.setRequestMethod("GET"); //设置请求方法
//设置连接超时时间为5s
con.setConnectTimeout(5000);
InputStream in=con.getInputStream(); //取得字节输入流
b=readInputStream(in);
Log.v("Save","getbyte");
Bitmap bitmap=decodeSampledBitmapFromStream(b,width-20,height-20);
try
{
saveJPGFile(bitmap, imgname);
Log.v("Downloadimage","保存图片成功");
}
catch(Exception e)
{
Log.v("getimage","保存图片失败");
}
} catch (Exception e) {

e.printStackTrace();
}
}

/**
*
* @param bm
* 图片的bitmap
* @param fileName
* 文件名
* @param folderName
* 文件夹名
* @throws IOException
*/
private void saveJPGFile(Bitmap bm,String fileName)
throws IOException {
String path = SDCard + "/";
File dirFile = new File(path);
// 文件夹不存在则创建文件夹
if (!dirFile.exists()) {
dirFile.mkdirs();
}
Log.v("保存文件函数", "创建文件夹成功");
File myCaptureFile = new File(path + fileName + ".jpg");
Log.v("保存文件函数", "文件路径");

try{
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(myCaptureFile));
Log.v("保存文件函数", "文件流");
bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);
Log.v("保存文件函数", "保存成功");
bos.flush();
bos.close();
if(bm.isRecycled()==false)
{
bm.recycle();
Log.v("Util","回收bitmap");
}
}catch(Exception e){

}
}

private byte[] readInputStream(InputStream in) throws Exception{
int len=0;
byte buf[]=new byte[1024];
ByteArrayOutputStream out=new ByteArrayOutputStream();
while((len=in.read(buf))!=-1){
out.write(buf,0,len); //把数据写入内存
}
out.close(); //关闭内存输出流
return out.toByteArray(); //把内存输出流转换成byte数组
}

private Bitmap decodeSampledBitmapFromStream(byte[] b,int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(b, 0, b.length, options);
// 调用上面定义的方法计算inSampleSize值
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// 使用获取到的inSampleSize值再次解析图片
options.inJustDecodeBounds = false;
Log.v("decode","返回bitmap");
return BitmapFactory.decodeByteArray(b, 0, b.length, options);
}
private int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// 源图片的高度和宽度
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// 计算出实际宽高和目标宽高的比率
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
// 一定都会大于等于目标的宽和高。
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
Log.v("calculate"," "+inSampleSize);
return inSampleSize;
}

至于本地图片,首先判断图片是否存在,大小是否为0(图片无效),如果没有问题的话,也是将图片文件转换为流,再将流转为bitmap,存入bitmap数组中,等待在viewpager中展示。

File file=new File(SDCard+"/"+imgname[i]+".jpg");
long sizeoffile=0;
try {
sizeoffile=getFileSizes(file);
if(file.exists()&&sizeoffile!=0)
{
//文件存在,本地获取
FileInputStream fis;
try {
fis = new FileInputStream(file);
newimgs[i]=BitmapFactory.decodeStream(fis);
fis.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
//文件不存在,判断网络状态
if(cd.isConnectingToInternet())
{
//有网状态,网络下载
URL url;
url = new URL(imgurl[i]);
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
InputStream is = conn.getInputStream();
newimgs[i] = BitmapFactory.decodeStream(is);
if(sizeoffile==0)
file.delete();
is.close();
DownloadImage(imgurl[i], imgname[i]);
Log.v("getImage","下载图片成功");
}
else
{
//无网无数据,提示信息
handler.sendEmptyMessage(0x01);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

当bitmap数组中填充好数据后,就可以在viewpager的adapter中展示了,根据图片的数量在viewpager的adapter中新建ImageView,用来展示图片。

viewpager.setAdapter(new PagerAdapter() {

public Object instantiateItem(ViewGroup container, final int position)
{
imageView = new ImageView(getApplicationContext());
imageView.setImageBitmap(newimgs[position]);
imageView.setOnClickListener(new OnClickListener() {

public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), imgname[position], Toast.LENGTH_SHORT).show();
}
});
container.addView(imageView);
return imageView;
}
public void destroyItem(ViewGroup container, int position,
Object object)
{

}

@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return arg0==arg1;
}

@Override
public int getCount() {
// TODO Auto-generated method stub
return imgname.length;
}
});

注意两点:1、需要在destroy时将bitmap释放掉,不然会出现OutOfMemery错误。

protected void onDestroy()
{
super.onDestroy();
handler.removeCallbacks(getImage);
for(int i=0;i<imgname.length;i++)
{
if(newimgs[i]!=null&&newimgs[i].isRecycled()!=false)
{
newimgs[i].recycle();
}
}
System.gc();
}

2、在manifest中加好权限,一共有四个

    <!-- 联网的权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 获取网络状态的权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 向SD卡中写数据的权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 从SD卡中读数据的权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


如果有不足之处,还望大家能够指出!

智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告