Próbuję udostępnić w aplikacji aktywność, która wyświetla miniatury zdjęć w magazynie mediów urządzenia i umożliwia użytkownikowi jej wybór. Po wybraniu przez użytkownika wyboru aplikacja odczytuje oryginalny obraz w pełnym rozmiarze i robi rzeczy z nim.Jak zapytać dostawcę zawartości Android MediaStore, unikając osieroconych obrazów?
Używam następujący kod do tworzenia Cursor
nad wszystkich obrazów na zewnętrznym przechowywania:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image_select);
mGridView = (GridView) findViewById(R.id.image_select_grid);
// Query for all images on external storage
String[] projection = { MediaStore.Images.Media._ID };
String selection = "";
String [] selectionArgs = null;
mImageCursor = managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection, selection, selectionArgs, null);
// Initialize an adapter to display images in grid
if (mImageCursor != null) {
mImageCursor.moveToFirst();
mAdapter = new LazyCursorAdapter(this, mImageCursor, R.drawable.image_select_default);
mGridView.setAdapter(mAdapter);
} else {
Log.i(TAG, "System media store is empty.");
}
}
i następujący kod, aby załadować obraz miniatury (Android 2.x kod jest pokazany) :
// ...
// Build URI to the main image from the cursor
int imageID = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media._ID));
Uri uri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
Integer.toString(imageID));
loadThumbnailImage(uri.toString());
// ...
protected Bitmap loadThumbnailImage(String url) {
// Get original image ID
int originalImageId = Integer.parseInt(url.substring(url.lastIndexOf("/") + 1, url.length()));
// Get (or create upon demand) the micro thumbnail for the original image.
return MediaStore.Images.Thumbnails.getThumbnail(mContext.getContentResolver(),
originalImageId, MediaStore.Images.Thumbnails.MICRO_KIND, null);
}
i następujący kod do załadowania obrazu z oryginalnego adresu URL, gdy użytkownik dokonuje wyboru:
public Bitmap loadFullImage(Context context, Uri photoUri ) {
Cursor photoCursor = null;
try {
// Attempt to fetch asset filename for image
String[] projection = { MediaStore.Images.Media.DATA };
photoCursor = context.getContentResolver().query(photoUri,
projection, null, null, null);
if (photoCursor != null && photoCursor.getCount() == 1) {
photoCursor.moveToFirst();
String photoFilePath = photoCursor.getString(
photoCursor.getColumnIndex(MediaStore.Images.Media.DATA));
// Load image from path
return BitmapFactory.decodeFile(photoFilePath, null);
}
} finally {
if (photoCursor != null) {
photoCursor.close();
}
}
return null;
}
Problem, który widzę na niektórych urządzeniach z Androidem, w tym w moim telefonie osobistym, polega na tym, że kursor , który otrzymuję z zapytania w onCreate()
, zawiera kilka pozycji, dla których faktycznie pełnowymiarowy plik obrazu (JPG lub PNG) brakuje. (W przypadku mojego telefonu obrazy zostały zaimportowane, a następnie usunięte przez iPhoto).
Osierocone wpisy mogą mieć lub nie miniatury, w zależności od tego, czy miniatury zostały wygenerowane przed rzeczywistym plikiem multimedialnym, gdy AWOL. W rezultacie aplikacja wyświetla miniatury obrazów, które w rzeczywistości nie istnieją.
mam kilka pytań:
- Czy istnieje kwerenda mogę zrobić, aby dostawcy treści
MediaStore
że będzie odfiltrować zdjęć z brakujących mediów w zwróconymCursor
? - Czy istnieje środek lub interfejs API, który zmusza skaner do przetestowania, i eliminuje pozycje osierocone? Na moim telefonie zamontowałem USB, a następnie odmontowałem zewnętrzne nośniki, które mają wywołać ponowne skanowanie. Ale pozycje sieroce pozostają.
- Czy jest coś fundamentalnie nie tak z moim podejściem, które powoduje ten problem?
Dzięki.