How to find whether two bitmaparraylist is same [duplicate] - android

This question already has answers here:
equals vs Arrays.equals in Java
(9 answers)
Closed 5 years ago.
i'm doing a image puzzle game in android i successfully loaded image from gallery and splitted and shuffle the bitmap and made a puzzle gave now i want to check whether the puzzl;e played is finished on clicking a button first i tried like this,
public void checkresult(View view)
{
if(beforeshuffle.toArray().equals(aftershuffle.toArray()))
{
Toast.makeText(getApplicationContext(),"correct",Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getApplicationContext(),"wrong",Toast.LENGTH_SHORT).show();
}
}
but id didn't work so please do say me a logic to do this.
My complete code
public class SmallImageActivity extends Activity {
ImageView img;
GridView image_grid;
Bitmap bs,as;
ArrayList<Bitmap> beforeshuffle = new ArrayList<Bitmap>(9);
ArrayList<Bitmap> aftershuffle = new ArrayList<Bitmap>(9);
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.child_image);
//Getting the image chunks sent from the previous activity
// ArrayList<Bitmap> smallImage = getIntent().getParcelableArrayListExtra("small images");
//Getting the grid view and setting an adapter to it
img = (ImageView) findViewById(R.id.image);
image_grid = (GridView) findViewById(R.id.gridview);
Intent intent = getIntent();
String pathinphone = intent.getExtras().getString("path");
Log.d("path", pathinphone);
loadImageFromStorage(pathinphone);
}
private void splitImage(ImageView image, int smallimage_Numbers) {
final ArrayList<Bitmap> smallimages = new ArrayList<Bitmap>(9);
//For the number of rows and columns of the grid to be displayed
int rows, cols;
//For height and width of the small image smallimage_s
int smallimage_Height, smallimage_Width;
//To store all the small image smallimage_s in bitmap format in this list
//Getting the scaled bitmap of the source image
BitmapDrawable mydrawable = (BitmapDrawable) image.getDrawable();
Bitmap bitmap = mydrawable.getBitmap();
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), true);
rows = cols = (int) Math.sqrt(smallimage_Numbers);
smallimage_Height = bitmap.getHeight() / rows;
smallimage_Width = bitmap.getWidth() / cols;
//xCo and yCo are the pixel positions of the image smallimage_s
int yCo = 0;
for (int x = 0; x < rows; x++) {
int xCo = 0;
for (int y = 0; y < cols; y++) {
smallimages.add(Bitmap.createBitmap(scaledBitmap, xCo, yCo, smallimage_Width, smallimage_Height));
xCo += smallimage_Width;
}
yCo += smallimage_Height;
}
Array []in=new Array[9];
for(int i=0;i<smallimages.size();i++)
{
beforeshuffle.add(smallimages.get(i));
}
Collections.shuffle(smallimages);
image_grid.setAdapter(new SmallImageAdapter(this, smallimages));
image_grid.setNumColumns((int) Math.sqrt(smallimages.size()));
image_grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
int counter=0;
int firstclick;
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
counter ++;
if(counter % 2 == 0){
firstclick = position;
Bitmap data1 = smallimages.get(position);
}
else {
for(int i=0;i<smallimages.size();i++)
{
Bitmap swapImage = smallimages.get(position);
smallimages.set(position, smallimages.get(firstclick));
smallimages.set(firstclick, swapImage);
image_grid.invalidateViews();
aftershuffle.add(smallimages.get(i));
}
}
}
});
}
public void checkresult(View view)
{
if(beforeshuffle.toArray().equals(aftershuffle.toArray()))
{
Toast.makeText(getApplicationContext(),"correct",Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getApplicationContext(),"wrong",Toast.LENGTH_SHORT).show();
}
}
}

There is a method called sameAS in Bitmap class to compare,
You can try something below like this,
public void checkresult(View view)
{
if(beforeshuffle.size() > 0 && aftershuffle.size() > 0){
if(beforeshuffle.get(0).sameAs(aftershuffle.get(0)))
{
Toast.makeText(getApplicationContext(),"correct",Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getApplicationContext(),"wrong",Toast.LENGTH_SHORT).show();
}
}
}
I hope this may help you,All the best

If your Min supported Version is 14 or above, then Bitmap class have a method
bitmap.sameAs()
which you can use here to compare bitmaps.
see the description
here

I think that if you remove toArray() it will do the job (comparing 2 arrays with equals is the same as doing array1 == array2 but comparing 2 lists with equals will compare their contents)

Related

Save bitmaps from gif / video

I would like to save individual images (bitmap) of a GIF file and a video file. I want 5 pictures of each file. Depending on the length (seconds) of the files, the pictures should take pictures at regular intervals, so that there are 5 pictures. I hope someone can help me, thanks!
I found a good solution (for gifs) with Glide:
Glide.with(Activity.this)
.asGif()
.load(picturePath)
.into(new SimpleTarget<GifDrawable>() {
#Override
public void onResourceReady(#NonNull GifDrawable resource, #Nullable Transition<? super GifDrawable> transition) {
try {
Object GifState = resource.getConstantState();
Field frameLoader = GifState.getClass().getDeclaredField("frameLoader");
frameLoader.setAccessible(true);
Object gifFrameLoader = frameLoader.get(GifState);
Field gifDecoder = gifFrameLoader.getClass().getDeclaredField("gifDecoder");
gifDecoder.setAccessible(true);
StandardGifDecoder standardGifDecoder = (StandardGifDecoder) gifDecoder.get(gifFrameLoader);
for (int i = 0; i < standardGifDecoder.getFrameCount(); i++) {
standardGifDecoder.advance();
if (i == 4) {
bitmap1 = standardGifDecoder.getNextFrame();
} else if (i == standardGifDecoder.getFrameCount() / 3) {
bitmap2 = standardGifDecoder.getNextFrame();
} else if (i == standardGifDecoder.getFrameCount() / 2) {
bitmap3 = standardGifDecoder.getNextFrame();
} else if (i == standardGifDecoder.getFrameCount() - 4) {
bitmap4 = standardGifDecoder.getNextFrame();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
you can use Android-Ndk-Gif library to handle your needs, and here's a full example of how to get each bitmap from GIF, you can change gifDecoder.frameNum() to 4 so you can get the first 5 frames from your GIF
GifDecoder gifDecoder = new GifDecoder();
boolean isSucceeded = gifDecoder.load(Path); // PATH OF YOUR IMAGE
ArrayList<BitmapGIFUtil> arrayListBitmaps = new ArrayList<>();
for (int i = 0; i < gifDecoder.frameNum(); ++i) {
Bitmap bitmap = gifDecoder.frame(i);
int GIFDelay = gifDecoder.delay(i);
arrayListBitmaps.add(new BitmapGIFUtil(bitmap, GIFDelay));
}
BitmapGIFUtil.java
public class BitmapGIFUtil {
private Bitmap bitmap;
private int Delay;
public BitmapGIFUtil() {
}
public BitmapGIFUtil(Bitmap bitmap, int delay) {
this.bitmap = bitmap;
Delay = delay;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public int getDelay() {
return Delay;
}
public void setDelay(int delay) {
Delay = delay;
}
}
After filling your arrayListBitmaps you can save each bitmap into your gallery
And here is a solution (for videos) with MediaMetadataRetriever:
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(videoFile.getAbsolutePath());
MediaPlayer mp = MediaPlayer.create(getBaseContext(), vidUri);
mp.release();
String strLength = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long time=Long.valueOf(strLength)*1000;
bitmap1 = retriever.getFrameAtTime(time/10*2,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
bitmap2 = retriever.getFrameAtTime(time/10*4,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
bitmap3 = retriever.getFrameAtTime(time/10*6,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
bitmap4 = retriever.getFrameAtTime(time/10*8,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);

Loading image in onCreate doesn't fill adapter correctly

My application is able to take pictures and to save and to show them in a list. They also can be deleted and the list is correctly updated.
However, if I close the application and then launch it again, the list is no more correct. In detail:
These are the list elements in the adapter after I take two pictures:
List[0] 20150603_042556
List[1] 20150603_042601
These pictures are correctly saved. However, if I close and open again the application, this is what happens:
Loaded selfie:﹕ 20150603_042556
List[0] 20150603_042556
Loaded selfie: 20150603_042601
List[0] 20150603_042601
List[1] 20150603_042601
This is the add function:
public void add(SelfieRecord listItem) {
list.add(listItem);
for(int k=0;k<list.size();k++)
Log.i("List: ", String.valueOf(k) + " " + list.get(k).getPicName());
notifyDataSetChanged();
}
This is how I load the saved pictures:
for (int ii = 0; ii < dirFiles.length; ii++) {
File file = dirFiles[ii];
String path = file.getAbsolutePath();
selfie.setPic(path);
selfie.setPicName(path.substring(path.indexOf("_") + 1, path.lastIndexOf("_")));
Log.i(TAG+" Loaded selfie: ",path);
mAdapter.add(selfie);
}
Can't figure out what happens.
EDIT: More code follows.
In the main activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// setup notifications
setNotifications();
mListView = (ListView)findViewById(R.id.selfieList);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(MainActivity.this, ViewActivity.class);
SelfieRecord record = (SelfieRecord) mAdapter.getItem(position);
intent.putExtra(SELFIE_KEY, record.getPic());
startActivity(intent);
}
});
mAdapter = new SelfieAdapter(getApplicationContext());
mListView.setAdapter(mAdapter);
// load selfies
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && mAdapter.getCount()==0) {
// gets the files in the directory
File fileDirectory = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath());
if (!fileDirectory.exists()) {
fileDirectory.mkdirs();
}
// lists all the files into an array
File[] dirFiles = fileDirectory.listFiles();
if (dirFiles.length != 0) {
SelfieRecord selfie = new SelfieRecord();
// loops through the array of files, outputing the name to console
for (int ii = 0; ii < dirFiles.length; ii++) {
File file = dirFiles[ii];
String path = file.getAbsolutePath();
selfie.setPic(path);
selfie.setPicName(path.substring(path.indexOf("_") + 1, path.lastIndexOf("_")));
Log.i(TAG+" Loaded selfie: ",path);
mAdapter.add(selfie);
}
}
}
registerForContextMenu(mListView);
}
In the Adapter:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View newView = convertView;
ViewHolder holder;
SelfieRecord curr = list.get(position);
Log.i("List: ", String.valueOf(position)+" "+list.get(position).getPicName());
if (null == convertView) {
holder = new ViewHolder();
newView = inflater.inflate(R.layout.list_record, parent, false);
holder.pic = (ImageView) newView.findViewById(R.id.pic);
holder.name = (TextView) newView.findViewById(R.id.pic_name);
newView.setTag(holder);
} else {
holder = (ViewHolder) newView.getTag();
}
//setPic(holder.pic, curr.getPic());
holder.name.setText(curr.getPicName());
mImageView = holder.pic;
new BitmapLoader().execute(curr.getPic());
Log.i("Loader: ", String.valueOf(position) + " " + curr.getPicName());
return newView;
}
static class ViewHolder {
ImageView pic;
TextView name;
}
public void add(SelfieRecord listItem) {
list.add(listItem);
for(int k=0;k<list.size();k++)
Log.i("List: ", String.valueOf(k) + " " + list.get(k).getPicName());
notifyDataSetChanged();
}
public void remove(int position) {
list.remove(position);
notifyDataSetChanged();
}
Bitmap Loader:
public class BitmapLoader extends AsyncTask<String,Integer,Bitmap> {
#Override
protected Bitmap doInBackground(String... resId) {
// Get the dimensions of the View
int targetW = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 160, mContext.getResources().getDisplayMetrics()));
int targetH = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 120, mContext.getResources().getDisplayMetrics()));
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(resId[0], bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(resId[0], bmOptions);
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
I believe the problem is when I put the elements in the adapter after recovered them from storage:
Loaded selfie:﹕ 20150603_042556
List[0] 20150603_042556
Loaded selfie: 20150603_042601
List[0] 20150603_042601
List[1] 20150603_042601
The second call to the adapter's add method overwrite the first element. Why?
Solved by changing the for loop in on Create:
if (dirFiles.length != 0) {
// loops through the array of files, outputing the name to console
for (int ii = 0; ii < dirFiles.length; ii++) {
File file = dirFiles[ii];
String path = file.getAbsolutePath();
SelfieRecord selfie = new SelfieRecord();
selfie.setPic(path);
selfie.setPicName(path.substring(path.indexOf("_") + 1, path.lastIndexOf("_")));
Log.i(TAG+" Loaded selfie: ",path);
mAdapter.add(selfie);
}
}
Must pass a different SelfieRecord Object to the add method.

optimize list view with albumart [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
My ListView Containing all songs with album art is very slow and it lags no matter how much i re size the album art Please Help And How To i get the indexable List to work on the songs Title. Android Beginner and Sorry For Bad English.
Thanks For Any Help
public class SongAdapter extends CursorAdapter implements SectionIndexer{
private String mSections = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private final LayoutInflater mInflater;
public SongAdapter(Context context, Cursor c, int textViewResourceId,
List<String> objects) {
super(context, c,textViewResourceId);
mInflater=LayoutInflater.from(context);
}
private Bitmap bitmap = null;
private BitmapDrawable drawable = null;
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView title1 = (TextView) view.findViewById(R.id.titlelist);
TextView artist1 = (TextView) view.findViewById(R.id.artistlist);
ImageView album1 = (ImageView) view.findViewById(R.id.iconlist);
String title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
String artist = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
String album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));
long albumId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));
StringBuilder titleBuild = new StringBuilder();
titleBuild.append(title);
if(titleBuild.length() > 35)
{
titleBuild.setLength(32);
title = titleBuild.toString()+"...";
}
else
{
title = titleBuild.toString();
}
StringBuilder artistBuild = new StringBuilder();
artistBuild.append(artist);
if(artistBuild.length() > 35)
{
artistBuild.setLength(32);
artist = artistBuild.toString()+"...";
}
else
{
artist = artistBuild.toString();
}
final Uri ART_CONTENT_URI = Uri.parse("content://media/external/audio/albumart");
Uri albumArtUri = ContentUris.withAppendedId(ART_CONTENT_URI, albumId);
ContentResolver res = context.getContentResolver();
InputStream in;
try {
if(bitmap != null)
{
bitmap = null;
if(drawable != null)
{
drawable = null;
}
}
in = res.openInputStream(albumArtUri);
bitmap = BitmapFactory.decodeStream(in);
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, 50, 50, false);
// bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), albumArtUri);
drawable = new BitmapDrawable(context.getResources(), resizedBitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
drawable = (BitmapDrawable) context.getResources().getDrawable(R.drawable.default_artwork);
}
album1.setImageDrawable(drawable);
title1.setText(title);
artist1.setText(artist);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater inflater = (LayoutInflater)context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
return inflater.inflate(R.layout.rowlayout, parent, false);
}#Override
public int getPositionForSection(int section) {
// If there is no item for current section, previous section will be selected
for (int i = section; i >= 0; i--) {
for (int j = 0; j < getCount(); j++) {
if (i == 0) {
// For numeric section
for (int k = 0; k <= 9; k++) {
if (StringMatcher.match(String.valueOf(( getItem(j))), String.valueOf(k)))
return j;
}
} else {
if (StringMatcher.match(String.valueOf(getItem(j)), String.valueOf(mSections.charAt(i))))
return j;
}
}
}
return 0;
}
#Override
public int getSectionForPosition(int position) {
return 0;
}
#Override
public Object[] getSections() {
String[] sections = new String[mSections.length()];
for (int i = 0; i < mSections.length(); i++)
sections[i] = String.valueOf(mSections.charAt(i));
return sections;
}
}
According to me, the problem lies here:
in = res.openInputStream(albumArtUri);
bitmap = BitmapFactory.decodeStream(in);
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, 50, 50, false);
You should be performing the above operations in a background thread rather than on the main thread, otherwise they'll be blocking the main (UI) thread and make everything unresponsive.
Also, instead of loading the full resolution bitmap directly into memory, consider using BitmapFactory.Options to down-sample it first.
Read more here: http://developer.android.com/training/displaying-bitmaps/index.html
You could also consider using this awesome image loading library (supports content provider uris): https://github.com/nostra13/Android-Universal-Image-Loader

Get the LinearLayout inside a ListView from an Async Task onRetainNonConfigurationInstance()

I hope the title is not mis-leading. I am trying to implement onRetainNonConfigurationInstance() of an AsyncTask of loading images and am getting this error "Java.lang.RuntimeException:Unable to retain Activity". Here is my code for onRetainNonConfigurationInstance():
public Object onRetainNonConfigurationInstance(){
//final ListView listview = list;
final int count = list.getChildCount();
final LoadedImage[] mylist = new LoadedImage[count];
for(int i = 0; i < count; i++){
final ImageView v = (ImageView)list.getChildAt(i); // getting error here
mylist[i] = new LoadedImage(((BitmapDrawable) v.getDrawable()).getBitmap());
}
return mylist;
}
Here is the Logcat:
05-18 08:43:15.385: E/AndroidRuntime(28130): java.lang.RuntimeException: Unable to retain activity {com.MyApps.ImageGen/com.MyApps.ImageGen.Wallpapers}: java.lang.ClassCastException: android.widget.LinearLayout
05-18 08:43:15.385: E/AndroidRuntime(28130): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:2989)
05-18 08:43:15.385: E/AndroidRuntime(28130): at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3100)
05-18 08:43:15.385: E/AndroidRuntime(28130): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3216)
05-18 08:43:15.385: E/AndroidRuntime(28130): at android.app.ActivityThread.access$1600(ActivityThread.java:132)
Here is my layout with the ListView:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="#00000000"
android:listSelector="#android:color/transparent" >
</ListView>
</LinearLayout>
Here is how I setup the ListView:
private void setupViews() {
list = (ListView)findViewById(android.R.id.list);
list.setDivider(null);
list.setDividerHeight(0);
imageAdapter = new ImageAdapter(getApplicationContext());
list.setAdapter(imageAdapter);
list.setOnItemClickListener(this);
}
my async task and Item Adapter:
class LoadImagesFromSDCard extends AsyncTask<Object, LoadedImage, Object> {
#Override
protected Object doInBackground(Object... params) {
Bitmap bitmap = null;
Bitmap newbitmap = null;
Uri uri = null;
String [] img = {MediaStore.Images.Media._ID};
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state)){
cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, img, null, null, null);
} else {
// cursor = getContentResolver().query(MediaStore.Images.Media.INTERNAL_CONTENT_URI, img, null, null, null);
inInternalStorage = true;
}
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
int size = cursor.getCount();
if(size == 0){
//Toast.makeText(getApplicationContext(), "There are no Images on the sdcard", Toast.LENGTH_SHORT).show();
//System.out.println("size equals zero");
Wallpaper.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "There are no Images on the sdcard", Toast.LENGTH_SHORT).show();
}
});
return params;
}else {
}
for(int i = 0; i < size; i++){
cursor.moveToPosition(i);
int ImageId = cursor.getInt(column_index);
if(inInternalStorage == true){
uri = Uri.withAppendedPath(MediaStore.Images.Media.INTERNAL_CONTENT_URI, "" + ImageId);
}else {
uri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + ImageId);
}
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
Log.i(TAG, "imageheight = " + imageHeight);
Log.i(TAG, "imagewidth = " + imageWidth);
Log.i(TAG, "imageType = " + imageType);
//options.inSampleSize=4;
options.inSampleSize = calculateInSampleSize(options, imageWidth, imageHeight);
options.inJustDecodeBounds = false;
//bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
if(bitmap != null){
newbitmap = Bitmap.createScaledBitmap(bitmap, 180, 180, true);
bitmap.recycle();
}
if(newbitmap != null){
publishProgress(new LoadedImage(newbitmap));
}
}catch(IOException e){
}
//cursor.close();
}
cursor.close();
return null;
}
#Override
public void onProgressUpdate(LoadedImage... value){
addImage(value);
}
#Override
protected void onPostExecute(Object result) {
setProgressBarIndeterminateVisibility(false);
}
}
private static class LoadedImage {
Bitmap mBitmap;
LoadedImage(Bitmap bitmap) {
mBitmap = bitmap;
}
public Bitmap getBitmap() {
return mBitmap;
}
}
/*Image Adapter to populate grid view of images*/
public class ImageAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<LoadedImage> photos = new ArrayList<LoadedImage>();
public ImageAdapter(Context context){
this.mContext = context;
}
public void addPhotos(LoadedImage photo){
photos.add(photo);
}
#Override
public int getCount() {
return photos.size();
}
#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) {
ImageView image;
ViewHolder holder;
if(convertView == null){
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//convertView = inflater.inflate(R.layout.image_list,null);
convertView = inflater.inflate(R.layout.media_view, null);
holder = new ViewHolder();
holder.image = (ImageView)convertView.findViewById(R.id.media_image_id);
//holder.item_name = (TextView)convertView.findViewById(R.id.media_image_id);
convertView.setTag(holder);
} else{
holder = (ViewHolder)convertView.getTag();
}
//holder.image.setLayoutParams(new GridView.LayoutParams(100, 100));
//String item_name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME));
holder.image.setImageBitmap(photos.get(position).getBitmap());
//holder.item_name.setText(item_name);
return convertView;
}
}
static class ViewHolder {
ImageView image;
TextView item_name;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor cursor = null;
int image_column_index = 0;
String[] proj = {MediaStore.Images.Media.DATA};
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state)){
cursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,proj,null, null,null);
}else{
cursor = managedQuery(MediaStore.Images.Media.INTERNAL_CONTENT_URI,proj,null, null,null);
}
cursor.moveToPosition(position);
image_column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
String info = cursor.getString(image_column_index);
Intent imageviewer = new Intent(getApplicationContext(), ViewImage.class);
imageviewer.putExtra("pic_name", info);
startActivity(imageviewer);
cursor.close();
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 2;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float)height / (float)reqHeight);
} else {
inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
/*final int REQUIRED_SIZE = 180;
int scale = 1;
if(reqWidth > REQUIRED_SIZE || reqHeight > REQUIRED_SIZE){
scale = (int)Math.pow(2, (int)Math.round(Math.log(REQUIRED_SIZE/(double)Math.max(reqHeight, reqWidth)) / Math.log(0.5)));
}*/
return inSampleSize;
}
other Methods within Async Task:
private void loadImages() {
final Object data = getLastNonConfigurationInstance();
if(data == null){
new LoadImagesFromSDCard().execute();
}else {
final LoadedImage[] photos = (LoadedImage[])data;
if(photos.length == 0){
new LoadImagesFromSDCard().execute();
}
for(LoadedImage photo:photos){
addImage(photo);
}
}
}
private void addImage(LoadedImage... value) {
for(LoadedImage photo: value){
imageAdapter.addPhotos(photo);
imageAdapter.notifyDataSetChanged();
}
}
I am assuming I should first get the root element before I get the ListView from the logcat error, but I don't know how, I can't seem to find a suitable method from the documentation.
P.S: I am using an Activity and not a ListActivity.
The exception tells you that you try to do an invalid cast. My guess is that your row layout isn't a simple ImageView like you assume with the cast in the onRetainNonConfigurationInstance(), instead your row layout probably has a parent Linearlayout that wraps the ImageView(and other views?!). When you call the method getChildAt you get that parent Linearlayout which you try to cast to a ImageView. Instead you should do this:
//...
for(int i = 0; i < count; i++){
LinearLayout parent = (LinearLayout)list.getChildAt(i);
final ImageView v = (ImageView) parent.findViewById(R.id.the_id_of_the_imageview_from_theRow_layout);
mylist[i] = new LoadedImage(((BitmapDrawable) v.getDrawable()).getBitmap());
}
Note: The getChildAt method returns the rows views for the visible rows only so if you try to access the View for a row that isn't currently visible you'll most likely end up with a NullPointerException(you should get the drawables directly from the adapter and not from parsing all the rows Views).
Edit based on the comments:
If I understood your problem, the behavior you see it's normal. You didn't say how you ended up getting the bitmaps in the onRetainNonConfigurationInstance but my guess is that you just save the images from the ListView rows that are currently visible to the user. When it's time to restore the adapter with the images from getLastNonConfigurationInstance() you end up getting only those images which were previously visible. This will get worse if you rotate the phone again as, most likely, there are fewer images visible in landscape orientation then in the portrait orientation.
I don't know if this will work but you could try to modify the LoadedImage class to store the id of the image from MediaStore.Images.Media. When it's time to save the configuration, stop the LoadImagesFromSDCard task and nullify all the images(remove the Bitmap to which LoadedImage points)from the LoadedImages ArrayList(in the adapter) except the ones that are currently visible to the user. Send the photos ArrayList from your adapter through
onRetainNonConfigurationInstance.
When it's time to restore the adapter set the photos ArrayList of your new adapter to the one you got back and put the ListView to the position of the visible images(so the user sees the sent images). In the getView method of your adapter you'll put a default image(like loading...) when you have a null value for the Bitmap in the associated LoadedImage class. Start a new LoadImagesFromSDCard task to get the images and parse them again. When you get the id from MediaStore.Images.Media you'll check if a LoadedImage with this id exists in the adapter and if it has a Bitmap set to it. If it doesn't exist(or it doesn't have a Bitmap associated) then load the image and put it in the adapter, if not the image already exists and move to the next one.
I don't know if the solution above will work or if it's efficient. I would recommend you to modify the code and load images on demand instead of loading all up in a big task.

How to set random images to ImageView's?

i am using 9 image view's i want set images to imageview randomly , when I click on refresh button, but I tried like this it's working for random allocation of images but it's repeating the same image in two (or) three imageview's at a time. where is the problem in my code..
final int[] imageViews = {
R.id.imgview11, R.id.imgview12, R.id.imgview13,
R.id.imgview21, R.id.imgview22, R.id.imgview23,
R.id.imgview31, R.id.imgview32, R.id.imgview33 };
final int[] images = {
R.drawable.i1, R.drawable.i2, R.drawable.i3,
R.drawable.i4, R.drawable.i5, R.drawable.i6,
R.drawable.i7, R.drawable.i8, R.drawable.empty };
final ImageButton shuffle = (ImageButton) findViewById(R.id.new_puzzle);
shuffle.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Random generator = new Random();
//int n = 9;
//n = generator.nextInt(n);
//Random random = new Random(System.currentTimeMillis());
for(int v : imageViews) {
ImageView iv = (ImageView)findViewById(v);
iv.setImageResource(images[generator.nextInt(images.length - 1)]);
}
}
});
i don't want repeat, one image for one imageview only..
using the post of blessenm ,i wrote a similar code that you need. check if this helps you.
shuffle.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Random rng = new Random();
List<Integer> generated = new ArrayList<Integer>();
for (int i = 0; i < 9; i++)
{
while(true)
{
Integer next = rng.nextInt(9) ;
if (!generated.contains(next))
{
generated.add(next);
ImageView iv = (ImageView)findViewById(imageViews[i]);
iv.setImageResource(images[next]);
break;
}
}
}
}
});
Maybe not the perfect answer, but I would just shuffle the images list and the set the resulting image to the imageview.
This will avoid having to generate random numbers that will of course create duplicate (If you throw a dice 6 times, you won't have the numbers 1,2,3,4,5,6 in random order, you will get multiple time the same number.)
Please check everything including the 'i' as I am not in front of my computer.
List<int> list = Arrays.asList(images);
// Here we just simply used the shuffle method of Collections class
// to shuffle out defined array.
Collections.shuffle(list);
int i=0;
// Run the code again and again, then you'll see how simple we do shuffling
for (int picture: list) {
ImageView iv = (ImageView)findViewById(imageViews[i]);
iv.setImageResource(picture);
i++;
}
as an alternative, you may also want to shuffle your list with this code:
public class ShuffleArray {
public static void shuffleArray(int[] a) {
int n = a.length;
Random random = new Random();
random.nextInt();
for (int i = 0; i < n; i++) {
int change = i + random.nextInt(n - i);
swap(a, i, change);
}
}
private static void swap(int[] a, int i, int change) {
int helper = a[i];
a[i] = a[change];
a[change] = helper;
}
public static void main(String[] args) {
int[] a = new int[] { 1, 2, 3, 4, 5, 6, 7 };
shuffleArray(a);
for (int i : a) {
System.out.println(i);
}
}
}
You might want to refer to this post. It shows a method to generate random numbers without duplicates
Creating random numbers with no duplicates

Categories

Resources