您的位置:首页 > 移动开发 > Android开发

Android拍照保存在系统相册

2015-10-19 21:15 375 查看
可能大家都知道我们保存相册到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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: