我试图从我的应用程序中打开画廊内置应用程序中的图像/图片。
我有一个图片的URI(图片位于SD卡上)。
你有什么建议吗?
我试图从我的应用程序中打开画廊内置应用程序中的图像/图片。
我有一个图片的URI(图片位于SD卡上)。
你有什么建议吗?
当前回答
除了前面的答案,如果你在获得正确的路径(如AndroZip)有问题,你可以使用这个:
public String getPath(Uri uri ,ContentResolver contentResolver) {
String[] projection = { MediaStore.MediaColumns.DATA};
Cursor cursor;
try{
cursor = contentResolver.query(uri, projection, null, null, null);
} catch (SecurityException e){
String path = uri.getPath();
String result = tryToGetStoragePath(path);
return result;
}
if(cursor != null) {
//HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
//THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
String filePath = cursor.getString(columnIndex);
cursor.close();
return filePath;
}
else
return uri.getPath(); // FOR OI/ASTRO/Dropbox etc
}
private String tryToGetStoragePath(String path) {
int actualPathStart = path.indexOf("//storage");
String result = path;
if(actualPathStart!= -1 && actualPathStart< path.length())
result = path.substring(actualPathStart+1 , path.length());
return result;
}
其他回答
这是我对这个主题的回顾,收集了这里的所有信息,再加上其他相关的堆栈溢出问题。它从某些提供者返回图像,同时处理内存不足的情况和图像旋转。它支持画廊,picasa和文件管理器,如下拉框。用法很简单:作为输入,构造函数接收内容解析器和uri。输出是最终的位图。
/**
* Creates resized images without exploding memory. Uses the method described in android
* documentation concerning bitmap allocation, which is to subsample the image to a smaller size,
* close to some expected size. This is required because the android standard library is unable to
* create a reduced size image from an image file using memory comparable to the final size (and
* loading a full sized multi-megapixel picture for processing may exceed application memory budget).
*/
public class UserPicture {
static int MAX_WIDTH = 600;
static int MAX_HEIGHT = 800;
Uri uri;
ContentResolver resolver;
String path;
Matrix orientation;
int storedHeight;
int storedWidth;
public UserPicture(Uri uri, ContentResolver resolver) {
this.uri = uri;
this.resolver = resolver;
}
private boolean getInformation() throws IOException {
if (getInformationFromMediaDatabase())
return true;
if (getInformationFromFileSystem())
return true;
return false;
}
/* Support for gallery apps and remote ("picasa") images */
private boolean getInformationFromMediaDatabase() {
String[] fields = { Media.DATA, ImageColumns.ORIENTATION };
Cursor cursor = resolver.query(uri, fields, null, null, null);
if (cursor == null)
return false;
cursor.moveToFirst();
path = cursor.getString(cursor.getColumnIndex(Media.DATA));
int orientation = cursor.getInt(cursor.getColumnIndex(ImageColumns.ORIENTATION));
this.orientation = new Matrix();
this.orientation.setRotate(orientation);
cursor.close();
return true;
}
/* Support for file managers and dropbox */
private boolean getInformationFromFileSystem() throws IOException {
path = uri.getPath();
if (path == null)
return false;
ExifInterface exif = new ExifInterface(path);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
this.orientation = new Matrix();
switch(orientation) {
case ExifInterface.ORIENTATION_NORMAL:
/* Identity matrix */
break;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
this.orientation.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
this.orientation.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
this.orientation.setScale(1, -1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
this.orientation.setRotate(90);
this.orientation.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
this.orientation.setRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
this.orientation.setRotate(-90);
this.orientation.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
this.orientation.setRotate(-90);
break;
}
return true;
}
private boolean getStoredDimensions() throws IOException {
InputStream input = resolver.openInputStream(uri);
Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);
/* The input stream could be reset instead of closed and reopened if it were possible
to reliably wrap the input stream on a buffered stream, but it's not possible because
decodeStream() places an upper read limit of 1024 bytes for a reset to be made (it calls
mark(1024) on the stream). */
input.close();
if (options.outHeight <= 0 || options.outWidth <= 0)
return false;
storedHeight = options.outHeight;
storedWidth = options.outWidth;
return true;
}
public Bitmap getBitmap() throws IOException {
if (!getInformation())
throw new FileNotFoundException();
if (!getStoredDimensions())
throw new InvalidObjectException(null);
RectF rect = new RectF(0, 0, storedWidth, storedHeight);
orientation.mapRect(rect);
int width = (int)rect.width();
int height = (int)rect.height();
int subSample = 1;
while (width > MAX_WIDTH || height > MAX_HEIGHT) {
width /= 2;
height /= 2;
subSample *= 2;
}
if (width == 0 || height == 0)
throw new InvalidObjectException(null);
Options options = new Options();
options.inSampleSize = subSample;
Bitmap subSampled = BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);
Bitmap picture;
if (!orientation.isIdentity()) {
picture = Bitmap.createBitmap(subSampled, 0, 0, options.outWidth, options.outHeight,
orientation, false);
subSampled.recycle();
} else
picture = subSampled;
return picture;
}
}
引用:
http://developer.android.com/training/displaying-bitmaps/index.html 通过编程方式从Android内置的Gallery应用程序中获取/选择一张图像 在将图像加载到位图对象时出现奇怪的内存不足问题 使用ExifInterface设置图像方向 https://gist.github.com/9re/1990019 如何获得位图信息,然后解码位图从internet-inputStream?
假设在SD卡目录中有一个图像文件夹仅用于图像。
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// tells your intent to get the contents
// opens the URI for your image directory on your sdcard
intent.setType("file:///sdcard/image/*");
startActivityForResult(intent, 1);
然后,您可以决定如何处理活动中的内容。
这是一个检索图像路径名称的示例,用您的代码进行测试,以确保您可以处理返回的结果。您可以根据需要更改代码以更好地满足您的需求。
protected final void onActivityResult(final int requestCode, final int
resultCode, final Intent i) {
super.onActivityResult(requestCode, resultCode, i);
// this matches the request code in the above call
if (requestCode == 1) {
Uri _uri = i.getData();
// this will be null if no image was selected...
if (_uri != null) {
// now we get the path to the image file
cursor = getContentResolver().query(_uri, null,
null, null, null);
cursor.moveToFirst();
String imageFilePath = cursor.getString(0);
cursor.close();
}
}
我的建议是尽量让检索图像工作正确,我认为问题是在存储卡上访问图像的内容。看一下在sd卡上显示图像。
如果您能够启动并运行它(可能通过示例提供正确的提供程序),那么您应该能够为您的代码找到一种变通方法。
通过更新这个问题来让我了解你的进展。祝你好运
这是我的例子,可能不完全是你的情况。
假设你从你的API提供者获得base64格式,给它一个文件名和文件扩展名,将它保存到文件系统中的某个位置。
public static void shownInBuiltInGallery(final Context ctx, String strBase64Image, final String strFileName, final String strFileExtension){
new AsyncTask<String, String, File>() {
@Override
protected File doInBackground(String... strBase64Image) {
Bitmap bmpImage = convertBase64StringToBitmap(strBase64Image[0], Base64.NO_WRAP);
if(bmpImage == null) {
cancel(true);
return null;
}
byte[] byImage = null;
if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_JPG) == 0) {
byImage = convertToJpgByte(bmpImage); // convert bitmap to binary for latter use
} else if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_PNG) == 0){
byImage = convertToPngByte(bmpImage); // convert bitmap to binary for latter use
} else if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_BMP) == 0){
byImage = convertToBmpByte(bmpImage); // convert bitmap to binary for latter use
} else {
cancel(true);
return null;
}
if(byImage == null) {
cancel(true);
return null;
}
File imageFolder = ctx.getExternalCacheDir();
if(imageFolder.exists() == false){
if(imageFolder.mkdirs() == false){
cancel(true);
return null;
}
}
File imageFile = null;
try {
imageFile = File.createTempFile(strFileName, strFileExtension, imageFolder);
} catch (IOException e){
e.printStackTrace();
}
if(imageFile == null){
cancel(true);
return null;
}
if (imageFile.exists() == true) {
if(imageFile.delete() == false){
cancel(true);
return null;
}
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(imageFile.getPath());
fos.write(byImage);
fos.flush();
fos.close();
} catch (java.io.IOException e) {
e.printStackTrace();
} finally {
fos = null;
}
return imageFile;
}
@Override
protected void onPostExecute(File file) {
super.onPostExecute(file);
String strAuthority = ctx.getPackageName() + ".provider";
Uri uriImage = FileProvider.getUriForFile(ctx, strAuthority, file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uriImage, "image/*");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
ctx.startActivity(intent);
}
}.execute(strBase64Image);}
不要忘记在AndroidManifest.xml中首先设置一个适当的文件提供程序
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
文件路径是XML在…/res/ XML /file_path.xml
<?xml version="1.0" encoding="utf-8"?>
<external-files-path name="external_files" path="Accessory"/>
<external-path name="ex_Download" path="Download/" />
<external-path name="ex_Pictures" path="Pictures/" />
<external-files-path name="my_Download" path="Download/" />
<external-files-path name="my_Pictures" path="Pictures/" />
<external-cache-path name="my_cache" path="." />
<files-path name="private_Download" path="Download/" />
<files-path name="private_Pictures" path="Pictures/" />
<cache-path name="private_cache" path="." />
长话短说,首先准备好文件提供程序,将已知且可访问的图片源的Uri传递给Intent,否则,将图片保存在所需的位置,然后将位置(作为Uri)传递给Intent。
检索特定类型的文件
这个示例将获得图像的副本。
static final int REQUEST_IMAGE_GET = 1;
public void selectImage() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_IMAGE_GET);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_GET && resultCode == RESULT_OK) {
Bitmap thumbnail = data.getParcelable("data");
Uri fullPhotoUri = data.getData();
// Do work with photo saved at fullPhotoUri
...
}
}
打开特定类型的文件
在4.4或更高版本上运行时,您请求打开由另一个应用程序管理的文件
static final int REQUEST_IMAGE_OPEN = 1;
public void selectImage() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("image/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Only the system receives the ACTION_OPEN_DOCUMENT, so no need to test.
startActivityForResult(intent, REQUEST_IMAGE_OPEN);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_OPEN && resultCode == RESULT_OK) {
Uri fullPhotoUri = data.getData();
// Do work with full size photo saved at fullPhotoUri
...
}
}
原始来源
请找到从图库中选择单个图像的答案
import android.app.Activity;
import android.net.Uri;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class PickImage extends Activity {
Button btnOpen, btnGet, btnPick;
TextView textInfo1, textInfo2;
ImageView imageView;
private static final int RQS_OPEN_IMAGE = 1;
private static final int RQS_GET_IMAGE = 2;
private static final int RQS_PICK_IMAGE = 3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image_pick);
btnOpen = (Button)findViewById(R.id.open);
btnGet = (Button)findViewById(R.id.get);
btnPick = (Button)findViewById(R.id.pick);
textInfo1 = (TextView)findViewById(R.id.info1);
textInfo2 = (TextView)findViewById(R.id.info2);
imageView = (ImageView) findViewById(R.id.image);
btnOpen.setOnClickListener(btnOpenOnClickListener);
btnGet.setOnClickListener(btnGetOnClickListener);
btnPick.setOnClickListener(btnPickOnClickListener);
}
View.OnClickListener btnOpenOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, RQS_OPEN_IMAGE);
}
};
View.OnClickListener btnGetOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, RQS_OPEN_IMAGE);
}
};
View.OnClickListener btnPickOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RQS_PICK_IMAGE);
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == RQS_OPEN_IMAGE ||
requestCode == RQS_GET_IMAGE ||
requestCode == RQS_PICK_IMAGE) {
imageView.setImageBitmap(null);
textInfo1.setText("");
textInfo2.setText("");
Uri mediaUri = data.getData();
textInfo1.setText(mediaUri.toString());
String mediaPath = mediaUri.getPath();
textInfo2.setText(mediaPath);
//display the image
try {
InputStream inputStream = getBaseContext().getContentResolver().openInputStream(mediaUri);
Bitmap bm = BitmapFactory.decodeStream(inputStream);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
byte[] byteArray = stream.toByteArray();
imageView.setImageBitmap(bm);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
}