Android拍照保存在系统相册

来源:互联网 发布:java获取毫秒数 编辑:程序博客网 时间:2024/05/16 13:50

可能大家都知道我们保存相册到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;}








0 0
原创粉丝点击