Programatically set background (drawable) doesn't center - android

I wrote an app that lets people select an image (drawable) and after they hit the "set as background" button the selected image should appear centered as the background of my phone.
Following code used to work fine. The image was placed and centered. But for operating systems (> api 13) it is depreciated. Does anyone know how to fix so that the image is also centered (or scaled to fit the screen if you wish)?
I've tried replacing it with "displaymetrics" or "points" to get w or h but it doesn't help centering the image. Is it the "suggestDesiredDimensions" that doesn't do it anymore?
ResID is the identifier of the needed drawable.
Anyone knows how to handle this? Thanks!
public void setBackground(View v)
{
try {
// Set background from a resource
WallpaperManager.getInstance(this).setResource(resID);
WallpaperManager wm = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
Display display = getWindowManager().getDefaultDisplay();
int w = display.getWidth(); // deprecated
int h = display.getHeight(); //deprecated
wm.suggestDesiredDimensions(w, h);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Try using display.getSize()
public void setBackground(View v){
try {
// Set background from a resource
WallpaperManager.getInstance(this).setResource(resID);
WallpaperManager wm = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int w = size.x;
int h = size.y;
wm.suggestDesiredDimensions(w, h);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Related

Home screen wallpaper gets zoomed when it goes to the background

I have scheduled background service to change device home screen wallpaper periodically. The wallpaper changes successfully and they are perfectly set to the screen size.
But when I move away from the home screen and return the image gets zoomed in too much,leaving only a portion of the image visible.Below given is the code I use
Bitmap theBitmap = null;
try {
DisplayMetrics metrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;
theBitmap = Glide.with(mContext)
.load(PhotoPath)
.asBitmap().into(width, height).get();
WallpaperManager wm = WallpaperManager.getInstance(mContext);
wm.setWallpaperOffsetSteps(1, 1);
wm.suggestDesiredDimensions(width, height);
try {
wm.setBitmap(theBitmap);Album
} catch (IOException e) {
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Try not to rush and flag this question as a duplicate. There are questions stating the image appears zoomed in when set but My wallpaper gets set perfectly,atleast initially it does. Why does it zoom in when I move homescreen to the background.

Image gets zoomed while setting as wallpaper in my android application

I am trying to set my image as wallpaper but it gets zoomed/cropped when set as wallpaper. I have tried almost everything but nothing works.
Here is my piece of code:
public void setAswallpaper(Bitmap wallpaper)
{
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
System.out.println("screen dimensions "+width+" "+height);
System.out.println("wallpaper dimensions "+wallpaper.getWidth()+" "+wallpaper.getHeight());
wallpaper = Bitmap.createScaledBitmap(wallpaper, width*2 , height, true);
try {
WallpaperManager wallpaperManager=WallpaperManager.getInstance(context);
wallpaperManager.suggestDesiredDimensions(width,height);
System.out.println("wallpaper manager dimensions "+wallpaperManager.getDesiredMinimumWidth()+" "+wallpaperManager.getDesiredMinimumHeight());
wallpaperManager.setBitmap(wallpaper); }
}
catch (IOException e)
{
e.printStackTrace();
Toast.makeText(context,
"Wallpaper Not Set",
Toast.LENGTH_SHORT).show();}
}
I need help so that I can set my complete image as wallpaper
My image size is : 640*960
bitmap size is : 1960*2880
screen dimensions : 1080*1960

Android : Issue with memory for large Bitmap objects

Lots been said, written, vented out ;) on this already, I know. But my question is a bit different. I realize that there is issue with using large bitmap objects in Android. In my Android App, I need to use large bitmaps in various places. cannot help it. I tried various things listed in stackoverflow. One that I want to try but not able to is to avoid using ARBG_8888. The App crashes exactly at that line many times. I have an ImageView where I load an initial large bitmap. Then the user can make some markings in the bitmap and then I need to save the whole image (i.e. the original bitmap + the user's markings). Am trying this with this code I got from stackoverflow:
public static Bitmap loadBitmapFromView(Context context, View view) {
Log.d(logtag, "loadBitmapFromView");
Bitmap bitmap;
BitmapFactory.Options options = new BitmapFactory.Options();
// These help in saving/recycling the bitmap memory
options.inPurgeable = true;
options.inInputShareable = true;
Bitmap dummy = null;
try {
dummy = BitmapFactory.decodeStream(context.getAssets().open("icon_add.png"), new Rect(-1,-1,-1,-1), options);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bitmap = Bitmap.createBitmap(view.getLayoutParams().width,
view.getLayoutParams().height, Bitmap.Config.ARGB_8888);
// bitmap = Bitmap.createScaledBitmap( dummy, view.getLayoutParams().width,
// view.getLayoutParams().height, false);
Canvas c = new Canvas(bitmap);
view.layout(0, 0, view.getLayoutParams().width, view.getLayoutParams().height);
view.draw(c);
Log.d(logtag, "loadBitmapFromView: width:" + view.getLayoutParams().width);
c = null;
return bitmap;
}
How do I avoid using ARGB_8888 in the above code? Can someone please help?
I removed it from many other places in the code, but, in the above snippet, am left in vain.
I tried using an initial dummy object (you can see the object 'dummy' in the above code) to create a scaled bitmap object ( with createScaledBitmap() which necessarily asks for a source bitmap ) and then tried to load the canvas, but the generated image is having only the dummy object (icon_add.png) and not the one from the imageview.
you can show image in device specific height width....then you don't get out of memory for imagesize.
this is code:
#SuppressLint("NewApi")
public static int getDeviceWidth(Activity activity) {
int deviceWidth = 0;
Point size = new Point();
WindowManager windowManager = activity.getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
windowManager.getDefaultDisplay().getSize(size);
deviceWidth = size.x;
} else {
Display display = windowManager.getDefaultDisplay();
deviceWidth = display.getWidth();
}
return deviceWidth;
}
#SuppressLint("NewApi")
public static int getDeviceHeight(Activity activity) {
int deviceHeight = 0;
Point size = new Point();
WindowManager windowManager = activity.getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
windowManager.getDefaultDisplay().getSize(size);
deviceHeight = size.y;
} else {
Display display = windowManager.getDefaultDisplay();
deviceHeight = display.getHeight();
}
return deviceHeight;
}
you can use device height and width..and set this image in imageview..
ImageView image = new ImageView(viewHomeScreen);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.FILL_PARENT,
FrameLayout.LayoutParams.FILL_PARENT);
params.height = getDeviceHeight(activity);
params.width = getDevicewidth(activity);
FrameLayout framelayout = new FrameLayout(viewHomeScreen);
framelayout.addView(image, 0, params);
i hope if you use device specific height and width then your image memory issue will be solved.

Android get Screen Size deprecated?

Hey I need to get the width of the screen in my application. The application will run on 2.1 and upwards. I have set it up like the one below. The method is deprecated and i should proabably use getSize or a other way. But the question is: Will this work on android versions like 3.0+ and 4.0+, or will it make the app crash. I have used a deprecated method in a thread before and it made the app crash on ice cream devices. Will the method below work ?
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
EDIT:
I have tried the getSize but i dont get it to work:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
I am not sure but this may work:
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) {
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
} else {
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
}
I don't know whether these deprecated methods will work on Android 3 and 4. The best way to tell is to test on an emulator.
But, the safest method here for max compatibility will be to try one method using reflection, and fall back to the other. Essentially, you could make your own version of getSize() that can't fail. I can't test this atm, but it might look like this:
void overrideGetSize(Display display, Point outSize) {
try {
// test for new method to trigger exception
Class pointClass = Class.forName("android.graphics.Point");
Method newGetSize = Display.class.getMethod("getSize", new Class[]{ pointClass });
// no exception, so new method is available, just use it
newGetSize.invoke(display, outSize);
} catch(NoSuchMethodException ex) {
// new method is not available, use the old ones
outSize.x = display.getWidth();
outSize.y = display.getHeight();
}
}
Then of course just call it with something like
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
overrideGetSize(display, size);
I've extended Steve's helpful code so that Eclipse doesn't give any warnings or errors, and I've also restructured it slightly. Since the Point class has been present since API level 1 I didn't see much benefit in creating it through reflection.
final static String mTAG = "MYTAG";
// Cope with deprecated getWidth() and getHeight() methods
Point getSize(Display xiDisplay)
{
Point outSize = new Point();
boolean sizeFound = false;
try
{
// Test if the new getSize() method is available
Method newGetSize =
Display.class.getMethod("getSize", new Class[] { Point.class });
// No exception, so the new method is available
Log.d(mTAG, "Use getSize to find screen size");
newGetSize.invoke(xiDisplay, outSize);
sizeFound = true;
Log.d(mTAG, "Screen size is " + outSize.x + " x " + outSize.y);
}
catch (NoSuchMethodException ex)
{
// This is the failure I expect when the deprecated APIs are not available
Log.d(mTAG, "getSize not available - NoSuchMethodException");
}
catch (InvocationTargetException e)
{
Log.w(mTAG, "getSize not available - InvocationTargetException");
}
catch (IllegalArgumentException e)
{
Log.w(mTAG, "getSize not available - IllegalArgumentException");
}
catch (IllegalAccessException e)
{
Log.w(mTAG, "getSize not available - IllegalAccessException");
}
if (!sizeFound)
{
Log.i(mTAG, "Used deprecated methods as getSize not available");
outSize = new Point(xiDisplay.getWidth(), xiDisplay.getHeight());
}
return outSize;
}
According to https://stackoverflow.com/a/1016941/2914140:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width = metrics.widthPixels;
int height = metrics.heightPixels;
What is wrong with Display's new function, getSize()? It'd be really easy to turn the Point object into the width and height values you need.

getSize() not supported on older Android OS versions, getWidth() / getHeight() deprecated

So how do I write code to accommodate for this? I don't want to leave deprecated API calls in my code, but I also don't want to lose the users with (slightly) older devices. Is there some sort of compatibility setting I can implement?
Rel. code
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int screen_width = size.x;
int screen_height = size.y;
vs. the older method:
int screen_width = getWindowManager().getDefaultDisplay().getWidth();
int screen_height = getWindowManager().getDefaultDisplay().getHeight();
i have two functions, sending the context and gettin height and width in pixels.
public static int getWidth(Context mContext){
int width=0;
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
if(Build.VERSION.SDK_INT>Build.VERSION_CODES.HONEYCOMB){
Point size = new Point();
display.getSize(size);
width = size.x;
}
else{
width = display.getWidth(); // deprecated
}
return width;
}
and
public static int getHeight(Context mContext){
int height=0;
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
if(Build.VERSION.SDK_INT>Build.VERSION_CODES.HONEYCOMB){
Point size = new Point();
display.getSize(size);
height = size.y;
}else{
height = display.getHeight(); // deprecated
}
return height;
}
The best (and by best, I mean the option that would work pretty much every time) option would be to use reflection. Check out the Android Backwards Compatibility Backwards Compatibility guidelines (updated with new location of the article on reflection).
While tyczj's answer will work perfectly so long as the deprecated functions are still in the SDK, as soon as they are removed you will have no way of using them or running your app on an older device if you still want to build against the latest SDK.
Reflection solves this problem by effectively dynamically detecting the function at runtime, which means that even if you build against ICS, so long as the minSdkVersion is correct, you can have your app run on a device with Gingerbread, or Froyo for example.
you can do something like this
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH){
//do stuff pertaining to this version here
}else{
//other versions
}
I think sort of thing RivieraKid is suggesting, would be something like this:
static Point getDisplaySize(Display d)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
{
return getDisplaySizeGE11(d);
}
return getDisplaySizeLT11(d);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
static Point getDisplaySizeGE11(Display d)
{
Point p = new Point(0, 0);
d.getSize(p);
return p;
}
static Point getDisplaySizeLT11(Display d)
{
try
{
Method getWidth = Display.class.getMethod("getWidth", new Class[] {});
Method getHeight = Display.class.getMethod("getHeight", new Class[] {});
return new Point(((Integer) getWidth.invoke(d, (Object[]) null)).intValue(), ((Integer) getHeight.invoke(d, (Object[]) null)).intValue());
}
catch (NoSuchMethodException e2) // None of these exceptions should ever occur.
{
return new Point(-1, -1);
}
catch (IllegalArgumentException e2)
{
return new Point(-2, -2);
}
catch (IllegalAccessException e2)
{
return new Point(-3, -3);
}
catch (InvocationTargetException e2)
{
return new Point(-4, -4);
}
}
I usually have a super class ie. BaseActivity with a generic method for getting a point with the current screen size. Keeps everything nice and clean in the actual activity.
/**
* Return screen size as a point.
* #return
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
#SuppressWarnings("deprecation")
protected Point getSize() {
final Point point = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
getWindowManager().getDefaultDisplay().getSize(point);
}
else {
final Display display = getWindowManager().getDefaultDisplay();
point.x = display.getWidth();
point.y = display.getHeight();
}
return point;
}

Categories

Resources