我试图从我的应用程序中打开画廊内置应用程序中的图像/图片。
我有一个图片的URI(图片位于SD卡上)。
你有什么建议吗?
我试图从我的应用程序中打开画廊内置应用程序中的图像/图片。
我有一个图片的URI(图片位于SD卡上)。
你有什么建议吗?
当前回答
假设在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卡上显示图像。
如果您能够启动并运行它(可能通过示例提供正确的提供程序),那么您应该能够为您的代码找到一种变通方法。
通过更新这个问题来让我了解你的进展。祝你好运
其他回答
我通过@hcpl和@mad的解决方案。hcpl的解决方案很好地支持图库中的本地图像& mad在此基础上提供了一个更好的解决方案-它也有助于加载OI/Astro/Dropbox图像。但在我的应用程序中,虽然在picasa库工作,现在集成在Android画廊,这两个解决方案都失败了。
我进行了一些搜索和分析,最终得出了一个更好和优雅的解决方案,克服了这一限制。感谢Dimitar Darazhanski的博客,在这种情况下,他帮助了我,我修改了一些,使它更容易理解。这是我的解
public class BrowsePicture extends Activity {
//YOU CAN EDIT THIS TO WHATEVER YOU WANT
private static final int SELECT_PICTURE = 1;
private String selectedImagePath;
//ADDED
private String filemanagerstring;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((Button) findViewById(R.id.Button01))
.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// in onCreate or any event where your want the user to
// select a file
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select Picture"), SELECT_PICTURE);
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
Log.d("URI VAL", "selectedImageUri = " + selectedImageUri.toString());
selectedImagePath = getPath(selectedImageUri);
if(selectedImagePath!=null){
// IF LOCAL IMAGE, NO MATTER IF ITS DIRECTLY FROM GALLERY (EXCEPT PICASSA ALBUM),
// OR OI/ASTRO FILE MANAGER. EVEN DROPBOX IS SUPPORTED BY THIS BECAUSE DROPBOX DOWNLOAD THE IMAGE
// IN THIS FORM - file:///storage/emulated/0/Android/data/com.dropbox.android/...
System.out.println("local image");
}
else{
System.out.println("picasa image!");
loadPicasaImageFromGallery(selectedImageUri);
}
}
}
}
// NEW METHOD FOR PICASA IMAGE LOAD
private void loadPicasaImageFromGallery(final Uri uri) {
String[] projection = { MediaColumns.DATA, MediaColumns.DISPLAY_NAME };
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
if(cursor != null) {
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(MediaColumns.DISPLAY_NAME);
if (columnIndex != -1) {
new Thread(new Runnable() {
// NEW THREAD BECAUSE NETWORK REQUEST WILL BE MADE THAT WILL BE A LONG PROCESS & BLOCK UI
// IF CALLED IN UI THREAD
public void run() {
try {
Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
// THIS IS THE BITMAP IMAGE WE ARE LOOKING FOR.
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
}
}
cursor.close();
}
public String getPath(Uri uri) {
String[] projection = { MediaColumns.DATA};
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
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(MediaColumns.DATA);
String filePath = cursor.getString(columnIndex);
cursor.close();
return filePath;
}
else
return uri.getPath(); // FOR OI/ASTRO/Dropbox etc
}
检查一下,如果有什么问题请告诉我。我已经测试过了,它在每种情况下都很好。
希望这对大家有所帮助。
hcpl的方法在kitkat之前工作得很好,但不能与DocumentsProvider API一起工作。为此,只需简单地遵循官方的Android文档提供者教程:https://developer.android.com/guide/topics/providers/document-provider.html ->打开一个文档,位图部分。
简单地,我使用了hcpl的代码并扩展了它:如果图像的检索路径的文件抛出异常,我调用这个函数:
private Bitmap getBitmapFromUri(Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
}
在Nexus 5上测试。
这是我的例子,可能不完全是你的情况。
假设你从你的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。
public class BrowsePictureActivity extends Activity {
// this is the action code we use in our intent,
// this way we know we're looking at the response from our own action
private static final int SELECT_PICTURE = 1;
private String selectedImagePath;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((Button) findViewById(R.id.Button01))
.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// in onCreate or any event where your want the user to
// select a file
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select Picture"), SELECT_PICTURE);
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
}
}
}
/**
* helper to retrieve the path of an image URI
*/
public String getPath(Uri uri) {
// just some safety built in
if( uri == null ) {
// TODO perform some logging or show user feedback
return null;
}
// try to retrieve the image from the media store first
// this will only work for images selected from gallery
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if( cursor != null ){
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
// this is our fallback here
return uri.getPath();
}
}
要显示图像和视频,请尝试以下方法:
Intent intent = new Intent();
intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 1);
startActivityForResult(Intent.createChooser(intent,"Wybierz plik"), SELECT_FILE);