7

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:

image

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?

Furkan Yurdakul
  • 2,801
  • 1
  • 15
  • 37

2 Answers2

3

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.

Sujal Kumar
  • 1,054
  • 10
  • 23
  • Please let me know if running this on your emulator is returning "true" or "false". – Sujal Kumar Jan 05 '22 at 06:28
  • yes this does return true on api 31 but the problem still remains as only a default blue color is applied regardless of the wallpaper. – DrHowdyDoo Jan 05 '22 at 10:08
  • Did you try adding "DynamicColors.applyToActivitiesIfAvailable(this);" in Application class' onCreate() ? – Sujal Kumar Jan 05 '22 at 10:39
  • Also, which theme are you using? What are the pre-defined colors in styles? – Sujal Kumar Jan 05 '22 at 10:40
  • 1
    i have a single activity so i used `DynamicColors.applyIfAvailable(this)` and it is applying a blue color . i am using `Theme.Material3.DayNight.NoActionBar` – DrHowdyDoo Jan 05 '22 at 11:29
  • i used material theme builder to create a theme – DrHowdyDoo Jan 05 '22 at 11:30
  • Strange. I just tried calling the isDynamicColorAvailable() in Android 12 Emulator and it's returning false! Then I tried toasting the Manufacturer name and it is showing "unknown". Maybe this is the reason when applyIfAvailable() is not working. – Sujal Kumar Jan 05 '22 at 12:00
  • @SujalKumar That method returns true on the API 31 emulator unfortunately, while not showing the options in the beta version. I've already checked this but probably did not add it in the question itself. As DrHowdyDoo said, the usage applies a default blue color. – Furkan Yurdakul Jan 05 '22 at 14:37
  • Ok, I tried making a helper class and literally copied the DynamicColors class doing changes where necessary and was able to get to that default Blue at most :( – Sujal Kumar Jan 05 '22 at 15:44
  • You are right, these emulators don't have those "Material You" features yet. We can only hope for an update or the last option is to test on a physical device with Android 12+ – Sujal Kumar Jan 05 '22 at 15:46
2

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?

  1. XML way: Follow the official doc: https://m3.material.io/libraries/mdc-android/color-theming
  2. 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
}

rosuh
  • 428
  • 4
  • 10
  • 1
    Thanks for the info on 1st, 2nd and 4th questions, but on the 3rd one I forgot to ask something extra, I meant if it is possible to detect the Material You support with different options enabled, a.k.a with wallpaper colors or with basic colors. Edited the question accordingly. – Furkan Yurdakul Jan 06 '22 at 11:30
  • 1
    @FurkanYurdakul I think you don't need to check if is "wallpaper colors or basic colors". In my opinion, Android 12 native supports setting color for the whole system. That is wallpaper's job or some custom ROM feature. For app developer, we just use the color of system. The wallpaper's behavior should be transparent to our app :) – rosuh Jan 06 '22 at 11:42
  • Is this piece of code equivalent to DynamicColors.applyifavailable()? – Sujal Kumar Jan 06 '22 at 12:32
  • Or we need to do it explicitly like this just for customization according to the taste? – Sujal Kumar Jan 06 '22 at 12:35
  • 1
    @SujalKumar The `DynamicColors.applyifavailable()` can apply dynamic color for specify activity but it only apply for official MD components in xml. If you have some custom views it would not apply to your custom views automatically. That is why using the No.4 solution to get dynamic color programmatically. – rosuh Jan 07 '22 at 02:48
  • Unfortunately that is exactly the case. I need to implement this into an app and they only want to change the colors if the device supports different colors based on wallpaper, specifically. As a developer, I can't really tell them that there is a system color, but no wallpaper colors. If there is only a system color, they want to keep the original design. So, I need to check that I'm afraid. They want me to look for a solution for this. – Furkan Yurdakul Jan 07 '22 at 06:19
  • @FurkanYurdakul It looks like you can only use the method `com.google.android.material.color.DynamicColors#isDynamicColorAvailable`. This is the determination method used by Material Design, which depends on the SDK version and the manufacturer of the phone. – rosuh Jan 08 '22 at 01:50
  • Exactly my answer xD – Sujal Kumar Jan 08 '22 at 05:32
  • That looks like the only possible way as of now. I don't think there's a way to check exactly if the device will use the default blue or not. – Sujal Kumar Jan 08 '22 at 05:34