trouble with scale graphic - java

I have a problem with android, version 5.1. (lolipop).
When I tried to scale bitmap using Bitmap.createScaledBitmap, app was send to me an error:
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
I doesn't know why this is doing. On newest versions of android this working good.
ImageView imageView = this.menuPageModel.getBackground();
int id;
Bitmap bitmap;
Context context = appModel.getContext();
id = context.getResources().getIdentifier("background", "drawable", context.getPackageName());
bitmap = BitmapFactory.decodeResource(context.getResources(), id);
bitmap = Bitmap.createScaledBitmap(bitmap, appModel.getScreenWidth(), appModel.getScreenHeight(), false);
imageView.setLayoutParams(new android.view.ViewGroup.LayoutParams(appModel.getScreenWidth(), appModel.getScreenHeight()));
imageView.setImageBitmap(bitmap);

Related

Decoding bitmap from Drawable Resource Id is giving null

I want to get Bitmap from drawable resource id, I found a solution to decode it using BitmapFactory decode method, but it's giving null.
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_tick);
Please check if you are using Vector drawable or normal png/jpeg image as a drawable, it gives null value if you try to decode vector drawable.
Use this code if you are trying to decode Vector drawable
public static Bitmap getBitmapFromVectorDrawable(Context context, int drawableId) {
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
drawable = (DrawableCompat.wrap(drawable)).mutate();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
Also make sure if you have vector support enable in your app gradle
vectorDrawables.useSupportLibrary = true

how to change android wallpaper from outside of the activity class?

in the end I'm starting up a service that I will want to call to that class and change my phone's wallpaper.
in the mainActivity java file I can just write >
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;
Bitmap bmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.superman);
Bitmap bitmap = Bitmap.createScaledBitmap(bmap2, width, height, true);
WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());
// Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.superman);
try {
wallpaperManager.setBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
and this works great... it uploads the wallpaper and starches it to fit screen
but I can't use it in another java class.,
how do I do this on another java class, and then later on call it from my myService Class ?
maybe don't use getWindowManager, from outside your activity ? since you can't use it outside activity class

How to fix "canvas: trying to use a recycled bitmap error"?

I'm creating a RecyclerView to show a Grid of pictures. When selecting one of them, it should open a new activity with a transition.
I'm using Glide library to load the pictures and the transition looks awful because it reloads the picture in the new activity. So I had to save it in cache, and then use it for the transition.
I have the code, but sometimes if the picture doesn't load, it throws a Canvas RuntimeException.
This is the log:
07-03 15:19:58.633 28461-28461/jahirfiquitiva.project E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: jahirfiquitiva.project, PID: 28461
java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap#29f09d20
at android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1282)
at android.view.GLES20Canvas.drawBitmap(GLES20Canvas.java:599)
at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:538)
at android.widget.ImageView.onDraw(ImageView.java:1176)
at android.view.View.draw(View.java:15239)
at android.view.View.updateDisplayListIfDirty(View.java:14175)
at android.view.View.getDisplayList(View.java:14197)
at android.view.GhostView.onDraw(GhostView.java:52)
at android.view.View.draw(View.java:15239)
at android.view.View.updateDisplayListIfDirty(View.java:14175)
at android.view.View.getDisplayList(View.java:14197)
at android.view.View.draw(View.java:14967)
at android.view.ViewGroup.drawChild(ViewGroup.java:3406)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3199)
at android.view.View.updateDisplayListIfDirty(View.java:14170)
at android.view.View.getDisplayList(View.java:14197)
at android.view.View.draw(View.java:14967)
at android.view.ViewGroup.drawChild(ViewGroup.java:3406)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3199)
at android.view.ViewOverlay$OverlayViewGroup.dispatchDraw(ViewOverlay.java:219)
at android.view.View.draw(View.java:15248)
at android.widget.FrameLayout.draw(FrameLayout.java:598)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2906)
at android.view.View.updateDisplayListIfDirty(View.java:14175)
at android.view.View.getDisplayList(View.java:14197)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:273)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:279)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:318)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2536)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2352)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1982)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5891)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5289)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
This is the code to open the other activity and save the picture as cache:
private void openViewer(WallpapersAdapter.WallsHolder wallsHolder, int index, final HashMap<String, String> data) {
final Intent intent = new Intent(wallsActivity, ViewerActivity.class);
intent.putExtra("wallUrl", data.get(WallpapersActivity.WALL));
intent.putExtra("wallName", data.get(WallpapersActivity.NAME));
intent.putExtra("transitionName", ViewCompat.getTransitionName(wallsHolder.wall));
//save image from drawable
//get its path and send it to activity
Bitmap bitmap = drawableToBitmap(wallsHolder.wall.getDrawable());
//Convert to byte array and send to the other activity
Log.e("Resolution", bitmap.getWidth() + "x" + bitmap.getHeight());
try {
//Write file
String filename = "bitmap.png";
FileOutputStream stream = this.openFileOutput(filename, Context.MODE_PRIVATE);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
//Cleanup
stream.close();
bitmap.recycle();
//Pop intent
intent.putExtra("image", filename);
} catch (Exception e) {
e.printStackTrace();
}
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
this, wallsHolder.wall, ViewCompat.getTransitionName(wallsHolder.wall));
startActivity(intent, options.toBundle());
}
public static Bitmap drawableToBitmap (Drawable drawable) {
Bitmap bitmap = null;
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
if(bitmapDrawable.getBitmap() != null) {
return bitmapDrawable.getBitmap();
}
}
if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
}
What could I do to fix this issue? Thanks in advance.
I suspect that once in a while your bitmap gets into the recycled state just before the Canvas gets a chance to draw onto it here drawable.draw(canvas);.
A quick solution should be not to call bitmap.recycle();, which is not strictly required for android >2.3.3. If you still want to reclaim this memory forcefully, you'll have to find a way to check when the bitmap is indeed no longer needed (i.e., Canvas had a chance to finish its drawing operations).
Move bitmap.recycle(); to another place in the code where this bitmap is really no longer needed.
Use this custom ImageView class
public class MyImageView extends ImageView {
public MyImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyImageView(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
try {
super.onDraw(canvas);
} catch (Exception e) {
Log.i(MyImageView.class.getSimpleName(), "Catch Canvas: trying to use a recycled bitmap");
}
}
}
I don't know much about canvas (I don't use animations that often) but if you don't find any way to fix this, you could try using this library instead: https://github.com/codepath/android_guides/wiki/shared-element-activity-transition
I solved by adding this:
Glide.with(activity).clear(view);
before load the image:
Glide.with(activity)
.load(imageUrl)
.apply(options)
.placeholder(R.drawable.loading_image)
.error(R.drawable.not_found)
.into(view);
See docs:
http://bumptech.github.io/glide/doc/resourcereuse.html
http://bumptech.github.io/glide/doc/resourcereuse.html#cannot-draw-a-recycled-bitmap

Set content of imageView as wallpaper (Picasso)

I'm using the picasso library for my app and it works very well so far. I have two activities, one which displays all the images and one that displays one image when I clicked on it in the first activity. The image is loaded into an imageView.
Now I want to set the content of this imageView as my homescreen wallpaper. So far I have this:
if (id == R.id.set_wall) {
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.id.image);
WallpaperManager myWallpaperManager = WallpaperManager
.getInstance(getApplicationContext());
try {
myWallpaperManager.setBitmap(mBitmap);
Toast.makeText(DetailActivity.this, "Wallpaper set",
Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(DetailActivity.this,
"Error setting wallpaper", Toast.LENGTH_SHORT)
.show();
}
return true;
}
But this gives me this error:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
Does anyone have an idea how I can set the content of this imageView as my wallpaper?
Thank you a lot!!
replace Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.id.image);
by Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
if you do not have a Drawable then ,
code to get bitmap from imageview
Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();

Android, Java: Share a dialog

I have a dialog with some TextViews and ImageViews inside. Now I want to share this with the Share Intent. Is this possible? Can I share a dialog or convert it first to a bitmap and then share it?
You can use this method.
public static Bitmap TakeBitmapFromDialog(View v, int width, int height) {
Bitmap b = Bitmap.createBitmap(width , height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
v.draw(c);
return b;
}
OR
simply use this.
View v1 = view.getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bm = v1.getDrawingCache();
BitmapDrawable bitmapDrawable = new BitmapDrawable(bm);
UPDATE:
if you don't want to use that then use this.
Bitmap cs = null;
view.setDrawingCacheEnabled(true);
view.buildDrawingCache(true);
cs = Bitmap.createBitmap(view.getDrawingCache());
Canvas canvas = new Canvas(cs);
view.draw(canvas);
canvas.save();
view.setDrawingCacheEnabled(false);
If you want to share that bitmap you need to insert in Media Images like,
String path = Images.Media.insertImage(getContentResolver(), cs,
"MyImage", null);
Uri file = Uri.parse(path);
Now for sharing,
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("image/png");
sharingIntent.putExtra(Intent.EXTRA_STREAM, file);
startActivity(Intent.createChooser(sharingIntent,
"Share image using"));
Create a custom dialog separately using activity context and use it in a separate activity.

Categories

Resources