В настоящее время я создаю приложение, которое работает с изображениями. Мне нужно реализовать функциональность, когда пользователь выбирает файл, хранящийся на SD-карте. Как только они выберут изображение (используя галерею Android), расположение файла изображения будет отправлено на другое мероприятие, где будет выполняться другая работа.
Я видел похожие сообщения здесь, на SO, но никто не ответил на мой вопрос конкретно. В основном это код, который я делаю, когда пользователь нажимает кнопку "Загрузить изображение":
// Create a new Intent to open the picture selector:
Intent loadPicture = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
// To start it, run the startActivityForResult() method:
startActivityForResult(loadPicture, SELECT_IMAGE);
Из этого кода у меня затем есть метод onActivityResult()
для прослушивания обратного вызова:
// If the user tried to select an image:
if(requestCode == SELECT_IMAGE)
{
// Check if the user actually selected an image:
if(resultCode == Activity.RESULT_OK)
{
// This gets the URI of the image the user selected:
Uri selectedImage = data.getData();
// Create a new Intent to send to the next Activity:
Intent i = new Intent(currentActivty.this, nextActivity.class);
// ----------------- Problem Area -----------------
// I would like to send the filename to the Intent object, and send it over.
// However, the selectedImage.toString() method will return a
// "content://" string instead of a file location. How do I get a file
// location from that URI object?
i.putExtra("PICTURE_LOCATION", selectedImage.toString());
// Start the activity outlined with the Intent above:
startActivity(i);
Как указано выше в коде, uri.toString()
вернет строку content://
вместо местоположения файла выбранного изображения. Как получить местоположение файла?
Примечание. Еще одно возможное решение - отправить по строке content://
и преобразовать ее в Bitmap
(что и происходит в следующем действии). Однако я не знаю, как это сделать.
Я нашел ответ на свой вопрос. Сделав еще несколько поисков, я, наконец, наткнулся на сообщение здесь, на SO, которое задает тот же вопрос: android получить реальный путь Uri.getPath().
К сожалению, ответ имеет сломанную ссылку. После некоторого поиска Google я нашел правильную ссылку на сайт здесь: http://www.androidsnippets.org/snippets/130/ (я убедился, что этот код действительно работает.)
Однако я решил пойти по другому пути. Поскольку мое следующее действие использует ImageView
для отображения изображения, я вместо этого собираюсь использовать строку содержимого Uri для всех методов, которые ссылаются на следующее действие.
В следующем действии я использую метод ImageView.setImageUri()
.
Вот код, который я делаю в следующем Управлении, чтобы отобразить изображение из строки content://
:
// Get the content string from the previous Activity:
picLocation = getIntent().getStringExtra("PICTURE_LOCATION");
// Instantiate the ImageView object:
ImageView imageViewer = (ImageView)findViewById(R.id.ImageViewer);
// Convert the Uri string into a usable Uri:
Uri temp = Uri.parse(picLocation);
imageViewer.setImageURI(temp);
Я надеюсь, что этот вопрос и ответ будут полезны будущим разработчикам Android.
Вот еще один ответ, который, надеюсь, кто-то найдет полезным:
Вы можете сделать это для любого контента в MediaStore. В моем приложении я должен получить путь от URI и получить URI из путей. Первый:
/**
* Gets the corresponding path to a file from the given content:// URI
* @param selectedVideoUri The content:// URI to find the file path from
* @param contentResolver The content resolver to use to perform the query.
* @return the file path as a string
*/
private String getFilePathFromContentUri(Uri selectedVideoUri,
ContentResolver contentResolver) {
String filePath;
String[] filePathColumn = {MediaColumns.DATA};
Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
filePath = cursor.getString(columnIndex);
cursor.close();
return filePath;
}
Последний (который я делаю для видео, но также можно использовать для аудио или файлов или других типов хранимого содержимого, заменив MediaStore.Audio(и т.д.) для MediaStore.Video:
/**
* Gets the MediaStore video ID of a given file on external storage
* @param filePath The path (on external storage) of the file to resolve the ID of
* @param contentResolver The content resolver to use to perform the query.
* @return the video ID as a long
*/
private long getVideoIdFromFilePath(String filePath,
ContentResolver contentResolver) {
long videoId;
Log.d(TAG,"Loading file " + filePath);
// This returns us content://media/external/videos/media (or something like that)
// I pass in "external" because that the MediaStore name for the external
// storage on my device (the other possibility is "internal")
Uri videosUri = MediaStore.Video.Media.getContentUri("external");
Log.d(TAG,"videosUri = " + videosUri.toString());
String[] projection = {MediaStore.Video.VideoColumns._ID};
// TODO This will break if we have no matching item in the MediaStore.
Cursor cursor = contentResolver.query(videosUri, projection, MediaStore.Video.VideoColumns.DATA + " LIKE ?", new String[] { filePath }, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(projection[0]);
videoId = cursor.getLong(columnIndex);
Log.d(TAG,"Video ID is " + videoId);
cursor.close();
return videoId;
}
В принципе, столбец DATA
MediaStore
(или какой-либо его подсектор, который вы запрашиваете) сохраняет путь к файлу, поэтому вы используете то, что знаете, для поиска DATA или вы запрашиваете на DATA
, чтобы выбрать интересующий вас контент.