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.
Related
I'd like to get the size of the screen of the phones but it keeps giving me wrong values, I already used
WindowManager windowmanager = (WindowManager)
getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
Display display = windowmanager.getDefaultDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
display.getMetrics(displayMetrics);
float deviceWidth = displayMetrics.widthPixels;
float deviceHeight = displayMetrics.ydpi;
I tried this code too :
Resources resources = getResources();
Configuration config = resources.getConfiguration();
DisplayMetrics dm = resources.getDisplayMetrics();
// Note, screenHeightDp isn't reliable
// (it seems to be too small by the height of the status bar),
// but we assume screenWidthDp is reliable.
// Note also, dm.widthPixels,dm.heightPixels aren't reliably pixels
// (they get confused when in screen compatibility mode, it seems),
// but we assume their ratio is correct.
double screenWidthInPixels = (double)config.screenWidthDp *dm.density;
double screenHeightInPixels = screenWidthInPixels * dm.heightPixels / dm.widthPixels;
deviceWidth = (int)(screenWidthInPixels + .5);
deviceHeight = (int)(screenHeightInPixels + .5);
And also that :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Point realSize = new Point();
display.getRealSize(realSize);
deviceWidth= realSize.x;
deviceHeight = realSize.y;
}
But on my Samsung S7 on sdk 7.0 I got 1920x1080 that is wrong because on a S7 on sdk 6.0.1 I got 2560x1440 that is the real value.
I tried a lot of solution but found nothing good.
Thanks
Your code is correct. Just in case if you wondering why you get that values, it is because your phone will automatically set the default resolution size to 1920x1080 after updated to 7.0 (Nougat) to conserve the battery life. One of the new features in Nougat is display scaling option, where you can set your phone (in this case, S7) to 3 available modes (WQHD (2560x1440), FHD (1920x1080), and HD (1280x720)). Try go to Settings -> Display and change the settings to your needs. You can read more here: Galaxy S7 on Nougat defaults to 1080p
use this
getWindowManager().getDefaultDisplay().getHeight();
getWindowManager().getDefaultDisplay().getWidth();
This will work for sure.
try {
display.getRealSize(size);
height = size.y;
width=size.x;
} catch (NoSuchMethodError e) {
height = display.getHeight();
width=display.getWidth();
}
Try this link
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
The method below return a Point that contain display size (x as Width and y as Height):
public static Point checkDisplaySize(Context context) {
Point tempDisplaySize = new Point();
try {
WindowManager manager = (WindowManager) context().getSystemService(Context.WINDOW_SERVICE);
if (manager != null) {
Display display = manager.getDefaultDisplay();
if (display != null) {
display.getSize(tempDisplaySize);
Log.d("tmessages", "display size = " + displaySize.x + " " + displaySize.y);
}
}
} catch (Exception e) {
Log.e("tmessages", e.getMessage(), e);
}
return tempDisplaySize;
}
P.S: This is the Code Telegram uses to get display size.
Hello I want to ask about the most efficient way to adjust layout in all devices mobile and tablets sometimes I can't use wrap_content and layout_weight
I set size in some percentage to the device size in java like this:
ImageView img;
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
img.getLayoutParams().width = width* 7 / 10;
and when rotating screen I use this method to change percentage
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE&& getResources().getBoolean(R.bool.isTablet)) {
width=(int) (width * 0.7);
}
I am asking If this procedure is more efficient than using multi XML files for each screen size / orientation
Actually it depends on the scenario. Sometimes maintaining xml is efficient and easy sometimes dynamic calculation is necessary. You can go through the link https://developer.android.com/guide/practices/screens_support.html . It will give you some ideas. In your above code for width/height calculation sometimes you may not get proper result for some devices. Below is the code that will support all version of android device Resolution(Width, Height) accurately at runtime.
private void calculateDeviceResolution(Activity context) {
Display display = context.getWindowManager().getDefaultDisplay();
if (Build.VERSION.SDK_INT >= 17) {
//new pleasant way to get real metrics
DisplayMetrics realMetrics = new DisplayMetrics();
display.getRealMetrics(realMetrics);
realWidth = realMetrics.widthPixels;
realHeight = realMetrics.heightPixels;
} else if (Build.VERSION.SDK_INT >= 14) {
//reflection for this weird in-between time
try {
Method mGetRawH = Display.class.getMethod("getRawHeight");
Method mGetRawW = Display.class.getMethod("getRawWidth");
realWidth = (Integer) mGetRawW.invoke(display);
realHeight = (Integer) mGetRawH.invoke(display);
} catch (Exception e) {
//this may not be 100% accurate, but it's all we've got
realWidth = display.getWidth();
realHeight = display.getHeight();
Constants.errorLog("Display Info", "Couldn't use reflection to get the real display metrics.");
}
} else {
//This should be close, as lower API devices should not have window navigation bars
realWidth = display.getWidth();
realHeight = display.getHeight();
}
}
I am having a dynamic layout where there is a imagebutton named ButtonQ.
I would like to set the dimension of the ButtonQ and then to see if it is correct, I have added a toast.
#Override
protected void onStart()
{
super.onStart();
measure_dimension();
}
private static Point getDisplaySize(final Display display)
{
final Point point = new Point();
try {
display.getSize(point);
} catch (java.lang.NoSuchMethodError ignore) { // Older device
point.x = display.getWidth();
point.y = display.getHeight();
}
return point;
}
public void measure_dimension()
{
Display display = getWindowManager().getDefaultDisplay();
Point size = getDisplaySize(display);
int screen_width = size.x;
int screen_height = size.y;
int target_height = Math.min(screen_height, 600);
int target_width = Math.min(screen_width, 600);
int target_dimension = Math.min(target_height, target_width);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(target_dimension, target_dimension); // width, height
buttonQ.setLayoutParams(layoutParams);
image_height = target_height;
image_width = target_width;
Toast.makeText(Game_middle.this, "buttonQ height:"+ buttonQ.getHeight() +"\nbuttonQ width=" + buttonQ.getWidth(), Toast.LENGTH_LONG).show();
}
Question:
The toast reports the height and the width of ButtonQ are both 0.
Why?
I'd use the analogue way you're setting your height and width: via getLayoutParams(). If you want to set the params dynamically, I wouldn't use pixels directly but the dp unit, using TypedValue.COMPLEX_UNIT_DIP.
Regarding to synchronization, in that example I'd definitely use asynchronous mechanisms, such as CountDownLatch or Semaphore mechanisms. It's quite more secure this way than using temporary timers. You may want to check the CountDownLatch(1) example in the reference page for that purpose.
Try this to get the button dimensions where popLayout is the button name in your case
popupLayout.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
width = popupLayout.getMeasuredWidth();
height = popupLayout.getMeasuredHeight();
I'm writing an App for Android.
I want to gather the screen width during runtime dynamically to draw the dialogs depending on the display size. For that I wrote the following function:
public static int getDisplayWidth( Context context )
{
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int width = 0;
if( android.os.Build.VERSION.SDK_INT >= 13 )
{
Point size = new Point();
display.getSize(size); //Error
width = size.x;
}
else
{
width = display.getWidth();
}
return width;
}
But I get an error on line "display.getSize(size);"
Error: "The method getSize(Point) is undefined for the type Display"
I use Ecslipe as Development Environment.
Project Build Target is "Android 2.3.3".
In Manifest.xml I set:
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" />
Can anybody tell me why I get this error?
What have I done wrong?
Sapp
Older Android versions don't have the getSize() method. The error is either calling, or linking, to the absent function.
private static Point getDisplaySize(final Display display) {
final Point point = new Point();
try {
display.getSize(point);
} catch (java.lang.NoSuchMethodError ignore) { // Older device
point.x = display.getWidth();
point.y = display.getHeight();
}
return point;
}
Experiment with the try-catch & see if this helps. This should safely fallback to the older API & ensure your code works on the broad range of devices.
Really, a bit of a balls-up on Google's part.
See:
http://developer.android.com/reference/android/view/Display.html
getSize() giving me errors
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;
}