Can I somehow detect if my app is running on HTC Sense?
More generally, the problem is, that I have a Button with custom drawable. It's something very similar to the account switcher in the top right of Gmail app. When pressed or focused, the button has orange highlight. But that doesn't look nice on HTC Sense - because the standard highlight color there is green.
Lets see android.os.Build strings I am not sure what the HTC folks use a combination to indicate a HTC sense device..
Here's a link suggesting a way to detect HTC Sense on the device, about 1/3 the way down the discussion. I've tested on Desire and Desire Z.
Code is below (from a user: David):
private static final String SENSE_UI_LAUNCHER_NAME =
"com.htc.launcher.Launcher";
private static Boolean senseUI;
public static final boolean isSenseUI(Context context) {
if (senseUI == null) {
senseUI = false;
PackageManager packageManager = context.getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
List<ResolveInfo> list = packageManager.queryIntentActivities(
intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo info : list) {
if (info.activityInfo != null
&& SENSE_UI_LAUNCHER_NAME
.equals(info.activityInfo.name)) {
senseUI = true;
break;
}
}
}
return senseUI;
}
I think that Android has provided a better way for you to solve this than doing a check for Sense, and it will work for every device manufacturer. HTC isn't the only one who has changed the colors on the selectors. I think Sony Ericsson has a transparent white/blue, Motorola changed it to red in their MotoBlur UI, and Garmin-Asus changed it to blue in theirs just to name a few.
What you should do is override the android:background attribute on your image button and use a drawable of your own instead of relying on the framework's background
drawable. If you're not already familiar with them, you'll probably also want to take a look at Selectors when you create your custom background, so you still get the pressed/selected/not-selected color cues.
If you have multiple buttons that you want to do this on, you may want to use styles and themes to help out with this. The two primary places you'll want to reference from the Android documentation are "Applying Styles and Themes" and "Style Resources"
Hope that helps!
I think the following approach should be followed - we define android:background, something like
<?xml version="1.0" encoding="UTF-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/pressed_application_background" />
<item android:state_focused="true" android:state_window_focused="true" android:drawable="#drawable/focused_application_background" />
<item android:state_focused="true" android:state_window_focused="false" android:drawable="#android:color/transparent" />
</selector>
But here we should refer to some standard resources, not to the images of our application. Just need to find out which ids they have.
This is a bit late, but I think this solution might work on some people cases.
I tried to use Build.MANUFACTURER to check if it is a HTC device. This solution doesnt work on some devices and we can ensure that that devices is running Sense anyway
If you notice, you may see Play Store needs to check what features available on the phone to display correct apps, and HTC Sense is one of the features!
To get all available features:
public FeatureInfo[] getSystemAvailableFeatures(Context context) {
FeatureInfo[] features = context.getPackageManager().getSystemAvailableFeatures();
for (FeatureInfo f : features) {
Log.d("Features", "feature " + f.name);
}
return features;
}
This will return something like these:
com.example D/Features﹕ Feature android.hardware.wifi
com.example D/Features﹕ Feature android.hardware.location.network
com.example D/Features﹕ Feature com.sec.android.mdm
com.example D/Features﹕ Feature android.hardware.location
com.example D/Features﹕ Feature android.hardware.sensor.gyroscope
com.example D/Features﹕ Feature android.hardware.screen.landscape
com.example D/Features﹕ Feature com.htc.software.Sense5.0
Notice the last line! You can use it to check HTC sense version
Hope it helps
Related
So, my boss asked me to analyze how to implement Material You colors starting from Android 12. I've been researching for it and every blog of every page about "how to do it" tells you that, you need to hold down at home screen, then go to "Wallpapers & Style" and change your wallpaper. There is an issue, though.
I remember that while Android 12 was in Beta, it was supporting Material You colors. However (I assume) after the official release, this support has been removed, because I am unable to find the option. Here is what it looks like when I hold down while at home screen:
It says "Wallpapers" and when I click on it, it does not open a menu called Wallpaper & style, it just redirects to Live Wallpapers. I've unable to find the wallpaper colors option on the official Android 12 release. However, it is present on the upcoming API 32 (Android 13 I believe) emulator.
Upon researching a little bit, I've found out that the system generates the wallpaper colors under the system resources such as system_accent1_600 etc. which are available starting from API 31 (more info here). This does work when I use an API 32 emulator which is in beta, but it defaults to something else (a shade of blue on accent colors, and shades of gray on neutral, a.k.a background colors) that I haven't figured out where from on an API 31 official emulator.
Here is the question:
Is Material You colors officially supported starting from Android 12 (API 31)? If yes, then why am I not able to find it on Android's official emulator?
Also, is it possible to detect if the device supports Material You colors with different options?
I think this is what you are looking for:
public static boolean isDynamicColorAvailable()
{
return VERSION.SDK_INT >= VERSION_CODES.S && DYNAMIC_COLOR_SUPPORTED_MANUFACTURERS.contains(Build.MANUFACTURER.toLowerCase());
}
Found this in DynamicColors class in com.google.android.material.color
You can simply call it like this:
boolean isdca = DynamicColors.isDynamicColorAvailable();
I hope this answers the last part.
1. Is Material You colors officially supported starting from Android 12 (API 31)?
Yes! But it based how the ROM implements. If you using Pixel, the you can change the color via the built wallpaper app. But if you're using AOSP, sine there is not an official way in UI to user to change it.
Check out this doc: https://gist.github.com/zhaofengli/232f5a3d33113871ad61491629886084
2. If yes, then why am I not able to find it on Android's official emulator?
It looks like Google removed it from the mirror. The previous mirror had this feature.
3. Also, is it possible to detect if the device supports Material You colors?
Since Android 12 supports Material You officially, so you can just check the api version simply.
But, according to the second point, some systems still don't support it, so you can use the method com.google.android.material.color.DynamicColors#isDynamicColorAvailable. This is the definitive method used by Material Design, depending on the SDK version and phone manufacturer.
https://cs.github.com/material-components/material-components-android/blob/2ae3ca42985722900f53de9d9a1ef61c143767eb/lib/java/com/google/android/material/color/DynamicColors.java#L279-L289
4. What is the correct way to implement Material You?
XML way: Follow the official doc: https://m3.material.io/libraries/mdc-android/color-theming
Programmatically way:
Check out my app's code:
val Context.colorOnPrimary: Int
get() {
return when {
DynamicColors.isDynamicColorAvailable() -> {
getColorFromAttr(R.attr.colorOnPrimary)
}
isNight() || !supportNight() -> {
ContextCompat.getColor(this, R.color.md_theme_dark_onPrimary)
}
else -> {
ContextCompat.getColor(this, R.color.md_theme_light_onPrimary)
}
}
}
#ColorInt
fun Context.getColorFromAttr(
#AttrRes attrColor: Int,
typedValue: TypedValue = TypedValue(),
resolveRefs: Boolean = true
): Int {
theme.resolveAttribute(attrColor, typedValue, resolveRefs)
return typedValue.data
}
I was thinking if there is a way to add an item in Quick Settings Panel in android ?
I have an app called Mirror by Koushik Dutta that does the same. It adds an item in Quick Settings panel. I decompiled the app and saw that he's moving the apk to /system/priv-app .
That's it. Nothing's related to adding an item in Quick Settings Toggle.
I know it'll require root access (just a college project). Please if anyone has any idea how it can be done, it would be really helpful.
Use the Android N tile API
Custom quick settings can be created in Android N using the tile API. Just make a class that inherits from TileService and add it to the manifest.
Here's the example given in the TileService documentation:
<service
android:name=".MyQSTileService"
android:label="#string/my_default_tile_label"
android:icon="#drawable/my_default_icon_label"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
Recent versions of CyanogenMod 12.1 support this through the CyanogenMod Platform SDK:
public void publishTile() {
if (supportsCustomTiles()) {
Intent receiver = new Intent(context, TileClickedReceiver.class);
PendingIntent clickIntent = PendingIntent.getBroadcast(
context,
0,
receiver,
PendingIntent.FLAG_CANCEL_CURRENT
);
CustomTile tile = new CustomTile.Builder(context)
.setIcon(R.drawable.tile_icon)
.setLabel("Test Tile")
.setOnClickIntent(clickIntent)
.build();
CMStatusBarManager
.getInstance(context)
.publishTile(1234, tile);
}
}
private boolean supportsCustomTiles() {
try {
Class.forName("cyanogenmod.app.CustomTile");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
The quick settings tiles in Android 4.4 are all hardcoded.
Here's a link to the source.
Even with root, the only way to change this would be patching system jars/apks.
The support for Mirror might be added by Cyanogenmod, have you tried if it works on any other ROM?
Edit: Here's a feature request for a quick settings api: https://code.google.com/p/android/issues/detail?id=42616
Koushik Dutta didn't add a new quick settings tile. The "Cast Screen"-Tile is implemented by the android system and appears sometimes. It's a shortcut to the "cast screen"-menu in system settings. Koush added new options for this menu (i don't know if there's an open api or if he needs the root permission for that) and now, the tile is always displayed because there's always content.
To answer your question: No, without system modifications with root, you can't add tiles to the android quick settings. (Edit: I haven't read that you'd also use root. So, you can't add tiles easily and the mirror application by Koushik Dutta doesn't do that, too.)
PS: It isn't because of CyanogenMod, because I use stock android and the app works, too.
Update 2019-08-08: With Android N, there's an official API to add custom quick setting tiles (see Sam's answer).
I am developing an app that targets for tablets only not for phones.
Is this code is enough to acheive my goal? Is there any way to test it or google play sorts it's by itself and present to users?
Below is the code I have tried. But I don't know how to test it?
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="18" />
<supports-screens
android:largeScreens="true"
android:normalScreens="false"
android:smallScreens="false"
android:requiresSmallestWidthDp="600"
android:xlargeScreens="true" />
Is android:anyDensity="true" should be given along with support screen tag? Or just leave that attribute. I want to work my application on all range of tablets.
Any help in this case is highly appreciable. Thanks in advance.
Seems oke, should work as far as I know.
Think about what you define as a tablet. What makes your app less suitable for a 6" phone, than for a 7" tablet?
You can't really test this until you upload it in the Google play Store. These filters in the manifest.xml are used by the Google Play Store, not actually when installing an app. They just make sure somebody doesn't find the app on his tablet and the install button won't work on the website.
You could test it by just uploading your APK but not publishing I think. It will give you a list of devices that are supported with the current settings.
whatever you given that is correct u have to test it on tablets it will load and for mobile phones it will not launch.
and go into the android market publisher page.
1.Make sure your app is uploaded.
2.Click on your app name.
3.Scroll down to where it says 'Show devices'.
4.Click that and you can exclude all mobile phones from downloading your app.
Failing that you can set some parameters in your manifest for screen size etc, but this is less reliable.
You can use a trick here...
1) Create an startup activity, which only verifies screen size in its on create an starts actual activity in success scenario. like,
// In onCreate of startup activity
if (isTablet()) {
startActivity(new Intent(StartupActivity.this, MainActivity.class));
this.finish(); // don't forget to kill startup activity after starting main activity.
} else {
setContentView(R.layout.startup);
}
This is the critical point. In else case you should set layout to this activity which ideally can have a label with you message like "Device not supported." and a button to close application.
2) Ideally, you should place all your string resources in res/values-large/strings.xml if you want to support only tablets. So here is the trick, Just add following item in your string resources...
<string name="is_supported_screen">true</string>
And now create a new string resource file at res/values/strings.xml which will contain the same string item but with false value like...
<string name="is_supported_screen">false</string>
NOTE: make sure this string resource file must contain atleast all the resources used in StarupActivity e.g. activity title, device not supported message, close app button text etc.
3) Finally write a method in your StartupActivity like,
private boolean isTablet() {
if (Boolean.parseBoolean(context.getResources().getString(R.string.is_supported_screen))) {
return true;
} else {
return false;
}
}
And its done...:)
Actually what happens here is, for devices with large screens like tablets, will load string resource from res/values-large/strings.xml and will found true and in the case of other device, android will load resources from res/values/strings.xml and it will found false int the method isTablet() for value of R.string.is_supported_screen.
And finally, Your main activity will be started if app is installed in tablet and will show message of device not supported will be displayed.
I would like to emphasize that this is a trick, so you need to follow all the steps carefully. Any mistake and you will not get desired results.
i wrote a custom syncadapter, which also added a custom field to the rawcontacts. Exactly how it is done in the SampleSyncAdapter or in this example with the last.fm-App. And it is working fine on the emulator.
The xml-file, which declares my custom field:
<ContactsSource xmlns:android="http://schemas.android.com/apk/res/android">
<ContactsDataKind
android:mimeType="vnd.com.google.cursor.item/vnd.alien.mimetype"
android:icon="#drawable/icon"
android:summaryColumn="data2"
android:detailColumn="data3"
android:detailSocialSummary="true" />
</ContactsSource>
The code to add the custom field to the data-table of the contactscontract-provider:
mContentUri = Data.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
Builder mID = ContentProviderOperation.newInsert(mContentUri)
.withValue(Data.RAW_CONTACT_ID, getRawContactId())
.withValue(Data.MIMETYPE, "vnd.com.google.cursor.item/vnd.alien.mimetype")
.withValue(Data.DATA1, mContactInformations.get("mID"))
.withValue(Data.DATA2, mContext.getString(R.string.profile_text))
.withValue(Data.DATA3, mContext.getString(R.string.profile_id)+" "+mContactInformations.get("mID"));
But when I run them on my HTC Desire with HTC Sense installed, I can't see this custom field anymore?!? Has anyone experienced the same problem?
Any hint to get my custom field visible is highly appreciated!
Cheers Ali3n
The default contact viewers do not show custom fields.
There are some 3rd party apps that do show custom fields, a free one (but ad supported) is here
Unfortunately I did not found a real solution for that. But two things reduce the problem:
This problem did only appear on my old HTC Desire. On my sisters HTC Sensation the custom-field shows up as expected (nice fail from HTC in the first try oO)
Even better is, that the intent that would be started via this custom-field also shows up in the QuickContactBadge, which is used by the native HTC Contacts-App even on my HTC Desires Sense. Therefore the user can invoke my activity via the QuickContactBadge on old Senses versions and in new versions he also has the ability to use the custom-field.
I'm currently working on an app to display the battery status and I'd like to use Android-drawables instead of own images to reduce the app size.
I've found this page which lists available images and the availability for each SDK-version:http://www.fixedd.com/projects/android_drawables_display
My question: How can I access the "system"-drawables? If you click on the link and choose the tab "Status", there are some battery-drawables like "stat_sys_battery_0", but I can't access it, Eclipse doesn't offer intellisense for it and won't compile the app if I use one of those drawables.
As those drawables are part of all SDK-versions, I'd think I should be able to use them, or are those "special" drawables protected in a way so they can only be used by system-functions (and not apps)?
Any idea is appreciated.
Select0r
Hope this is what you were looking for:
private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context arg0, Intent intent) {
int level = intent.getIntExtra("level", 0);
int batteryIconId = intent.getIntExtra("icon-small", 0);
Button toolBarBattery = (Button) findViewById(R.id.toolBarButton);
LevelListDrawable batteryLevel = (LevelListDrawable) getResources().getDrawable(batteryIconId);
batteryLevel.setLevel(level);
toolBarBattery.setBackgroundDrawable(batteryLevel);
}
};
I've found another link with information that not all drawables are public. It doesn't say why some drawables would be private, but I guess I'll have to live with the fact and copy the needed images to my app.http://androiddrawableexplorer.appspot.com/
NOTE: Some of the images in the Android jar are not public and therefore cannot be directly used (you can copy them to you own application, but can't reference them via the "android" package namespace).
There actually seems to be a way to access the system icons, but it's not really working as stated in the documentation, but I'll add it in case somebody is interested:
intent.getIntExtra(BatteryManager.EXTRA_ICON_SMALL, -1)
Will get you the resource-ID of the icon that matches the current battery-status:http://developer.android.com/reference/android/os/BatteryManager.html#EXTRA_ICON_SMALL
Extra for ACTION_BATTERY_CHANGED:
integer containing the resource ID of
a small status bar icon indicating the
current battery state.
However, it always returns the same icon, no matter what the actual battery level is. Finding the icon by just trying random numbers may work, but I don't know if the IDs are consistent throughout the SKD-levels as well as different machines, so I'd rather not rely in that.