So I'm implementing admob banners into my Unity 4.6 Android game. I have the banner at the bottom and need to account for it in my UI. Specifically I need to know exactly how tall it is, but I'm having trouble with figuring this out.
Based on the information found here the Smart Banner should be 32, 50, or 90 pixels tall, depending on device height. This doesn't seem to typically be the case though.
Some searching would seem to indicate this is because of density pixels. So I attempt to convert the stated pixel height using px = dp * (Screen.dpi/ 160). So for example if I determine the banner height should be 90 pixels, I would use bannerHeight = 90 * (Screen.dpi / 160). This seems to work on some devices but not others.
For example my Nexus 4 has a DPI of 320. Using the above it would seem to indicate that the banner should be 180 pixels tall, but the banner appears to actually be about 90 pixels tall. But on the Nexus 7 (which has a dpi of 166), the banner appears to be about 120 pixels tall when the formula would indicate it should be ~93.
So I guess I have no idea how to figure out how tall the banner is actually going to be, and I haven't found a way to get this information from the API. My code for calling the banner is pretty stock:
string adUnitId = "my_id";
BannerView bannerView = new BannerView(adUnitId, AdSize.SmartBanner, AdPosition.Bottom);
AdRequest request = new AdRequest.Builder().Build();
bannerView.LoadAd(request);
First you need to calculate which Ads google will give you (32 or 50 or 90 ?)
for this you can calculate it by screen sizes.
height/dpi = actual height in inches
so, Google says above 720 (with dp of 160dpi) is acctauly
720/160 = 4.5 inch height, above this height, the ads are 90 pixels (dp!)
below its 50 dp!
400/160 = 2.5 , below this, ads will be 32 dp
SO!
if i have Xiaomi mi3 with 1920x1080
thats,
1920/480dpi = 4 inch height..which will give us 50 dp ads.
with the formula of converting DP to pixel
px = dp * (Screen.dpi/ 160)
50 * (480/160) = 150 pixels height for the ad!
For landscape you need to use as "height" 1080 instead of 1920
1080/480dpi = 2.25 height in landscape
this means the ads will be 32 pixels dp
which converts to:
32* (480/160) = 96 pixels in landscape
its too bad google doesn't give enough examples so we can really check ourselves.
Your info page is:
https://developers.google.com/admob/android/banner
There is answer:
https://stackoverflow.com/a/14204959/1900546
int heightPixels = AdSize.SMART_BANNER.getHeightInPixels(this);
The following function may come in handy to those of you using Admob Smart Banners:
public static float adHeight(){
float f = Screen.dpi / 160f;
float dp = Screen.height / f;
return (dp>720f)? 90f * f
:(dp>400f)? 50f * f
:32f * f;
}
To use it:
r.offsetMin = new Vector2(r.offsetMin.x, adHeight());
where r is the RectTransform of the fullscreen Canvas / Panel.
I am attaching a 'loadBannerAd' script to every panel which requires it.
The link you gave says that the Smart banner will have a height of
32 dp for phones in landscape
50 dp for phones in portrait
90 dp for tablets in either orientation
Let's take the two examples you gave.
The Nexus 4 has a DPI of ~320 dp. Given that it's a phone, it'll have an ad with a height of 50 dp.
Using the formula, it works out to 50 * 320 / 160 = 100 pixels (close to your actual banner's height)
The Nexus 7s I looked up have either a 216 dp (2012) or 323 dp (2013), so I don't quite know which model has 166 dp.
But let's assume that it's 216 dp, then being a tablet, ad height in dp is 90. Therefore, pixels = 90 * 216 / 160 = 121.5, once again close to your banner's actual height.
I realize that Google has also mentioned the following
For devices with heights between 400 & 720, an ad with a height of 50 is used
For devices with heights above 720, an ad with a height of 90 is used.
However, I believe that the 400 & 720 MIGHT also be expressed in dp? i.e. 400 pixels in an mdpi device. Your Nexus 4 being an xhdpi device (320 dp), with a height of 1280 pixels then would be the same as an mdpi device of height 640 pixels, falling within the range for an ad height of 50 dp.
Bottomline, your calculations seem valid. Stick to the first set of rules, and you should see consistent results.
bannerView.SetPosition(AdPosition.Top);
or something similar to this is how you change a position of an active banner
Related
I have a major issue I am working on for days now. It is much understandable by looking at the requirement first. I will list down my requirement as simple as possible in point form below.
I have 5 android phones. 5 different brands, different screen sizes.
Imagine the screen sizes are 4inch, 4.5inch, 5inch, 5.1inch and 5.2inch
I have an android app and it has a drawing canvas.
Now using canvas.drawCircle(x / 2, y / 2, radius, paint) I am drawing a circle. Imagine the radius is 100 (100 pixels?)
I install this app in my smallest screen phone, 4inch. Then I use a ruler and measure the the circle diameter. Imagine the circle diameter is "exact" 3cm.
Now I install this in my other phones.
Unfortunately, in my 4.5 inch phone the circle diameter is 3.2cm. In 5 inch phone it is 3.3 cm. In 5.1 inch phone it is 2.8cm and so on.
However I want my circle diameter to be 3cm (exact 3cm) in every phone.
Above requirement is something I am trying for days now. I tried the following to make sure I get a circle with no size change across all screens.
Using ImageView - I tried using an ImageView and added a circle image. I have given the width, height fixed. I have tryied setting the values in px, dp, inches etc. I also tried scalling options available for ImageView. Also tried placing the same image in drawable-nodpi folder. Tried creating drawable folders for all sizes (ex: drawable-mdpi, drawable-hdpi). Non of this stopped the image from being scaled.
Using Canvas - As explained in the above, I tried using canvas and drawing the image. The drawing scales.
Finding pixels per inch.- Tried finding pixels per inch of each phone programatically thinking I can find a way to develop a logic from it to dynamically draw the images in same size. I used several links including - Calculate PPI of Android Device. Most of them talk about getting screen resolution only.
How can I fulfill my requirement of drawing same size circles? If it can be done by knowing PPI, how should I do it?
The Answer before has worked for me but as long as it didn't for you I will try explain something I think it will help.
I have a device that have a density of 1 (160 px per inch), and the Display metrics told me that i have 320 * 480 pixels, with simple calculation I should know my mobile width and height in inch like this : 320 /160 = 2 inch for width , 480/160 = 3 . for now everything was just fine until i got the ruler and measured it and the surprise was this : I have a 1.65 * 2.48 inch !!.
Then I noticed that there is something called physical pixels per inch of the screen this was the relief for me and you can get it like this :
getResources().getDisplayMetrics().xdpi; //for width physical dpi
getResources().getDisplayMetrics().ydpi; //for height physical dpi
And now I can calculate my Physical width and height of my device like this :
my physical dpi for both width and height is 193.5238 so...
320 / 193.5238 = 1.65 inch width
480 / 193.5238 = 2.48 inch height
And that was correct !!.
Now back to your problem lets get the 3cm in pixels for any Phone :
getting the width in cm :
width in cm = width in inch * 2.54 (because 1 inch equals 2.54 cm)
getting the amount of pixels in each cm :
width in pixels / width in cm = Pixels per cm for width (px/cm)
now you want a 3cm then the pixels according to it is:
3 * Number = 3cm Pixels
all of the above can be shortened like this :
float devicePixelsWidth = getResources().getDisplayMetrics().widthPixels;
float deviceActualDpi = getResources().getDisplayMetrics().xdpi ;
float deviceActualInchWidth = devicePixelsWidth / deviceActualDpi ;
float deviceActualCMWidth = deviceActualInchWidth * 2.54f ;
float PixelsForActual3CM = devicePixelsWidth / deviceActualCMWidth * 3;
In the end, all of the above has been tested and approved by me and has the same accuracy of the previous Answer method :)
maybe this is not answer, but might be helpful
float _100MmAsPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM,
100/*mm unit set*/, getResources().getDisplayMetrics());
above gives me 1661.5354 on Nexus 5x and 1889.7638 Nexus 5 (emulator). both have fullHD display, but 5 has 4.95 inch versus 5.2 inch in 5x.
it means 100 millimeters is 1662 pixels on 6 and 1890 on 5x
I know this might be a silly question but I have really gone through so many materiel and links but still not quite understand it. In the "Supporting Multiple Screens" section of Android Develop Doc, it introduces dp like this:
Density-independent pixel (dp)
A virtual pixel unit that you should use when defining UI layout, to express layout dimensions or position in a density-independent way. The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a "medium" density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different densities.
Basically I understand the fact that screen with higher dpi would have more pixels in a single physical inch, which means a dp in such a screen would equal more physical pixels(px).
But according to the above conversion equation (in bold font), in a screen with higher dpi (e.g. 240 dpi screen) , a px = (240 / 160) * dp = 1.5dp. This seems to mean that in higher dpi screen a px would equal more dp. This looks in conflict with my previous understanding.
So, please, could anyone help me to figure this tricky issue out. Thank you a lot, really.
You are looking at the wrong place in the formula. To see how many dp equals one px in different density, lets rearrange the formula:
px = dp * (dpi/160)
dp = px / (dpi/160)
Now for 1px, in mdpi devices:
dp = 1 / (160/160) = 1dp
In hdpi devices:
dp = 1 / (240/160) = 0.666666667dp
You can see that 1px equals less dp in higher density devices
I'm testing on a Samsung Galaxy Note 3 which according to the docs is 1080 x 1920 pixels (~386 ppi pixel density). I want to figure out what the screen width in dp is so I can properly apply and check the new size qualifiers.
I've measured the screen width (in portrait) with a good 'ole ruler = 71mm = 2.8 inches
1080 / 2.8 = 386 ppi. Great, this matches the stated density.
I'm trying to figure out how many dp units the screen is wide.
dp = px / (dpi / 160) from here
= 1080 / (386 / 160) = 1080 /
2.4125 = 447.7 dp
So if I do this:
<TextView
android:id="#+id/density_test"
android:layout_width="447dp"
android:layout_height="wrap_content"
android:background="#ffff0000"
android:text="DENSITY TEST 447dp" />
then on my Galaxy Note 3 this view should be almost exactly the width of the screen. But it isn't, it's way wider.
So I set the above view to layout_width="300dp", measured how wide it was with my ruler and extrapolated the actual screen width in dp, based on this test:
300dp = 59mm
Total screen width is 71mm
so extrapolating screen width in dp = (71 / 59) * 300 = 361dp
361dp != 447.7dp
What is going on here? I feel like I must be doing something dumb.
Edit: I tried putting the layout file inside /res/layout-xhdpi but it had no effect. I thought maybe it was scaling it by xhdpi / mdpi since I had the xml in the default /res/layout dir.
The actual pixel size is calculated based on dp, but not as accurate as the formula dp = px / (dpi / 160) does. Indeed, it first determines the screen density (ldpp, mdph, hdpi, xhdpi, xxhdpi, xxxhdpi) and using that density to get one ratio from {0.75, 1.0, 1.5, 2.0, 3.0, (4.0)}.
In you case, the system deems 386dpi as xxhdpi, so it calculates the value by multiplying 3.0, and 360dp would exactly fill the width of your screen (1080p)
I'm trying to integrate ads into my Android app using AdWhirl and AdMob.
The AdWhirl site gave me the following code to use:
AdWhirlLayout adWhirlLayout = (AdWhirlLayout) findViewById(R.id.layoutAdWhirl);
int diWidth = 320;
int diHeight = 52;
int density = (int) getResources().getDisplayMetrics().density;
int scaledWidth = (int) (diWidth * density);
int scaledHeight = (int) (diHeight * density);
adWhirlLayout.setAdWhirlInterface(this);
adWhirlLayout.setMaxWidth(scaledWidth);
adWhirlLayout.setMaxHeight(scaledHeight);
This works just fine on some of my emulators, but when I try some smaller or older emulators, I get the following error in LogCat:
Not enough space to show ad! Wants: 480, 75, Has: 320, 52
What am I supposed to do if I'm using their code for requesting an appropriately sized ad, but then they won't display that ad?
Couple of things here:
The AdMob ad needs 320x50 density-independent pixels to show an ad. Every Android device, even the old small ones, meet these specs. The small 240x400 pixel phones are low density, meaning 1px = 0.75dp, and so there are still 320dp in portrait mode to show an ad. Your small emulators are probably in such a state where they are really small (low pixel count), but have medium or high density such that the emulator isn't 320dp wide. Check your emulator settings - they are likely not representative of any device.
The above code to calculate max width and max height isn't necessary. As long as the xml gives the AdWhirlView 320x52dp size (or more preferred, wrap_content), you don't need to grab the device density to calculate these values manually.
UPDATE:
I have a new theory. The error you're displaying where the AdMob SDK Wants: 480, 75 means you're running on a high-density device, because it multiplied 320x50dip by 1.5. However, the piece of code:
int density = (int) getResources().getDisplayMetrics().density;
is casting 1.5 to 1, so the max width and height of the adWhirlLayout were incorrectly set to 320x52 pixels. This would probably have been an issue for low density devices as well, because 0.75 density would have been casted to 0. It may have worked on medium density devices.
The AdWhirl documentation is a bit outdated, but it probably should have said float density instead of int density.
One would say that if the Galaxy Tab screen resolution (in portrait mode) is 600px and the screen width is 3.55inch, the screen density would be 600/3.55 = 169 dpi. Knowing that and keeping in mind the way the device independent pixels (dp) is computed (http://developer.android.com/guide/practices/screens_support.html):
px = dp * (dpi / 160);
600 = dp * (169 / 160);
dip = 568
So drawing a horizontal line of 568dp (device independent pixels) width starting at position 0 must exactly match the width of the screen. But if you try this on device you will find that the screen width is 400dp. I will use the same formula again but for getting dpi:
600 = 400 * (dpi / 160);
dpi = 240
So having the 240dpi, 3.55inch screen width and 600pixels, does it mean that one physical pixel is composed of more ‘dots’ otherwise the parameters corresponds to the width of 852pixel (3.55*240).
I thought that dpi means dots per inch, which is pixels per inch. But this seems to not be true...
Added later:
This (http://developer.android.com/guide/topics/resources/more-resources.html#Dimension) says:
160dp is always one inch regardless of the screen density
Which is not true. Just check the measurement source from this:
Difference between android dimension: pt and dp
Added even later:
The reason I am asking is that violating the rule that 160dp = 1inch leads to the fact that when specifying the control width to e.g. 320dp it will cover on Galaxy Tab much bigger portion that that really necessary and much bigger then what you would expect from 600x1024px screen...
Thanks for clarification
BR
STeN
Galaxy Tab (7") doesn't report its real density. To understand this issue, read the following article:
http://realmike.org/blog/2010/12/21/multiple-screen-sizes-with-processing-for-android/
Apparently, that’s also what Samsung found when they made the Galaxy
Tab. The Galaxy Tab has a 7″, 1024×600 screen with 170 dpi. Yet, the
Tab does not report its density as “mdpi” but as “hdpi”, so the layout
looks exactly as in the second screenshot. If they used “mdpi”, the
icons would be .28″ wide, with “hdpi”, they are .42″ wide—not a big
deal, and I must admit, the layout does look prettier this way.
The article contains some images that will make you understand the problem.