本文章提供的技术有:网络获取图片并保存到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; }
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; } });
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(); }
<!-- 联网的权限 --> <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" />