Using a String to change a Bitmap - java

I have the following problem:
String explosion_type = this.prefs.getString("explosion_type", "ring_explosion");
BitmapFactory.Options optionsExplosion = new BitmapFactory.Options();
optionsExplosion.inPurgeable = true;
this._explosionSprite = BitmapFactory.decodeResource(_context.getResources(),
com.forwardapps.liveitems.R.drawable.explosion, optionsExplosion);
I'm trying to use a String in place of the resource name, that way I can hotswap resources in the preference menu. This method causes the app to crash.
What is the proper way of implementing a situation like this? (Without making it too complicated or using if statements)

Use method getIdentifier on Resources object to fetch id of a drawable:
String explosion_type = this.prefs.getString("explosion_type", "ring_explosion");
Log.i("imagename", explosion_type);
BitmapFactory.Options optionsExplosion = new BitmapFactory.Options();
optionsExplosion.inPurgeable = true;
int imageResource = getResources().getIdentifier(explosion_type, "drawable", getPackageName());
this._explosionSprite = BitmapFactory.decodeResource(_context.getResources(), imageResource, optionsExplosion);

Related

How to list out only either static or animated images in Android?

I want to detect and display most recent images and it should be either animated or static images on user choice.
Also cannot depend on extentions.Because
There would be absence of extention
webp images could be animated or static with same extention (.webp)
It could be wrong extentions
Is there way to identify whether images are animated (webp, gif, apng) or static (jpg, png, webp, etc)?
private static final String[] COLUMNS_OF_INTEREST = new String[]
{
MediaStore.Video.Media._ID,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.SIZE,
MediaStore.Video.Media.WIDTH,
MediaStore.Video.Media.HEIGHT,
MediaStore.Video.Media.DATE_ADDED
};
public void printGifUri(Context context)
{
ContentResolver cr = context.getContentResolver();
String selection = MediaStore.Images.Media.MIME_TYPE + "=?";
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("webp");
String[] selectionArgsPdf = new String[]{ mimeType };
Cursor gifCursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, COLUMNS_OF_INTEREST, selection,selectionArgsPdf,
MediaStore.Images.Media.DATE_ADDED + " DESC");
gifCursor.moveToFirst();
int columnIndexUri = gifCursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
for (int i = 0; i < gifCursor.getCount(); i++)
Log.d("gif file uri -> ", gifCursor.getString(columnIndexUri));
}
I want to also avoid the third party modules as they would increase the size of the app. You can suggest if there is any module available for this with low size.
I have Tried checking the existance of flags like ANIM, VP8, in image file and it works well but this explicit method is time consuming.
The major issue in this is webp as same extention would be static or animated. This makes difficult me to identify the animated and static type.
I think I maybe found a solution... try using
ImageDecoder
the documentation says
If the encoded image is an animated GIF or WEBP, decodeDrawable will
return an AnimatedImageDrawable.
So maybe checking that the result of ImageDecoder.decodeDrawable(source); is an instance of AnimatedImageDrawable should help you figure out if a file is animated or not
such as:
ImageDecoder.Source source = ImageDecoder.createSource(cr,uri);
Drawable drawable = ImageDecoder.decodeDrawable(source);
if (drawable instanceof AnimatedImageDrawable) {
//THE FILE IS ANIMATED
}else{
//THE FILE IS STATIC
}
or such as
private boolean isAnimated(ContentResolver cr,Uri uri){
ImageDecoder.Source source = ImageDecoder.createSource(cr,uri);
Drawable drawable = ImageDecoder.decodeDrawable(cr,source);
return drawable instanceof AnimatedImageDrawable;
}
EDIT:
for API 28 and before, we should use Movie class
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
ImageDecoder.Source source = ImageDecoder.createSource(file);
Drawable drawable = ImageDecoder.decodeDrawable(source);
return drawable instanceof AnimatedImageDrawable;
} else {
Movie movie = Movie.decodeStream(input);
return movie != null;
}
I hope that helps with your problem

Resources.NotFoundException is thrown while loading many images in a loop

I am displaying almost 4,000 images in a loop with image name.
Here is the code which i am using to get my images from drawable folder
for(int i=0; i<count(images_array); i++) {
mDrawableName = images_array(i);
int resID = res.getIdentifier(mDrawableName, "drawable", activity.getPackageName());
Drawable drawable = res.getDrawable(resID);
image.setImageDrawable(drawable);
}
the issues are:
When the image name is not found in resource folder my app throws
me an exception and crashes.
Is there any better way to load 4000 images from drawable in
listview? Is there any way i can check if image is not in drawable
then show placeholder image ?
When the image name is not found in resource folder my app through me
an exception and crash.
This is not an issue since it is expected behavior that getIdentifier returns 0 for a non-existent resource and then getDrawable throws the Resources.NotFoundException for id = 0 (which is not a valid ID).
Is there any way i can check if image is mot in drawable then show
placeholder image?
You either catch that exception or check if getIdentifier returned 0.
I don't know the rest of your code, so based on what you posted, you could do this:
for (int i=0; i<count(images_array); i++) {
mDrawableName = images_array(i);
int resID = res.getIdentifier(mDrawableName, "drawable", activity.getPackageName());
Drawable drawable;
if (resID == 0) {
drawable = res.getDrawable(R.drawable.placeholderimage, null);
} else {
drawable = res.getDrawable(resID);
}
image.setImageDrawable(drawable);
}
Note:
getDrawable(int id) is now deprecated starting API 22.
In the sample code, I used getDrawable(int id, Resources.Theme theme) instead.
You might want to check out the other alternatives.
Is there any better way to load 4000 images from drawable in listview?
Try using Android's RecyclerView and/or 3rd-party libs such as Glide.
Boolean fileFound = true;
try{
int resID = res.getIdentifier(mDrawableName , "drawable", activity.getPackageName());
Drawable drawable = res.getDrawable(resID );
image.setImageDrawable(drawable );
}catch (Resources.NotFoundException e){
fileFound = false;
}
if(!fileFound){
int resID = res.getIdentifier("img_not_found" , "drawable", activity.getPackageName());
Drawable drawable = res.getDrawable(resID );
image.setImageDrawable(drawable );
}

How to convert Int to constant for res/raw?

InputStream inputStream = getResources().openRawResource(R.raw.ac);
here, ac is constant file name from res/raw.
int books = cursor.getColumnIndexOrThrow(DictionaryDatabase.BOOK_DETAILS)
is an int contains name: ac also.
Is it possible to use
InputStream inputStream = getResources().openRawResource(Int books);
???
If yes how??
If I understand correctly, you want to get the value of the R.raw.xxxx field having the name xxxx in a variable. This can be achieved with a code like this:
String resName = "mybook";
int resID = context.getResources().getIdentifier(resName, "raw", context.getPackageName());
InputStream inputStream = getResources().openRawResource(resId);
Here, context is an instance of Context in your app, in an activity, this would be this.

Dynamic naming of Resources in Android without getIdentifier

I'm using OpenGL ES to make a game in Android. I got some code from a tutorial and I'm trying to change it to suit my app but I'm having a problem. I want to dynamically get an image resource using a string passed into a function as the resource name. I know usually you use getIdentifier() in this case, but that returns an int and I need an input stream. Is there any way of getting an input stream from a resource dynamically?
Alternatively, is there a better way of doing this?
Code below:
InputStream is = mContext.getResources().openRawResource(R.drawable.<imagename>);
Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(is);
}
finally {
try {
is.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
yes u can Suppose u have images stored in drawable with naming img1,img2,img3,img4,img5,img6,img7 than
first make an array like
String[] imgarray={"img1","img2","img3","img4","img5","img6","img7"};
public static String PACKAGE_NAME ;
PACKAGE_NAME=getApplicationContext().getPackageName();
Random r = new Random();
int n=r.nextInt(imgarray.length());
int resID = getResources().getIdentifier( PACKAGE_NAME+":drawable/" +imgarray[n] , null, null);
imageview.setImageResource(resID);
if want bitmap image than just add below line
Bitmap bm = BitmapFactory.decodeResource(getResources(),resID);
if u want other way with less coding than see accepted answer at Other Example

Android: How to retrieve file name and extension of a resource by resource ID

I have the following:
getResources().getResourceEntryName(resourceId);
The problem is, that it retrieves only the file name without the extension.
For example, if I have the following res/drawable/pic.jpg, the
getResources().getResourceEntryName(resourceId);
is returning the value "pic". The extension .jpg is missing.
To get "res/drawable/pic.jpg" you could use this:
TypedValue value = new TypedValue();
getResources().getValue(resourceId, value, true);
// check value.string if not null - it is not null for drawables...
Log.d(TAG, "Resource filename:" + value.string.toString());
// ^^ This would print res/drawable/pic.jpg
Source: android/frameworks/base/core/java/android/content/res/Resources.java
You can do so
Field[] fields = R.raw.class.getFields();
for (int count = 0; count < fields.length; count++) {
// Use that if you just need the file name
String filename = fields[count].getName();
Log.i("filename", filename);
int rawId = getResources().getIdentifier(filename, "raw", getPackageName());
TypedValue value = new TypedValue();
getResources().getValue(rawId, value, true);
String[] s = value.string.toString().split("/");
Log.i("filename", s[s.length - 1]);
}
This should be the best solution:
TypedValue value = new TypedValue();
getResources().getValue(resourceId, value, true);
String resname = value.string.toString().substring(13, value.string.toString().length());
resname = "pic.jpg"
Short answer: You can't.
Another way to do this, would be to put your graphics inside the assets folder.
Then you can access the Files directly, without your App needing any permission.
You can, for example, do so in your Activity:
AssetManager am = this.getApplicationContext().getAssets()
InputStream is = am.open(foldername+"/"+filename)
Bitmap myNewImage = BitmapFactory.decodeStream(is);
I hope that this will accomplish what you had in mind.
UPDATE: it seems it is indeed possible, see Aleksandar Stojiljkovic's answer instead.

Categories

Resources