Possible to make accessibility announcement on Android independent of UI control? - android

On Xamarin iOS, it is possible to make a VoiceOver announcement for example when a background operation has completed, see here. This announcement is not dependent on the appearance of any UI control.
On Xamarin Android on the other hand, the accessibility developer documentation only gives an example where the TalkBack announcement is enforced for a specific UI control, see here.
As an attempted workaround I programmatically created a simple UI control ctl and called ctl.AnnounceForAccessibility("My announcement") but no announcement could be heard. Presumably because the control is not in the visual tree?
Is there any way to make a TalkBack announcement on Android without the involvement of a (visible) UI control?

With inspiration from this StackOverflow answer, I implemented the following workable solution:
var manager = (AccessibilityManager)Application.Context.GetSystemService(Context.AccessibilityService);
var accessibilityEvent = AccessibilityEvent.Obtain(EventTypes.Announcement);
if (manager != null && accessibilityEvent?.Text != null)
{
accessibilityEvent.Text.Clear();
accessibilityEvent.Text.Add(new Java.Lang.String(myDotNetString));
manager.SendAccessibilityEvent(accessibilityEvent);
}

Related

Detect if Material You is present in device

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
}

How to check accessibility enabled or disabled and then change the view accordingly in android?

I am working on android application development. We need to do some changes as per accessibility guidelines i.e our app should support accessibility guidelines also. So my question is how we will make the code change as per the Accessibility guidelines.
For example: In my Login screen, as per the accessibility guideline, the textview should be 48dp in size. But this change should happen only when the user enables accessibility in the device. Otherwise, the default size of the textview should be 40dp. How to achieve this in my app? Could anyone please help me on this. Thanks in advance.
This is an extension function that checks if a particular AccessibiltyService is running
fun Context.isAccessibilityServiceRunning(): Boolean {
val accessibilityManager =
getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
return accessibilityManager
.getEnabledAccessibilityServiceList(AccessibilityEvent.TYPES_ALL_MASK)
.map { it.id }
.contains(ACCESSIBILITY_SERVICE_ID)
}
There are various accessibility services. If you were checking for any of them to be running you could just check to see if the service list is no empty.
I don't see any accessibility resource qualifiers here:
https://developer.android.com/guide/topics/resources/providing-resources#AlternativeResources
Because of that you will probably need to programmatically change the size or create a style that you apply.

How to listen to taps and get views using Accessibility in Android?

I want to implement an Accessibility service in my Android app which can do the following things:
=>Get the onscreen taps/clicks across any apps.
=>Get the view which was tapped/clicked.
Initially I thought it would not be possible to do so because of security reasons but while doing some research I came across an app (Native clipboard) which could do following things:
=>Detect taps on EditTexts from any app
=>Add value (string) to those EditTexts.
I also saw Google's talkback which speaks whatever you tap on. For it to speak, it needs to access the view (to get the text) across apps.
These apps obviously makes use of 'Accessibility services' to do so, but I would like to know how can I implement that?
I mostly find tutorials or stuffs for things I need to achieve but I am struggling finding some for implementing Accessibility service for my app. I did visit the Android official documentation which is too technical for a newbie like me. (I initially prefer to learn from Youtube, SO and tutorial websites). It will also be great if you can pin point me to some other tutorials which covers these things.
Accessibility services are pretty poorly documented, but I have created some accessibility service boilerplate code, that sets up a starter project and logs the base callbacks. Here is a bit of code that I think you care about given your specific questions. The scaffolding, project set up and such I leave for the repo.
Below is the onAccessibilityEvent callback. This is where you will listen for different types of a events, and the most convenient place to grab onto screen content for most scenarios. Though, as an accessibility service you also don't have to wait for events. You could just as easily spawn an AsynTask and grab on to it on an interval of some kind.
public void onAccessibilityEvent(AccessibilityEvent event) {
CLog.d(event.toString());
switch (event.getEventType()) {
//On Gesture events print out the entire view heirarchy!
case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
CLog.d(A11yNodeInfo.wrap(getRootInActiveWindow()).toViewHeirarchy());
case AccessibilityEvent.TYPE_VIEW_CLICKED:
CLog.d(event.getSource().toString());
default: {
//The event has different types, for you, you want to look for "action clicked"
if (event.getSource() != null) {
CLog.d(A11yNodeInfo.wrap(event.getSource()).toViewHeirarchy());
}
}
}
}
I will point out one bit of configuration for this, because it is super important. Accessibility services are best configured through an XML file connected to your service through the Manifest file. The contents of this file are:
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:description="#string/accessibility_service_description"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFlags="flagReportViewIds"
android:canRetrieveWindowContent="true"
android:canRequestTouchExplorationMode="true"
android:accessibilityFeedbackType="feedbackSpoken"
android:notificationTimeout="100"
android:settingsActivity="com.moba11y.basicaccessibilityservice.SettingsActivity"
/>
For you the important bits are canRetrieveWindowContent="true" and accessibilityEventTypes="typeAllMask". A design bit I like, is ensuring that your grabbing onto the minimal set of event types you want. Different Accessibility Events report broadly different results. For example, many events return "null" from getSource(). This forces you to add a lot of filters for this, or risk null pointer exceptions. It's quite annoying.
The last bit you need is Accessibility Actions. This is what allows you to simulate clicks, long clicks AND add text to an editable text view. Below is code that allows you to do this.
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo source = event.getSource();
if (source != null & event.getClassName().equals("android.widget.EditText")) {
Bundle arguments = new Bundle();
arguments.putCharSequence(
AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,"some value");
source.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
}
}
https://github.com/chriscm2006/Android-Accessibility-Service-Boilerplate

Activity Background change dynamic

I have just started developing an android weather app and I was wondering how to change activity background automatically. For example, in daytime it should show day time or in the night it should show night photos.
This is the app of Sony which has a feature (mentioned above)
Check the screenshots.
Okay Credit goes to SteD;so for you check this(beginner's guide)
Follow this
//set an ID for Relative Layout in content_main.xml(Android Studio)
RelativeLayout rlayout=(RelativeLayout)findViewById(R.id.rlayout);
if(something){Drawable drawble=getResource().getDrawable(R.drawable.your_image);rlayout.setBackgroundDrawable(drawable);}
//If it works,destroy the upvote
The only automatic way is the newly released (Day/Night theme for android app)
For finer control you check the condition yourself and call the normal Java methods, like this:
if(something) {
getWindow()
.setBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.image));
}
of if you don't care about the newly introduced context themed styling, you just call the deprecated method (which will keep working without issues for all the foreseeable future)
if(something) {
getWindow()
.setBackgroundDrawable(
getResources().getDrawable(R.drawable.image));
}

HERE SDK turn-by-turn navigation maneuvers

In the HERE SDK user guide there is a screenshot showing the next maneuver. See:
https://developer.here.com/mobile-sdks/documentation/android-hybrid-plus/topics/map-guidance.html
Is this something that is provided by the SDK or is the developer expected to render this manually?
Here is the navigation code I am using:
Route route = list.get(0).getRoute();
map.setMapScheme(Map.Scheme.CARNAV_DAY);
map.getPositionIndicator().setVisible(true);
map.setTilt(45);
map.addMapObject(new MapRoute(route));
manager.setRoute(route);
manager.setTrafficAvoidanceMode(NavigationManager.TrafficAvoidanceMode.DYNAMIC);
manager.setRealisticViewMode(NavigationManager.RealisticViewMode.DAY);
manager.setMap(map);
NavigationManager.Error simError = manager.startNavigation(route);
if(simError != NavigationManager.Error.NONE) {
Log.e(LOG_TAG, "Error" + simError);
}
Maybe a bit late, but for the others who are having the same question,
You can use the HERE Mobile SDK UI Kit (MSDKUI) which provides a highly customizable user interface components that can be used on top of the HERE SDKs.
Here is the repo on Github:
https://github.com/heremaps/msdkui-android
Some things are rendered automatically by the HERE SDK, mainly things that are directly tied to the map rendering (like navigation arrows on the street when doing guidance), but most UI things you have to do on your own since most users want to have their own look&feel and UI.
So, yes the maneuver icons are something you have to provide and render in your UI manually (or the other way around: you have the full freedom to decide how it should look like).

Categories

Resources