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号