Android保存图片到图库,Android扫描文件到媒体库,Android保存图片到SD卡

我们最常常遇到的也就是保存图片到SD卡,然后打开系统的图库可以看得到,可是为什么微信QQ之类的应用可以,我们保存到SD卡就看不到呢?原因就是保存到SD卡后我们还要让系统扫描图片到多媒体库,因为系统的图库读的其实是一个多媒体库的数据库,所以我们保存之后如果没有通知系统扫描的画是看不到的

这里要声明一点,后边的扫描要用到获取文件的Mimetype,不知道怎么获取的人看这里:http://blog.csdn.net/yanzhenjie1003/article/details/44936643

Demo源码连接在文章尾部给出。

首先,保存图片到SD卡,当然方法不止一种,我这里例举一种:

[java]  view plain  copy
 print ?
  1. /** 
  2.  * 保存图片 
  3.  * @author YOLANDA 
  4.  * @param bitmap 图片 
  5.  * @return 
  6.  */  
  7. private String saveImg(Bitmap bitmap){  
  8.     File myappDir = new File(Environment.getExternalStorageDirectory(), "yolanda");  
  9.     if(myappDir.exists() && myappDir.isFile()) {  
  10.         myappDir.delete();  
  11.     }  
  12.     if (!myappDir.exists()) {  
  13.         myappDir.mkdir();  
  14.     }  
  15.     String fileName = System.currentTimeMillis() + ".png";  
  16.     File file = new File(myappDir, fileName);  
  17.     if(file.exists()) {  
  18.         file.delete();  
  19.     }  
  20.     try {  
  21.         FileOutputStream fos = new FileOutputStream(file);  
  22.         bitmap.compress(CompressFormat.PNG, 100, fos);  
  23.         fos.flush();  
  24.         fos.close();  
  25.     } catch (FileNotFoundException e) {  
  26.         e.printStackTrace();  
  27.     } catch (IOException e) {  
  28.         e.printStackTrace();  
  29.     }  
  30.     return file.getAbsolutePath();  
  31. }  

那么还有一个问题是,我们怎么保存图片到系统图库呢?为什么要单独说这个问题呢,因为有的手机保存的路径在DCIM/100ANDRo下,有的手机在DCIM/Camera下,所以很难做到兼容,所以我们用到系统的一个方法:
[java]  view plain  copy
 print ?
  1. MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), fileName, null);  
这里做个参数说明,第一个参数不用说了,第二个参数是文件在SD卡的路径,第三个是文件保存的名字,第四个是文件描述,可有可无;

那么现在完成的代码就是:

[java]  view plain  copy
 print ?
  1. /** 
  2.  * 保存图片到SD卡 
  3.  * @author YOLANDA 
  4.  * @param isInsertGallery 是否保存到图库 
  5.  * @return 
  6.  */  
  7. private String saveImg(Bitmap bitmap, boolean isInsertGallery){  
  8.     File myappDir = new File(Environment.getExternalStorageDirectory(), "yolanda");  
  9.     if(myappDir.exists() && myappDir.isFile()) {  
  10.         myappDir.delete();  
  11.     }  
  12.     if (!myappDir.exists()) {  
  13.         myappDir.mkdir();  
  14.     }  
  15.     String fileName = System.currentTimeMillis() + ".png";  
  16.     File file = new File(myappDir, fileName);  
  17.     if(file.exists()) {  
  18.         file.delete();  
  19.     }  
  20.     try {  
  21.         FileOutputStream fos = new FileOutputStream(file);  
  22.         bitmap.compress(CompressFormat.PNG, 100, fos);  
  23.         fos.flush();  
  24.         fos.close();  
  25.     } catch (FileNotFoundException e) {  
  26.         e.printStackTrace();  
  27.     } catch (IOException e) {  
  28.         e.printStackTrace();  
  29.     }  
  30.     if(isInsertGallery) {  
  31.         try {  
  32.             MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), fileName, null);  
  33.         } catch (FileNotFoundException e) {  
  34.             e.printStackTrace();  
  35.         }  
  36.     }  
  37.     return file.getAbsolutePath();  
  38. }  

这样就可以做到既保存到我们自定义的目录中,又保存在系统图库中了。现在打开图库就直接可以看到图片了。

看似好像解决了我们刚开始说的保存图片到SD打开图库可以看到的问题了,那么有人就问了,QQ和微信人家也不是直接存到图库的啊,人家咋可以保存到自己的目录打开图库就可以看到呢?好,下面我们就来解决这个问题

其实,我们保存图片到SD卡时,要通知系统来扫描,这里分为两种情况:

1、在Androd4.4出来之前,我们都可以发送一个系统广播出去,这个广播既可以扫描一个文件夹:

[java]  view plain  copy
 print ?
  1. sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));  

又可以扫描一个文件:

[java]  view plain  copy
 print ?
  1. sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + filePath)));  

所以在Android4.4之前的的系统中最终的代码是:

[java]  view plain  copy
 print ?
  1. /** 
  2.  * 保存后用广播扫描,Android4.4以下使用这个方法 
  3.  * @author YOLANDA 
  4.  */  
  5. private void saveBroadcast(){  
  6.     String filePath = saveImg(true);  
  7.     sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + filePath)));  
  8.     Toast.makeText(this"保存成功:" + filePath, Toast.LENGTH_LONG).show();  
  9. }  
  10.   
  11. /** 
  12.  * 保存图片到SD卡 
  13.  * @author YOLANDA 
  14.  * @param isInsertGallery 是否保存到图库 
  15.  * @return 
  16.  */  
  17. private String saveImg(boolean isInsertGallery){  
  18.     File myappDir = new File(Environment.getExternalStorageDirectory(), "yolanda");  
  19.     if(myappDir.exists() && myappDir.isFile()) {  
  20.         myappDir.delete();  
  21.     }  
  22.     if (!myappDir.exists()) {  
  23.         myappDir.mkdir();  
  24.     }  
  25.     String fileName = System.currentTimeMillis() + ".png";  
  26.     File file = new File(myappDir, fileName);  
  27.     if(file.exists()) {  
  28.         file.delete();  
  29.     }  
  30.     try {  
  31.         FileOutputStream fos = new FileOutputStream(file);  
  32.         bitmap.compress(CompressFormat.PNG, 100, fos);  
  33.         fos.flush();  
  34.         fos.close();  
  35.     } catch (FileNotFoundException e) {  
  36.         e.printStackTrace();  
  37.     } catch (IOException e) {  
  38.         e.printStackTrace();  
  39.     }  
  40.     if(isInsertGallery) {  
  41.         try {  
  42.             MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), fileName, null);  
  43.         } catch (FileNotFoundException e) {  
  44.             e.printStackTrace();  
  45.         }  
  46.     }  
  47.     return file.getAbsolutePath();  
  48. }  

为什么说是Android4.4之前呢?因为Android4.4开始,Android把系统广播的权限回收了,只有系统应用才可以发送系统广播,那么这还怎么活啊???不要着急,车道山前必有路,还有一个MediaScannerConnection,这个玩意儿可强大了,不仅仅可以搞定图片,只要是媒体文件都可以用他来扫描,不过要知道文件的MimeType,不知道怎么获取文件MimeType的看这里: http://blog.csdn.net/yanzhenjie1003/article/details/44936643

2、在Android4.4和之后用MediaScannerConnection来扫描。

这里讲解一下怎么用MediaScannerConnection来扫描文件,我封装好了一个类出来:

[java]  view plain  copy
 print ?
  1. /** 
  2.  * 实现MediaScannerConnection.MediaScannerConnectionClient 
  3.  * @author YOLANDA 
  4.  * @Time 2015年4月8日 上午9:03:54 
  5.  */  
  6. public class MediaScanner implements MediaScannerConnection.MediaScannerConnectionClient {  
  7.   
  8.     /** 
  9.      * 扫描对象 
  10.      */  
  11.     private MediaScannerConnection mediaScanConn = null;  
  12.   
  13.     public MediaScanner(Context context) {  
  14.         //实例化  
  15.         mediaScanConn = new MediaScannerConnection(context, this);  
  16.     }  
  17.   
  18.     /**文件路径集合**/  
  19.     private String[] filePaths;  
  20.     /**文件MimeType集合**/  
  21.     private String[] mimeTypes;  
  22.   
  23.     /** 
  24.      * 扫描文件 
  25.      * @author YOLANDA 
  26.      * @param filepaths 
  27.      * @param mimeTypes 
  28.      */  
  29.     public void scanFiles(String[] filePaths, String[] mimeTypes) {  
  30.         this.filePaths = filePaths;  
  31.         this.mimeTypes = mimeTypes;  
  32.         mediaScanConn.connect();//连接扫描服务  
  33.     }  
  34.   
  35.     /** 
  36.      * @author YOLANDA 
  37.      */  
  38.     @Override  
  39.     public void onMediaScannerConnected() {  
  40.         for (int i = 0; i < filePaths.length; i++) {  
  41.             mediaScanConn.scanFile(filePaths[i], mimeTypes[i]);//服务回调执行扫描  
  42.         }  
  43.         filePaths = null;  
  44.         mimeTypes = null;  
  45.     }  
  46.   
  47.     private int scanTimes = 0;  
  48.   
  49.     /** 
  50.      * 扫描一个文件完成 
  51.      * @author YOLANDA 
  52.      * @param path 
  53.      * @param uri 
  54.      */  
  55.     @Override  
  56.     public void onScanCompleted(String path, Uri uri) {  
  57.         scanTimes ++;  
  58.         if(scanTimes == filePaths.length) {//如果扫描完了全部文件  
  59.             mediaScanConn.disconnect();//断开扫描服务  
  60.             scanTimes = 0;//复位计数  
  61.         }  
  62.     }  
  63. }  


这个类可以单个文件,也可以扫描多个文件,用法就是直接new一个MediaScannerConnection对象,这个对象需要一个实现了MediaScannerConnection.MediaScannerConnectionClient接口的对象,我们调用的时候步骤是:

1、new一个MediaScannerConnection对象

2、传要扫描的文件路径和文件MimeType进来

3、调用MediaScannerConnection对象的connect()方法,会触发MediaScannerConnection.MediaScannerConnectionClient接口的onMediaScannerConnected方法

4、在MediaScannerConnection.MediaScannerConnectionClient接口的onMediaScannerConnected()方法内调用用MediaScannerConnection.scanFile(String path, String mimeType)来扫描文件

5、扫描结束后会触发MediaScannerConnection.MediaScannerConnectionClient接口的onScanCompleted方法,在这个方法里调用MediaScannerConnection.disconnect()断开连接

所以我们完成的代码是:

[java]  view plain  copy
 print ?
  1. public class MainActivity extends Activity implements View.OnClickListener {  
  2.   
  3.     private Bitmap bitmap = null;  
  4.     private ImageView imgUserHead;//假如这是用户头像  
  5.     private Button btnSaveBoradcase;//保存并广播扫描  
  6.     private Button btnSaveScan;//保存并扫描到媒体库  
  7.   
  8.     @Override  
  9.     protected void onCreate(Bundle savedInstanceState) {  
  10.         super.onCreate(savedInstanceState);  
  11.         setContentView(R.layout.activity_main);  
  12.   
  13.         imgUserHead = (ImageView) findViewById(R.id.img_userhead);  
  14.         btnSaveBoradcase = (Button) findViewById(R.id.btn_broadcast);  
  15.         btnSaveScan = (Button) findViewById(R.id.btn_scan);  
  16.   
  17.         bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.scan);  
  18.         imgUserHead.setImageBitmap(bitmap);  
  19.   
  20.         btnSaveBoradcase.setOnClickListener(this);  
  21.         btnSaveScan.setOnClickListener(this);  
  22.     }  
  23.   
  24.     /** 
  25.      * @author YOLANDA 
  26.      * @param v 
  27.      */  
  28.     @Override  
  29.     public void onClick(View v) {  
  30.         if(v == btnSaveBoradcase) {  
  31.             saveBroadcast();  
  32.         }  
  33.         if(v == btnSaveScan) {  
  34.             saveScan();  
  35.         }  
  36.     }  
  37.   
  38.     /** 
  39.      * 保存后用广播扫描,Android4.4以下使用这个方法 
  40.      * @author YOLANDA 
  41.      */  
  42.     private void saveBroadcast(){  
  43.         String filePath = saveImg(true);  
  44.         sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + filePath)));  
  45.         Toast.makeText(this"保存成功:" + filePath, Toast.LENGTH_LONG).show();  
  46.     }  
  47.   
  48.     /** 
  49.      * 保存后用MediaScanner扫描,通用的方法 
  50.      * @author YOLANDA 
  51.      */  
  52.     private void saveScan(){  
  53.         String filePath = saveImg(false);  
  54.         MediaScanner mediaScanner = new MediaScanner(this);  
  55.         String[] filePaths = new String[]{filePath};  
  56.         String[] mimeTypes = new String[]{MimeTypeMap.getSingleton().getMimeTypeFromExtension("png")};  
  57.         mediaScanner.scanFiles(filePaths, mimeTypes);  
  58.         Toast.makeText(this"保存成功:" + filePath, Toast.LENGTH_LONG).show();  
  59.     }  
  60.   
  61.   
  62.     /** 
  63.      * 保存图片到SD卡 
  64.      * @author YOLANDA 
  65.      * @param isInsertGallery 是否保存到图库 
  66.      * @return 
  67.      */  
  68.     private String saveImg(boolean isInsertGallery){  
  69.         File myappDir = new File(Environment.getExternalStorageDirectory(), "yolanda");  
  70.         if(myappDir.exists() && myappDir.isFile()) {  
  71.             myappDir.delete();  
  72.         }  
  73.         if (!myappDir.exists()) {  
  74.             myappDir.mkdir();  
  75.         }  
  76.         String fileName = System.currentTimeMillis() + ".png";  
  77.         File file = new File(myappDir, fileName);  
  78.         if(file.exists()) {  
  79.             file.delete();  
  80.         }  
  81.         try {  
  82.             FileOutputStream fos = new FileOutputStream(file);  
  83.             bitmap.compress(CompressFormat.PNG, 100, fos);  
  84.             fos.flush();  
  85.             fos.close();  
  86.         } catch (FileNotFoundException e) {  
  87.             e.printStackTrace();  
  88.         } catch (IOException e) {  
  89.             e.printStackTrace();  
  90.         }  
  91.         if(isInsertGallery) {  
  92.             try {  
  93.                 MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), fileName, null);  
  94.             } catch (FileNotFoundException e) {  
  95.                 e.printStackTrace();  
  96.             }  
  97.         }  
  98.         return file.getAbsolutePath();  
  99.     }  
  100.     /** 
  101.      * @author YOLANDA 
  102.      */  
  103.     @Override  
  104.     protected void onDestroy() {  
  105.         super.onDestroy();  
  106.         if(bitmap != null) {  
  107.             bitmap.recycle();  
  108.             bitmap = null;  
  109.         }  
  110.     }  
  111. }  

Demo源码在: http://download.csdn.net/detail/yanzhenjie1003/8573229
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值