Hello kindhearted experts.
I am a newbie to Android Programming world.
I've asked a question about how to list images of phone on a GridView with three columns.
I finally got to the part where I am able to show my images on a GridView, but I am thinking my decoding method isn't efficient enough that it says "The application may be doing too much work on its main thread." and it is obvious the application is really slow.
here is my part of my code:
BitmapFactory.Options bo = new BitmapFactory.Options();
bo.inSampleSize = 8;
Bitmap bmp = BitmapFactory.decodeFile(thumbsDataList.get(position), bo);
Bitmap resized = Bitmap.createScaledBitmap(bmp, 95, 95, true);
imageView.setImageBitmap(resized);
Also, if this part helps you to figure out the issue:
private void getThumbInfo(ArrayList<String> thumbsIDs, ArrayList<String> thumbsDatas){
String[] proj = {MediaStore.Images.Media._ID,
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.SIZE};
Cursor imageCursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
proj, null, null, null);
if (imageCursor != null && imageCursor.moveToFirst()){
String thumbsID;
String thumbsImageID;
String thumbsData;
int thumbsIDCol = imageCursor.getColumnIndex(MediaStore.Images.Media._ID);
int thumbsDataCol = imageCursor.getColumnIndex(MediaStore.Images.Media.DATA);
int thumbsImageIDCol = imageCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME);
int num = 0;
do {
thumbsID = imageCursor.getString(thumbsIDCol);
thumbsData = imageCursor.getString(thumbsDataCol);
thumbsImageID = imageCursor.getString(thumbsImageIDCol);
num++;
if (thumbsImageID != null){
thumbsIDs.add(thumbsID);
thumbsDatas.add(thumbsData);
}
}while (imageCursor.moveToNext());
}
imageCursor.close();
return;
}
If anyone could give me an idea to fix this lag, I will appreciate it very much.
Thank you very much in advance.
Related
I want to make a button to be able to display selected document names from the downloads folder that can be found in the "My Files" app in android, but i cant seem to find the right path to get to the documents. Anyone knows the path? I have tried ways like
Environment.getExternalStorageState()
but im not getting the downloads folder, instead it goes to google drive to select.
this is how im using the uri.
else if (btnNo == 5 ) {
// File downloads = new File(String.valueOf(Environment.getExternalStorageState()));
//create new file directory object
//File downloads = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath());
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
File f = new File(picturePath);
tvOther = (TextView) findViewById(R.id.textViewOtherImage);
tvOther2 = (TextView) findViewById(R.id.textViewOtherImage2);
tvOther3 = (TextView) findViewById(R.id.textViewOtherImage3);
tvOther4 = (TextView) findViewById(R.id.textViewOtherImage4);
tvOther5 = (TextView) findViewById(R.id.textViewOtherImage5);
tvOther6 = (TextView) findViewById(R.id.textViewOtherImage6);
tvOther7 = (TextView) findViewById(R.id.textViewOtherImage7);
tvOther8 = (TextView) findViewById(R.id.textViewOtherImage8);
tvOther9 = (TextView) findViewById(R.id.textViewOtherImage9);
tvOther10 = (TextView) findViewById(R.id.textViewOtherImage10);
if (tvOther.getText() == "") {
tvOther.setText(addClickablePart("[" + f.getName() + "]"), TextView.BufferType.EDITABLE);
iv_3 = BMP.getBytes(BitmapFactory.decodeFile(picturePath));
to_attach_img_name_3 = f.getName();
imgArr[2] = to_attach_img_name_3;
also a problem with editing the textviews im using, i cant seem to delete the text using the spannable class. any help with that will be good
my codes for the spannable class
private SpannableStringBuilder addClickablePart2(String str) {
SpannableStringBuilder ssb = new SpannableStringBuilder(str);
int idx1 = str.indexOf("[");
int idx2 = 0;
while (idx1 != -1) {
idx2 = str.indexOf("]", idx1) + 1;
final String clickString = str.substring(idx1, idx2);
ssb.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
tvOther2.setText("");
}
}, idx1, idx2, 0);
idx1 = str.indexOf("[", idx2);
}
return ssb;
}
This answer might have answered already what you need: https://stackoverflow.com/a/7908446/8050896
Did you try to write the Environment.DIRECTORY_DOWNLOADS constant?
Make sure you have the proper permissions in the manifest set as well.
Well... got my answer while trying to find how to upload PDF to server... Here's where i got the answer to go to downloads folder, im still trying to find out how to display the name
i need to get all the MMS Data detalis like mms_image, address,date and type.
i am using following logic. In this i am using two cursors, one for images and other for remaining fields. but the size of two cursors are different. so, i am unable to match both image and other fields.
//for date,address,type
Cursor curPdu = getContentResolver ().query(Uri.parse("content://mms"), null, null, null, null);
while(curPdu.moveToNext())
{
String id = curPdu.getString (curPdu.getColumnIndex ("_id"));
String date = curPdu.getString (curPdu.getColumnIndex ("date"));
mms_add.add(getAddressNumber(Integer.parseInt(id)));
int type = Integer.parseInt(curPdu.getString(curPdu.getColumnIndex("m_type")));
mms_type.add((type==128)?"2":"1");
mms_date.add(getDate(Long.parseLong(date)));
}
//for image
Cursor curPart = getContentResolver (). query (Uri.parse ("content://mms/part"), null, null, null, null);
while(curPart.moveToNext())
{
coloumns = curPart.getColumnNames();
if(values == null)
values = new String[coloumns.length];
for(int i=0; i< curPart.getColumnCount(); i++)
{
values[i] = curPart.getString(i);
}
if(values[3].equals("image/jpeg"))
{
mms_image.add(GetMmsAttachment(values[0],values[12],values[4]));
}else{
mms_image.add("null");
}
}
so, please guide me how to get all the details using one cusor if possible.
You can try the solution and url provided here.
And may i know why you need 2 cursor ? I assume there is some mms without image attached so that's the reason you get a different count.
I have created a database of objects. Each of these objects contains two strings and two bitmaps. When I do a getAllContacts() call to my database, the loading takes quite a while. For me its not a problem, but for the end-users, this would be annoying. When I load an object I set this options to my bitmaps saying:
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 8;
Which will shrink the Bitmaps to 1/8 of the original height and width. But still, it takes around 10-15 seconds to load 50 records and fill this into a ListView. Is there any way I can check if the object I try to load is in the memory, also called paging? Or maybe I can load the Bitmaps, when the users presses one of the items in the ListView?
Thanks in advance!
You set the sample size but it's still reading (I assume) large images. Why not set your bitmaps so that they are already small and then you can read small images without the scale factor applied?
I had a listView in my own code doing similar things and it was very slow until I wrote code to shrink each new image as it was created and then always just dealt with small images. And the code lived happily ever after.
The solution:
So, finally I found a solution to my problem. Instead of getting all of the Bitmaps when I do a getAllContact() call, the bitmap's is loaded when the user presses a row in the ListView This is whats done in the setOnClickListener method in CustomAdapter for my ListView
String PCN = cases.get(position).getCaseNumber();
int tempPCN = Integer.valueOf(PCN);
tempBitMapArray = dbHandler.getFinger(tempPCN);
Bitmap left = tempBitMapArray[0];
Bitmap right = tempBitMapArray[1];
ByteArrayOutputStream bs1 = new ByteArrayOutputStream();
left.compress(Bitmap.CompressFormat.PNG, 100, bs1);
ByteArrayOutputStream bs2 = new ByteArrayOutputStream();
right.compress(Bitmap.CompressFormat.PNG, 100, bs2);
And the getFinger(...) method:
public Bitmap[] getFinger(int pcn) {
Bitmap[] fingers = new Bitmap[2];
String SQLQUERY = "SELECT " + RIGHTFINGER + ", " + LEFTFINGER +" FROM " + TABLE_CASES + " WHERE " + KEY_ID + "=" + pcn + ";";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(SQLQUERY, null);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 2;
if (cursor.moveToFirst()) {
do {
byte[] blob1 = cursor.getBlob(cursor.getColumnIndexOrThrow("leftFinger"));
Bitmap bmp1 = BitmapFactory.decodeByteArray(blob1, 0, blob1.length, options);
byte[] blob2 = cursor.getBlob(cursor.getColumnIndexOrThrow("rightFinger"));
Bitmap bmp2 = BitmapFactory.decodeByteArray(blob2, 0, blob2.length, options);
fingers[0] = bmp1;
fingers[1] = bmp2;
return fingers;
} while(cursor.moveToNext());
}
return null;
}
I hope this example will give other people a pinpoint in the right direction.
Hi all,
I have searched a lot for my problem, I found a lot of posts with similar problems, but no one gave me a correct solution.
What I want is a gridview displaying a sdcard folder's images. I also have to offer the possibility to take a picture, and when going back to the gridview, update it with the new picture.
To take the picture, I use this code :
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getImageFileUri());
startActivityForResult(intent, TAKE_PICTURE_ACTIVITY);
Where getImageFileUri() is a function giving me a picture name with a timestamp, using Environment.getExternalStorageDirectory() to get the sdcard path, and checking if the folder exists (and create it if it doesn't).
For the moment, I use a cursor to get my images :
private void displayGallery() {
// Query params :
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Images.Media._ID};
String selection = MediaStore.Images.Media.DATA + " like ? ";
String[] selectionArgs = {"%Otiama%"};
// Submit the query :
mCursor = managedQuery(uri, projection, selection, selectionArgs, null);
if (mCursor != null) {
mGridView.setOnItemClickListener(this);
mGridView.setAdapter(new ImageAdapter(this, mCursor));
}
else showToast("Gallery is empty : " + uri.toString());
}
And here is my adapter's getView :
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(mContext);
// Move cursor to current position
mCursor.moveToPosition(position);
// Get the current value for the requested column
int columnIndex = mCursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
int imageID = mCursor.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(mContext.getContentResolver(), originalImageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
imageView.setImageBitmap(b);
return imageView;
}
This code works, but is very slow and doesn't update (new pictures's thumbnails aren't created), even if I call again my displayGallery() function in the onActivityResult(). Well, it doesn't update even if I reload the app >< . I have to run it again from eclipse.
In fact, what I would like is the same behavior than ES File Explorer (when you open a folder, the pictures have all a preview image, and they are loaded asynchronously), which, I think, doesn't use those ** thumbnails.
So I tried to load the pictures as bitmaps using the bitmap factory, but even with a few pictures (1-2), I instantly get a "java.lang.OutOfMemoryError: bitmap size exceeds VM budget"... I guess I have to resize them, but if I do so, won't I have the same error when I will load 20-30 pictures ?? Or the problem is that each picture exceeds the budget, and so if I resize them I will avoid this error for all of them ?
Sorry for the big post, if someone can help...
Well, I answer myself :
I created my own thumbnails this way :
public static Bitmap resizedBitmap(Bitmap bitmap, int newWidth) {
// Get the bitmap size :
int width = bitmap.getWidth();
int height = bitmap.getHeight();
double ratio = (double)width / (double)height;
// Compute the thumbnail size :
int thumbnailHeight = newWidth;
int thumbnailWidth = (int) ( (double)thumbnailHeight * ratio);
// Create a scaled bitmap :
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, thumbnailWidth, thumbnailHeight, false);
return scaledBitmap;
}
I don't use cursors anymore, to load the thumbnails I proceed like this (in the ImageAdapter) :
public void loadThumbnails() {
// Init the ArrayList :
_thumbnails = new ArrayList<ImageView>();
_imagesNames = new ArrayList<String>();
// Run through the thumbnails dir :
File imagesThumbnailsDir = new File(_imagesThumbnailsDirUri.getPath());
File[] imagesThumbnails = imagesThumbnailsDir.listFiles();
Arrays.sort(imagesThumbnails);
// For each thumbnail :
for(File imageThumbnail : imagesThumbnails)
{
// Check if the image exists :
File image = new File(_imagesDirUri.getPath() + File.separator + imageThumbnail.getName());
if(image.exists()) {
ImageView imageView = new ImageView(_context);
imageView.setImageDrawable(Drawable.createFromPath(imageThumbnail.getAbsolutePath()));
_thumbnails.add(imageView);
_imagesNames.add(imageThumbnail.getName());
}
// If not, delete the thumbnail :
else {
ImageUtils.deleteFile(Uri.fromFile(imageThumbnail));
}
}
}
And so my ImageAdapter's getView function sounds like this :
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(_context);
imageView.setLayoutParams(new GridView.LayoutParams(80, 80));
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageView.setPadding(5, 5, 5, 5);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageDrawable(_thumbnails.get(position).getDrawable());
return imageView;
}
Hope it helps..
For a content: URI, I used ContentProvider/Contentresolver to retrieve information about the modified date, size and data. I would like to do the same for file: URI but when I try the following code:
CursorLoader loader = new CursorLoader(this, uri, proj, null, null, null);
Cursor cursor = loader.loadInBackground();
Cursor is returned as null. How to get the file size, data and date added/modified?
I might be misunderstanding your question, but you use java's normal file IO to find that information.
Here is an example of me finding out that information for a picture called cat.jpg:
File f = new File("/data/cat.jpg");
//Size of file in bytes
Long size = f.length();
//Time of when the file was last modified in microseconds
Long lastModified = f.lastModified();
//The bytes of the file. This gets populated below
byte[] fileData = new byte[(int)f.length()];
try {
FileInputStream fis = new FileInputStream(f);
int offset = 0;
int bytesActuallyRead;
while( (bytesActuallyRead = fis.read(fileData, offset, 1024)) > 0) {
offset += bytesActuallyRead;
}
} catch(Exception e) {
}