Android拍照保存在系统相册

可能大家都知道我们保存相册到Android手机的时候,然后去打开系统图库找不到我们想要的那张图片,那是因为我们插入的图片还没有更新的缘故,先讲解下插入系统图库的方法吧,很简单,一句代码就能实现

MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", "");  

过上面的那句代码就能插入到系统图库,这时候有一个问题,就是我们不能指定插入照片的名字,而是系统给了我们一个当前时间的毫秒数为名字

<span style="white-space:pre">		</span>/** 
            * Insert an image and create a thumbnail for it. 
            * 
            * @param cr The content resolver to use 
            * @param source The stream to use for the image 
            * @param title The name of the image 
            * @param description The description of the image 
            * @return The URL to the newly created image, or <code>null</code> if the image failed to be stored 
            *              for any reason. 
            */  
           public static final String insertImage(ContentResolver cr, Bitmap source,  
                                                  String title, String description) {  
               ContentValues values = new ContentValues();  
               values.put(Images.Media.TITLE, title);  
               values.put(Images.Media.DESCRIPTION, description);  
               values.put(Images.Media.MIME_TYPE, "image/jpeg");  
  
               Uri url = null;  
               String stringUrl = null;    /* value to be returned */  
  
               try {  
                   url = cr.insert(EXTERNAL_CONTENT_URI, values);  
  
                   if (source != null) {  
                       OutputStream imageOut = cr.openOutputStream(url);  
                       try {  
                           source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut);  
                       } finally {  
                           imageOut.close();  
                       }  
  
                       long id = ContentUris.parseId(url);  
                       // Wait until MINI_KIND thumbnail is generated.  
                       Bitmap miniThumb = Images.Thumbnails.getThumbnail(cr, id,  
                               Images.Thumbnails.MINI_KIND, null);  
                       // This is for backward compatibility.  
                       Bitmap microThumb = StoreThumbnail(cr, miniThumb, id, 50F, 50F,  
                               Images.Thumbnails.MICRO_KIND);  
                   } else {  
                       Log.e(TAG, "Failed to create thumbnail, removing original");  
                       cr.delete(url, null, null);  
                       url = null;  
                   }  
               } catch (Exception e) {  
                   Log.e(TAG, "Failed to insert image", e);  
                   if (url != null) {  
                       cr.delete(url, null, null);  
                       url = null;  
                   }  
               }  
  
               if (url != null) {  
                   stringUrl = url.toString();  
               }  
  
               return stringUrl;  
           }  

当然Android还提供了一个插入系统相册的方法,可以指定保存图片的名字:

         /** 
          * Insert an image and create a thumbnail for it. 
          * 
          * @param cr The content resolver to use 
          * @param imagePath The path to the image to insert 
          * @param name The name of the image 
          * @param description The description of the image 
          * @return The URL to the newly created image 
          * @throws FileNotFoundException 
          */  
         public static final String insertImage(ContentResolver cr, String imagePath,  
                 String name, String description) throws FileNotFoundException {  
             // Check if file exists with a FileInputStream  
             FileInputStream stream = new FileInputStream(imagePath);  
             try {  
                 Bitmap bm = BitmapFactory.decodeFile(imagePath);  
                 String ret = insertImage(cr, bm, name, description);  
                 bm.recycle();  
                 return ret;  
             } finally {  
                 try {  
                     stream.close();  
                 } catch (IOException e) {  
                 }  
             }  
         }  
上面那段代码插入到系统相册之后还需要发条广播:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));    
这个广播在4.4 以上的手机会报错( 那是因为Android4.4中限制了系统应用才有权限使用广播通知系统扫描SD卡):

W/ActivityManager(  498): Permission Denial: not allowed to send broadcast android.intent.action.MEDIA_MOUNTED from pid=2269, uid=20016 

解决方式: 
使用MediaScannerConnection执行具体文件或文件夹进行扫描。

MediaScannerConnection.scanFile(this, new String[]{Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath() + "/" + fileName}, null, null);
<span style="white-space:pre">	</span>String url = MediaStore.Images.Media.insertImage(context.getContentResolver(), mBitmap, "", "");
        // 4.4以上 Android 不允许发送 Intent.ACTION_MEDIA_MOUNTED
        // context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory() + url)));
        // 这个扫描指定文件,不能用于扫描文件夹
        // context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + Environment.getExternalStorageDirectory() + url)));
        MediaScannerConnection.scanFile(context, new String[]{FileUtil.getRealFilePath(context, Uri.parse(url))}, null, null);


 
 可能你会问我,怎么获取到我们刚刚插入的图片的路径?呵呵,这个自有方法获取: 
 
      /**
	 * 将文件相对路径uri 转化为绝对路径
	 * content://media/external/images/media/62026  ===>> url
	 *
	 * @param context
	 * @param uri
	 * @return
	 */
	public static String getRealFilePath( final Context context, final Uri uri ) {
		if ( null == uri ) return null;
		final String scheme = uri.getScheme();
		String data = null;
		if ( scheme == null )
			data = uri.getPath();
		else if ( ContentResolver.SCHEME_FILE.equals( scheme ) ) {
			data = uri.getPath();
		} else if ( ContentResolver.SCHEME_CONTENT.equals( scheme ) ) {
			Cursor cursor = context.getContentResolver().query( uri, new String[] { MediaStore.Images.ImageColumns.DATA }, null, null, null );
			if ( null != cursor ) {
				if ( cursor.moveToFirst() ) {
					int index = cursor.getColumnIndex( MediaStore.Images.ImageColumns.DATA );
					if ( index > -1 ) {
						data = cursor.getString( index );
					}
				}
				cursor.close();
			}
		}
		return data;
	}

补充: 今天在看系统截图源码的时候,里面也有保存屏幕截图到系统图库的代码,如下:

      Context context = params[0].context;  
        Bitmap image = params[0].image;  
        Resources r = context.getResources();  
  
        try {  
            // Create screenshot directory if it doesn't exist  
            mScreenshotDir.mkdirs();  
  
            // media provider uses seconds for DATE_MODIFIED and DATE_ADDED, but milliseconds  
            // for DATE_TAKEN  
            long dateSeconds = mImageTime / 1000;  
  
            // Save the screenshot to the MediaStore  
            ContentValues values = new ContentValues();  
            ContentResolver resolver = context.getContentResolver();  
            values.put(MediaStore.Images.ImageColumns.DATA, mImageFilePath);  
            values.put(MediaStore.Images.ImageColumns.TITLE, mImageFileName);  
            values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, mImageFileName);  
            values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, mImageTime);  
            values.put(MediaStore.Images.ImageColumns.DATE_ADDED, dateSeconds);  
            values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, dateSeconds);  
            values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png");  
            values.put(MediaStore.Images.ImageColumns.WIDTH, mImageWidth);  
            values.put(MediaStore.Images.ImageColumns.HEIGHT, mImageHeight);  
            Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);  
  
            OutputStream out = resolver.openOutputStream(uri);  
            image.compress(Bitmap.CompressFormat.PNG, 100, out);  
            out.flush();  
            out.close();  
  
            // update file size in the database  
            values.clear();  
            values.put(MediaStore.Images.ImageColumns.SIZE, new File(mImageFilePath).length());  
            resolver.update(uri, values, null, null);  
  
             
        } catch (Exception e) {  
             
        }  

继续补充: 

MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", "");  

上面说的这个方法在本地相册路径不存在的时候 会抛出异常 FileNotFound ,当然这种情况下手机中不会存在,但是,市面上某些模拟器在没有拍过照片的情况下就会出现。 所以为了适配这种情况,换方法。


/**
 * 将图片保存至系统相册,并让系统刷新相册中的指定图片
 * @param context
 * @param mBitmap
 */
public static String savePicToSystemGallery(Context context, Bitmap mBitmap){
    // 这个insertImage 在本地相册路径不存在的时候回抛异常 : 例如天天模拟器
    // String url = MediaStore.Images.Media.insertImage(context.getContentResolver(), mBitmap, "", "");
    String url = PicUtil.saveBitmapToSDCard(System.currentTimeMillis() + "", mBitmap);
    // 4.4以上 Android 不允许发送 Intent.ACTION_MEDIA_MOUNTED
    // context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory() + url)));
    // 这个扫描指定文件,不能用于扫描文件夹
    // context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + Environment.getExternalStorageDirectory() + url)));
    MediaScannerConnection.scanFile(context, new String[]{FileUtil.getRealFilePath(context, Uri.parse(url))}, null, null);
    return url;
}


public static String saveBitmapToSDCard(String picName, Bitmap bitmap) {
    try {
        File saveFile = new File(Environment.getExternalStorageDirectory().toString() + File.separator + PayConstants.KP_FOLDER_PATH + PayConstants.KP_SCREEN_SHOT_PATH + picName
                + ".png");
        if (!saveFile.exists()) {
            File dir = new File(saveFile.getParent());
            dir.mkdirs();
            saveFile.createNewFile();
        }
        FileOutputStream saveFileOutputStream;
        saveFileOutputStream = new FileOutputStream(saveFile);
        boolean nowbol = bitmap.compress(Bitmap.CompressFormat.PNG, 100,
                saveFileOutputStream);
        saveFileOutputStream.close();
        if(nowbol) {
            return saveFile.getPath();
        }

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}








你可能感兴趣的:(android,图片,图库,保存图片到系统相册,不显示的问题)