I have built a custom camera app that saves pictures to a specific folder on my sdcard and has its own gallery view for viewing the photos in that folder "/sdcard/myApp/images"
I have been testing it on two different tablets, Galaxy Tab-1 10 inch and Galaxy Tab-2 10 inch. The camera works on both tablets just fine, taking pictures and saving them to the app created folder. But the gallery View on the Tab1, doesn't show all the photos in that folder. The tab-2 always shows all the photos currently in the folder but the tab-1 often only shows the images in that folder from the last time the tablet was rebooted.
So on the Tab-1 if i have no photos in that folder and then take two pictures with the camera and switch to the gallery view, it shows no photos. If i then reboot, and go to the gallery view i see both of the photos, but if i switch to the camera and take another photo the gallery only shows the original two until i reboot.
works on android 3.2 + but 3.1 nope!
Any ideas?
cursor sent to adapter in constructor of galleryView:
// Set up an array of the Thumbnail Image ID column we want
String[] projection = {MediaStore.Images.Media._ID};
// Create the cursor pointing to the SDCard
cursor = managedQuery( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection, // Which columns to return
MediaStore.Images.Media.DATA + " like ? ",
new String[] {"%LC/images%"},
MediaStore.Images.Media._ID + " DESC");
// Get the column index of the Thumbnails Image ID
columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
ga.setAdapter(new GallAdapter(this,cursor,columnIndex));
addapter:
public class GallAdapter extends BaseAdapter {
public Cursor cursor;
private int columnIndex;
private Context context;
int imageBackground;
String url;
Uri uri;
int originalImageId;
int imageID;
int columnData;
ViewGroup myp;
ImageView d;
public GallAdapter(Context ctx, Cursor cur, int cIn ) {
context = ctx;
columnIndex = cIn;
cursor = cur;
Log.v("GallAdapter", "COUNT:"+getCount());
}
#Override
public int getCount() {
return cursor.getCount();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
myp = parent;
View v;
if(convertView ==null){
v = LayoutInflater.from(context).inflate(R.layout.galitem, parent, false);
}else{
v = convertView;
}
ImageView photo = (ImageView) v.findViewById(R.id.imageView);
ImageView border = (ImageView) v.findViewById(R.id.borderView);
d = (ImageView) v.findViewById(R.id.delView);
// Move cursor to current position
cursor.moveToPosition(position);
// Get the current value for the requested column
imageID = cursor.getInt(columnIndex);
// obtain the image URI
uri = Uri.withAppendedPath( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, Integer.toString(imageID) );
url = uri.toString();
// Set the content of the image based on the image URI
originalImageId = Integer.parseInt(url.substring(url.lastIndexOf("/") + 1, url.length()));
Bitmap b = MediaStore.Images.Thumbnails.getThumbnail(context.getContentResolver(),
originalImageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
photo.setImageBitmap(b);
photo.setScaleType(ImageView.ScaleType.FIT_CENTER);
d.setTag(uri);
d.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
String path = getRealPathFromURI((Uri) v.getTag());
alertBox("Warning!", "Are you sure you want to delete this photo?", path, v);
}
});
return v;
}
again this works on tab-2 (os 4.0) and tab-1 now that the firm ware was updated on the tab-1 and the os from 3.1 to 3.2 but why was it not working..
Try this in order to refresh your media files.
this._context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + Environment.getExternalStorageDirectory() + "/Hugg/" + name)));
Related
I have modified the code in this question ,according to the answers there, in order to load contact's picture on a ListView. I am getting the Photo_id, and use it to get the Bitmap of the contact, using loadContactPhoto(ContentResolver cr, long id) . The problem is that no ImageView is getting a new image, although the photo id is always different. I tried using the Contact._ID, but still only two contacts' ImageView got a contact picture, and they were both wrong. I have commented the new lines I have added below.
Here is the code after the edit:
ContactStock:
public class ContactStock {
private String name;
private String number;
private Bitmap picture;
public ContactStock(String name, String number) {
this.name = name;
this.number = number;
}
public ContactStock(String name, String number, Bitmap photo) {
this.name = name;
this.number = number;
this.picture = photo;
}
public void setName(String name) {
this.name = name;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return this.name;
}
public String getNumber() {
return this.number;
}
public void setPicture(Bitmap picture) { // NEW METHOD
this.picture = picture;
}
public Bitmap getPicture() { // NEW METHOD
return picture;
}
}
addlistfromcontact:
public class addlistfromcontact extends Activity {
private ListView lst;
private List<ContactStock> contactstock;
private Cursor mCursor;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_contact_list);
lst = (ListView) findViewById(R.id.tab_contact_list);
contactstock = new ArrayList<ContactStock>();
mCursor = managedQuery(ContactsContract.Data.CONTENT_URI, null,
Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", null,
ContactsContract.Data.DISPLAY_NAME + " ASC");
int number = mCursor.getColumnIndex(Phone.NUMBER);
int name = mCursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME);
int id = mCursor.getColumnIndex(Contacts.PHOTO_ID); // NEW LINE
while (mCursor.moveToNext()) {
String phName = mCursor.getString(name);
String phNumber = mCursor.getString(number);
long phId = mCursor.getLong(id); // NEW LINE
Bitmap phPhoto = loadContactPhoto(getContentResolver(), phId); // NEW LINE
Log.d("phId=", phId + "");
contactstock.add(new ContactStock(phName, phNumber, phPhoto)); // NEW LINE EDIT
}
lst.setAdapter(new ContactListAdapter(addlistfromcontact.this,
contactstock));
}
public static Bitmap loadContactPhoto(ContentResolver cr, long id) { // NEW METHOD
Uri uri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI, id);
InputStream input = ContactsContract.Contacts
.openContactPhotoInputStream(cr, uri);
if (input == null) {
return null;
}
return BitmapFactory.decodeStream(input);
}
}
ContactListAdapter:
public class ContactListAdapter extends ArrayAdapter {
private final Activity activity;
private final List stocks;
public ContactListAdapter(Activity activity, List objects) {
super(activity, R.layout.listview_detail_tab_contact_list, objects);
this.activity = activity;
this.stocks = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
ContactStockView sv = null;
if (rowView == null) {
// Get a new instance of the row layout view
LayoutInflater inflater = activity.getLayoutInflater();
rowView = inflater.inflate(
R.layout.listview_detail_tab_contact_list, null);
// Hold the view objects in an object,
// so they don't need to be re-fetched
sv = new ContactStockView();
sv.name = (TextView) rowView.findViewById(R.id.contact_name);
sv.number = (TextView) rowView.findViewById(R.id.contact_number);
sv.photo = (ImageView) rowView.findViewById(R.id.contact_photo);
// Cache the view objects in the tag,
// so they can be re-accessed later
rowView.setTag(sv);
} else {
sv = (ContactStockView) rowView.getTag();
}
// Transfer the stock data from the data object
// to the view objects
ContactStock currentStock = (ContactStock) stocks.get(position);
sv.name.setText(currentStock.getName());
sv.number.setText(currentStock.getNumber());
sv.photo.setImageBitmap(currentStock.getPicture()); // NEW LINE
// TODO Auto-generated method stub
return rowView;
}
protected static class ContactStockView {
protected TextView name;
protected TextView number;
protected ImageView photo; // NEW LINE
}
}
There are two problems in your code. The first one is easy to overcome, the others need more work.
Lets start with the easy one:
The method ContactsContract.Contacts.openContactPhotoInputStream(cr, uri) takes a contact uri and not a photo uri. That is the id in your call to ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id) has to be a contact id.
Also you create a lot of Bitmap objects when iterating over the result set. Don't do this. Though this might work at first, it probably crashes with OutOfMemory errors when the list get's to long. Try to create as few Bitmapobjects as necessary. That is: Only for those rows visible. When scrolling the list view you have to recycle existing Bitmaps.
Since I had lots of trouble figuring out how to load all contacts' photos efficiently without any UI freezing, errors on loading the images when I first started working on Android, I highly recommend anyone looking at my question to take a good look here.
It's a sample app that teaches you how to handle all proccessing data and loading images seamingly, efficiently without any 'hiccups' while scrolling your list. It is also a great project to get you started working on Android!
Specifically, for the contact image part of my questions code, the API provides two simple methods that can be found here that returns the InputStream of the contact's high res image or thumbnail. All you have to do is decode it using BitmapFactory.decodeByteArray(). Remember to load the size of the image you need to use in your app (something described in the link above), so that you won't get an OutOfMemoryError!
In order to improve the code further, you can also replace the ArrayAdapter with a custom Cursor adapter, and only load the lines of the listView you need on the spot.
I have a working custom camera and gallery view in my android app. My camera saves pictures with a timestamp essentially as their name in a specific folder which i have successfully got showing in my gallery. It seems that it sorts these images by default from oldest to newest or alphabetically, not sure.. but i would like them to display in the opposite order.. can someone point me in the right direction? is it possible? do i change my BaseAdapter or my oncreate of my gallery activity...
my gallery activity:
public class GalleryView extends Activity{
ImageView imageView;
Cursor cursor;
private int columnIndex;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gallery);
Gallery ga = (Gallery)findViewById(R.id.Gallery01);
// Set up an array of the Thumbnail Image ID column we want
String[] projection = {MediaStore.Images.Media._ID};
// Create the cursor pointing to the SDCard
cursor = managedQuery( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection, // Which columns to return
MediaStore.Images.Media.DATA + " like ? ",
new String[] {"%LC/images%"},
null);
// Get the column index of the Thumbnails Image ID
columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
ga.setAdapter(new GallImageAdapter(this,cursor,columnIndex));
}
}
my custom adapter:
public class GallImageAdapter extends BaseAdapter {
public Cursor cursor;
private int columnIndex;
private Context context;
int imageBackground;
public GallImageAdapter(Context ctx, Cursor cur, int cIn) {
context = ctx;
columnIndex = cIn;
cursor = cur;
}
#Override
public int getCount() {
return cursor.getCount();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v;
if(convertView ==null){
v = LayoutInflater.from(context).inflate(R.layout.galitem, parent, false);
}else{
v = convertView;
}
ImageView photo = (ImageView) v.findViewById(R.id.imageView);
ImageView border = (ImageView) v.findViewById(R.id.borderView);
ImageView d = (ImageView) v.findViewById(R.id.delView);
// Move cursor to current position
cursor.moveToPosition(position);
// Get the current value for the requested column
int imageID = cursor.getInt(columnIndex);
// obtain the image URI
Uri uri = Uri.withAppendedPath( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, Integer.toString(imageID) );
String url = uri.toString();
// Set the content of the image based on the image URI
int originalImageId = Integer.parseInt(url.substring(url.lastIndexOf("/") + 1, url.length()));
Bitmap b = MediaStore.Images.Thumbnails.getThumbnail(context.getContentResolver(),
originalImageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
photo.setImageBitmap(b);
photo.setScaleType(ImageView.ScaleType.FIT_CENTER);
return v;
}
}
The last parameter is for describing the order of URI in interest.
Try this approach to sort images in descending order
final String orderBy = MediaStore.Images.Media._ID;
cursor = managedQuery( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection, // Which columns to return
MediaStore.Images.Media.DATA + " like ? ",
new String[] {"%LC/images%"},
orderBy + " DESC");
In my app I need to implement an option for the user to select images from sd-card or phone memory. I have used custom cover-flow to animate the images. I have written a code to retrieve images from sd-card using cursor. But I get only few images, not all. And these images are displayed multiple times in my cover-flow. Each image is displaying twice.
If there are no images on sd-card then app crashes.
Here is my code, Please somebody help
public class CoverFlowActivityMain extends Activity {
private Cursor cursor;
private int columnIndex;
private File file;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CoverFlow coverFlow;
coverFlow = new CoverFlow(this);
file = new File("/sdcard/");
// I am using this file to check iamges on sd-card,
// but this does not search files in subdirectories.
File[] allFiles = file.listFiles();
for(int i=0; i<allFiles.length; i++) {
Log.v("File: "+i, ""+allFiles[i].getName().toString());
}
// Set up an array of the Thumbnail Image ID column we want
String[] projection = {MediaStore.Images.Thumbnails._ID};
// Create the cursor pointing to the SDCard
cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection, // Which columns to return
null, // Return all rows
null,
MediaStore.Images.Thumbnails.IMAGE_ID);
// Get the column index of the Thumbnails Image ID
columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);
coverFlow.setAdapter(new ImageAdapter(this));
ImageAdapter coverImageAdapter = new ImageAdapter(this);
coverFlow.setAdapter(coverImageAdapter);
coverFlow.setSpacing(-5);
coverFlow.setSelection(0, true);
coverFlow.setAnimationDuration(1500);
setContentView(coverFlow);
}
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return cursor.getCount();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
//-- Use this code if you want to load from sdcard --\\
ImageView picturesView;
if (convertView == null) {
picturesView = new ImageView(mContext);
// Move cursor to current position
cursor.moveToPosition(position);
// Get the current value for the requested column
int imageID = cursor.getInt(columnIndex);
// Set the content of the image based on the provided URI
picturesView.setImageURI(Uri.withAppendedPath(
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, "" + imageID));
picturesView.setLayoutParams(new CoverFlow.LayoutParams(380, 450));
picturesView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
//Make sure we set anti-aliasing otherwise we get jaggies
BitmapDrawable drawable = (BitmapDrawable) picturesView.getDrawable();
drawable.setAntiAlias(true);
}
else {
picturesView = (ImageView)convertView;
}
return picturesView;
}
}
}
I'm trying to load images from the specific folder in sd card.i saved images to folder in the sd card. now i want to load images from that folder.try to do this using online tutorials. but didn't work any thing.when i try to use below code i received blank screen.
What am I doing wrong? Many thanks for any help.
public class F6Activity extends softActivity
{
private Cursor cursor;
private int columnIndex;
Button next;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_f6);
Gallery g = (Gallery) findViewById(R.id.gallery);
//request only the image ID to be returned
String[] projection = {MediaStore.Images.Media._ID};
//Create the cursor pointing to the SDCard
cursor = managedQuery( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection,
MediaStore.Images.Media.DATA + " like ? ",
new String[] {"%ereports%"},
null);
//Get the column index of the image ID
columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
g.setAdapter(new ImageAdapter(this));
}
private class ImageAdapter extends BaseAdapter {
private Context context;
public ImageAdapter(Context localContext)
{
context = localContext;
}
public int getCount()
{
return cursor.getCount();
}
public Object getItem(int position)
{
return position;
}
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(context);
// Move cursor to current position
cursor.moveToPosition(position);
// Get the current value for the requested column
int imageID = cursor.getInt(columnIndex);
// obtain the image URI
Uri uri = Uri.withAppendedPath( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
Integer.toString(imageID) );
String url = uri.toString();
// Set the content of the image based on the image URI
int originalImageId = Integer.parseInt(url.substring(url.lastIndexOf("/") + 1,
url.length()));
Bitmap b = MediaStore.Images.Thumbnails.getThumbnail(getContentResolver(),
originalImageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
i.setImageBitmap(b);
i.setLayoutParams(new Gallery.LayoutParams(150, 100));
i.setScaleType(ImageView.ScaleType.FIT_XY);
int mGalleryItemBackground = 0;
i.setBackgroundResource(mGalleryItemBackground);
return i;
}
}
}
I am getting confused with code, Now I can't say the problem in your code, it will take time for me. I suggest to use the code available at below link. It is working fine. I will try to find the problem in your code afterwards. Now check the link below.
Display images from SD card
I have an app on the market that displays all photos from the user's SDcard in a gallery. Initially I had out of memory issues, but alleviated those by increasing the inSampleSize in the BitmapFactory options. However, I still have intermittent reports of images not displaying, in some cases none at all. There seems to be a larger proportion of Droid Eris users having problems. Here is the method that loads all photos and the accompanying ImageAdapter:
private void loadAllPhotos() {
setContentView(R.layout.add_pictures);
String[] projection = {MediaStore.Images.Thumbnails._ID};
cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection,
null,
null,
MediaStore.Images.Thumbnails.IMAGE_ID);
column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);
int size = cursor.getCount();
if (size == 0) {
Toast.makeText(thisContext, "Can't find pics on SDcard.", Toast.LENGTH_SHORT).show();
}
g = (Gallery) findViewById(R.id.gallery);
g.setAdapter(new ImageAdapter(this));
}
The ImageAdapter:
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
public ImageAdapter(Context c) {
mContext = c;
TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
mGalleryItemBackground = a.getResourceId(R.styleable.Gallery1_android_galleryItemBackground, 0);
a.recycle();
}
public int getCount() {
int cursorCount = mCursor.getCount();
return cursorCount;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(mContext);
System.gc();
if (convertView == null) {
try {
String [] proj={MediaStore.Images.Media.DATA};
mCursor = managedQuery( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,proj, null, null, null);
column_index = mCursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
mCursor.moveToPosition(position);
filename = mCursor.getString(column_index);
if (filename.endsWith(".jpg") || filename.endsWith(".png")) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 15;
Bitmap bm = BitmapFactory.decodeFile(filename, options);
i.setImageBitmap(bm);
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setLayoutParams(new Gallery.LayoutParams(150, 150));
i.setBackgroundResource(mGalleryItemBackground);
System.gc();
}
} catch (Exception e) {
}
}
return i;
}
}
If you have not done so already, integrate Flurry or DroidDrop or something to collect exceptions, as they may shed some light on your problem.
Also:
Please recycle your Views! You are creating a new ImageView on every getView() call, which is not helping your GC situation.
You are calling the same managedQuery() on every getView() call, which is horrible. Do that once, please.
You seem to be accessing mCursor in getCount() before it is initialized in getView().
column_index should always be 0 in the way you are calling managedQuery(), so you should not need to use getColumnIndexOrThrow(). Even if you want to use that, only do that once, when you make your single managedQuery() call.
Whether any of that will clear up your Droid Eris problems, though, I cannot say.
I tried the code above, it works well only if you have just .png and .jpg on the SD. Otherwise it can get some strange path out of the mCursor and in that case will show nothing.