How can I check the status bar colour in Android? - android

How can I check the status bar colour in Android?
Why do I need to check this? I have created my status bar icons as per the design guidelines however on some devices (Samsung Galaxy S) the status bar is black and it is running Android 2.1.
The recommendations for the status bar icons look great on Android 2.3 (Nexus S) and within the emulator (earlier Android 2.1) with the default light grey status bar. However the black icons that are recommended for pre-2.3 don't look clear on the Samsung Galaxy S.
I would like to provide a white icon if the Android is running 2.1 or 2.2 with a black status bar.
Basically the problem is that the Android design guidelines don't really cover the phones that changed the UI like the Samsung Galaxy S. For example the Samsung Galaxy S running Android 2.1 should have a light grey status bar but it has a black one. This doesn't fit in well with Google's provided design guidelines.

I've developed the following method to guess light value of a status bar background. It actually gets background color of a status bar item, but I assume the whole status bar should have similar color. I use this method to distinguish, whether to load black or white version of my status notification icon.
/**
* Returns estimated value of the lightness of the status bar background
* #return
*/
private int getStatusBarBackgroundLightValue()
{
// better this than nothing
Drawable bg = getResources().getDrawable(android.R.drawable.status_bar_item_background);
int height = Math.max(1, bg.getIntrinsicHeight());
int width = Math.max(1, bg.getIntrinsicWidth());
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
bg.setBounds(0, 0, width, height);
bg.draw(canvas);
long sum = 0;
for (int x=0; x<width; x++){
for (int y=0; y<height; y++){
int color = bitmap.getPixel(x, y);
int r = (color >> 16) & 0xFF;
int g = (color >> 8) & 0xFF;
int b = (color) & 0xFF;
int max = Math.max(r, Math.max(g, b));
int min = Math.min(r, Math.min(g, b));
int l = (min + max)/2;
sum = sum + l;
}
}
bitmap.recycle();
bitmap = null;
canvas = null;
bg = null;
sum = sum / (width * height);
// should be [0..255]
return (int)Math.min(255, Math.max(sum, 0));
}

Usually you are suppose to bind this via the manifest file but there is a way to get the value:
Use the Build.VERSION.SDK_INT and check it against the Build.VERSION_CODES,
http://developer.android.com/reference/android/os/Build.VERSION.html
you can get the more interesting read from an android dev blog post here
--edit--
You will have to figure out what device you are on from BUILD but don't forget people have themes as well...
Short of ripping up the framework and the status bar app, that is going to be the best... here is a link if you want to try digging into the StatusBar and getting it from the raw Framework.jar...
Here is a link to a guy who mentions how he handled playing with the status bar.

With adb (you'll find in android development kit) with "pull" command, or just a root file manager, you need to access /system/framework/framework-res.apk. Decompress, it's like zip use(!) apktool. Inside, you'll find the bitmaps of the graphics. Select the ones, containing "statusbar", you just look at them, and you'll see if you want to mass with it, or not.
The tricky part is to get them back, for what you'll need to recompress it, with apktool. The bitmaps have an extra line, with info on streching them. Apktool gets rid of those, or better put, just hides them.
The really hard part is, where you change the clock, and notification colors, from white to black, and for that you'll need to modify classes.dex, whitch part I was stuck.
The easy method is to download and install CyanogenMod, it lets you access these parameters.
Cheers.

Related

How to detect emoji support on Android by code

By code, I can make a button that inserts these 3 emojis into the text: ⚽️😈🐺
On many phones when the user clicks the button, though, the problem is that ⚽️😈🐺 displays as [X][X][X]. Or even worse, it displays only three empty spaces.
I would like to disable and hide my own built-in emoji-keypad on Android devices that do not display emojis correctly. Does anyone knows or have a tip on how to detect in code if a device has emoji support?
I have read that emoji is supported from android 4.1, but that is not my experience....
I just implemented a solution for this problem myself. The nice thing with Android is that it is open source so that when you come around problems like these, there's a good chance you can find an approach to help you.
In the Android Open Source Project, you can find a method where they use Paint.hasGlyph to detect whether a font exists for a given emoji. However, as this method is not available before API 23, they also do test renders and compare the result against the width of 'tofu' (the [x] character you mention in your post.)
There are some other failings with this approach, but it should be enough to get you started.
Google source:
https://android.googlesource.com/platform/packages/inputmethods/LatinIME/+/master/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java#441
https://android.googlesource.com/platform/packages/inputmethods/LatinIME/+/master/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
Based on Jason Gore answer:
For example create boolean canShowFlagEmoji:
private static boolean canShowFlagEmoji() {
Paint paint = new Paint();
String switzerland = "\uD83C\uDDE8\uD83C\uDDED"; // Here enter Surrogates of Emoji
try {
return paint.hasGlyph(switzerland);
} catch (NoSuchMethodError e) {
// Compare display width of single-codepoint emoji to width of flag emoji to determine
// whether flag is rendered as single glyph or two adjacent regional indicator symbols.
float flagWidth = paint.measureText(switzerland);
float standardWidth = paint.measureText("\uD83D\uDC27"); // U+1F427 Penguin
return flagWidth < standardWidth * 1.25;
// This assumes that a valid glyph for the flag emoji must be less than 1.25 times
// the width of the penguin.
}
}
And then in code whenever when you need to check if emoji is available:
if (canShowFlagEmoji()){
// Code when FlagEmoji is available
} else {
// And when not
}
Surrogates of emoji you can get here, when you click on detail.
An alternative option might be to include the Android "Emoji Compatibility" library, which would detect and add any required Emoji characters to apps running on Android 4.4 (API 19) and later: https://developer.android.com/topic/libraries/support-library/preview/emoji-compat.html
final Paint paint = new Paint();
final boolean isEmojiRendered;
if (VERSION.SDK_INT >= VERSION_CODES.M) {
isEmojiRendered = paint.hasGlyph(emoji);
}
else{
isEmojiRendered = paint.measureText(emoji) > 7;
}
The width > 7 part is particularly hacky, I would expect the value to be 0.0 for non-renderable emoji, but across a few devices, I found that the value actually ranged around 3.0 to 6.0 for non-renderable, and 12.0 to 15.0 for renderable. Your results may vary so you might want to test that. I believe the font size also has an effect on the output of measureText() so keep that in mind.
The second part was answerd by RogueBaneling here how can I check if my device is capable to render Emoji images correctly?

How to Get the CORRECT Pixel Colour

I would also like to read out the colour of the pixels from an 'Image'. I've read a lot of topics here about this but the success is still missing.
So after a lot of unwanted values, I tried to simplify my code and the Image as well. I tried with the following:
//..
Android.Graphics.BitmapFactory.Options op = new BitmapFactory.Options();
op.InPreferredConfig = Bitmap.Config.Argb8888;
Bitmap b = Android.Graphics.BitmapFactory.DecodeResource(this.Resources, Resource.Drawable.Image, op);
//imageView.SetImageBitmap(b);
int pixel1 = b.GetPixel(3, 4);
int pixel2 = b.GetPixel(12, 11);
int pixel3 = b.GetPixel(19, 20);
int pixel4 = b.GetPixel(27, 28);
int pixel5 = b.GetPixel(27, 19);
int pixel6 = b.GetPixel(20, 11);
int redV1 = Android.Graphics.Color.GetRedComponent(pixel1);
int greenV1 = Android.Graphics.Color.GetGreenComponent(pixel1);
int blueV1 = Android.Graphics.Color.GetBlueComponent(pixel1);
int redV2 = Android.Graphics.Color.GetRedComponent(pixel2);
int greenV2 = Android.Graphics.Color.GetGreenComponent(pixel2);
int blueV2 = Android.Graphics.Color.GetBlueComponent(pixel2);
//..
Surprisingly I got the results as follows:
pixel1 color is OK.
pixel2 color is NOT OK its pixel1 color.
pixel3 color is NOT OK its pixel2 color.
pixel4 color is NOT OK its pixel2 color.
pixel5 color is NOT OK its pixel2 color.
pixel6 color is NOT OK its existing color in my Image but on different coordinates. (it was not mentioned in my code)
Presentation of the .png Image in an imageView seems to be smooth.
Could anyone help with my fault?
THX!
pixel1..6 values seems to be correct (different on different colours and equal on the same) and they would be enough for me but all the values became -1 after I start to work with my real .png file (1500x1500 image as a resource). Is that too large to work with? What is the maximum in this case? Thx!
... Ok, perhaps I got the fault. To be precise, not the fault but a usable solution! Now I'm trying with a smaller .png Image sized 500x500. It is small enough to work with.
BUT: It seems the BitmapFactory creates a larger image (1000 x 1000). So I have to divide each coordinate with 2 if I want to check the correct colour on my original image. AND there is another problem: Some colours may be different read by the Getpixel(). It can be small differences in R,G,B values. In example: RGB(148,0,198) instead of (153,0,204). It means a 'bit' extra work for me to identify all the new 'Android colours' on my bitmap :( I hope, I could help for the others with this topic. It wasn't easy to find one bug/problem after another.

how can I check if my device is capable to render Emoji images correctly?

I'm using Emoji unicode in a View. On most devices the images appear ok, but on one of my low-end device(android 2.3) they are rendered as little squares.
Can I check whether the device support emoji? So that I can publish my apk while won't show that ugly squares on some devices.
This is a late answer but I recently ran into a similar problem. I needed to filter through a List<String> and filter out emojis that couldn't be rendered on the device (i.e., if the device was old and didn't support rendering them).
What I ended up doing was using Paint to measure the text width.
Paint mPaint = new Paint();
private boolean emojiRenderable(String emoji) {
float width = mPaint.measureText(emoji);
if (width > 7) return true;
return false;
}
The width > 7 part is particularly hacky, I would expect the value to be 0.0 for non-renderable emoji, but across a few devices, I found that the value actually ranged around 3.0 to 6.0 for non-renderable, and 12.0 to 15.0 for renderable. Your results may vary so you might want to test that. I believe the font size also has an effect on the output of measureText() so keep that in mind.
Overall I am not sure if this is a great solution but it's the best that I've come up with so far.
please check the source code from Googles Mozc project.
The EmojiRenderableChecker class seems to work pretty well!
https://github.com/google/mozc/blob/master/src/android/src/com/google/android/inputmethod/japanese/emoji/EmojiRenderableChecker.java
it's like a compat version for Paint.hasGlypgh (added in Marshmallow).
https://developer.android.com/reference/android/graphics/Paint.html#hasGlyph(java.lang.String)
https://android.googlesource.com/platform/packages/inputmethods/LatinIME/+/master/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java#441
Inspired from the two methods found in the above file.
public static boolean canShowEmoji(String emoji) {
Paint paint = new Paint();
float tofuWidth = paint.measureText("\uFFFE");
float standardWidth = paint.measureText("\uD83D\uDC27");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return paint.hasGlyph(emoji);
} else {
float emojiWidth = paint.measureText(emoji);
return emojiWidth > tofuWidth && emojiWidth < standardWidth * 1.25;
// This assumes that a valid glyph for the cheese wedge must be greater than the width
// of the noncharacter.
}
}

Qt Android. Get device screen resolution

I'm developing in qt 5.3 on android device. I can't get the screen resolution.
With the old qt 5 version this code worked:
QScreen *screen = QApplication::screens().at(0);
largh=screen->availableGeometry().width();
alt =screen->availableGeometry().height();
However now it doesn't work (returns a screen size 00x00). Is there another way to do it? thanks
Size holds the pixel resolution
screen->size().width()
screen->size().height();
Whereas, availableSize holds the size excluding window manager reserved areas...
screen->availableSize().width()
screen->availableSize().height();
More info on the QScreen class.
for more information, screen availableSize is not ready at the very beginning, so you have to wait for it, here is the code:
Widget::Widget(QWidget *parent){
...
QScreen *screen = QApplication::screens().at(0);
connect(screen, SIGNAL(virtualGeometryChanged(QRect)), this,SLOT(getScreen(QRect)));
}
void Widget::getScreen(QRect rect)
{
int screenY = screen->availableSize().height();
int screenX = screen->availableSize().width();
this->setGeometry(0,0,screenX,screenY);
}
I found that there are several ways to obtain the device resolution, each outputs the same results and thankfully works across all Os-es supported by Qt...
1) My favorite is to write a static function using QDesktopWidget in a reference class and use it all across the code:
QRect const CGenericWidget::getScreenSize()
{
//Note: one might implement caching of the value to optimize processing speed. This however will result in erros if screen resolution is resized during execution
QDesktopWidget scr;
return scr.availableGeometry(scr.primaryScreen());
}
Then you can just call across your code the function like this:
qDebug() << CGenericWidget::getScreenSize();
It will return you a QRect const object that you can use to obtain the screen size without the top and bottom bars.
2) Another way to obtain the screen resolution that works just fine if your app is full screen is:
QWidget *activeWindow = QApplication::activeWindow();
m_sw = activeWindow->width();
m_sh = activeWindow->height();
3) And of course you have the option that Zeus recommended:
QScreen *screen = QApplication::screens().at(0);
largh=screen->availableSize().width();
alt =screen->availableSize().height();

How do you get the selection color in Android?

I need to get the selection color used by Android to draw ListView and EditText selection. I know these controls user selectors to draw their states, but I've written a few widgets that I want to match the selection color of the platform they are running on and the drawables that are defined can't do that because they are using 9 patch images instead of colors.
I've looked all through the Android source and haven't found a color selector or color constant I can use to get the color I'm looking for.
You could try this :
android:background="?android:attr/selectableItemBackground"
you can get all the resource from here
android-sdk-windows\platforms\android-<Desire API Level>\data\res\drawable-hdpi.
or you can use directly like this
android:background="#android:drawable/list_selector_background"
or like this also
Drawable d = getResources().getDrawable(android.R.drawable.list_selector_background);
Take a look at this answer. You can browse through the platform colors and styles at the Android github mirror. Please note this values can be different for every version of Android. If you want to use platform styles, just don't create your own custom selectors for the controls. Hope it will help.
You could just get the list_selector_background drawable, as explained by Jignesh, and then find its average color as shown in this answer (I'd do it in your initialization code so you don't have to waste processing them every time, but hey, that's premature optimization). That should be consistent enough with the theme to let your widgets match as needed.
Your code could look like this:
public static Color getPlatformSelectionColor(Context c) {
Bitmap bitmap = BitmapFactory.decodeResource(c.getResources(),
android.R.drawable.list_selector_background);
long redBucket = 0;
long greenBucket = 0;
long blueBucket = 0;
long pixelCount = 0;
for (int y = 0; y < bitmap.getHeight(); y++)
{
for (int x = 0; x < bitmap.getWidth(); x++)
{
Color c = bitmap.getPixel(x, y);
pixelCount++;
redBucket += Color.red(c);
greenBucket += Color.green(c);
blueBucket += Color.blue(c);
// does alpha matter?
}
}
Color averageColor = Color.rgb(redBucket / pixelCount,
greenBucket / pixelCount,
blueBucket / pixelCount);
return averageColor;
}
You can achieve easily achieve this for google owned devices but not for other manufacturers as most of the manufacturers have overridden the default colors, layouts, backgrounds, etc for almost all the versions of android including jelly-beans.
So ideally its not recommended and also tough to follow each and everyone's design guidelines.

Categories

Resources