Can't enable accessibility function on Custom View on Android
<p>I'm trying to enable Accessibility functionality on my Custom View called MyCompass. The compass holds two values, wind speed and direction, and I'd like them to be read out loud when user touches the compass, if TalkBack and Explore By Touch are enabled. As you can see in the code below, I put a couple of logging statements for debugging purpose. I do get output from both as follows.</p>

<pre>
 D/MyCompass: accessibility event sent
 D/MyCompass: populate with 0.36666667, 267.0
</pre>

<p>But when I touch MyCompass, nothing will be read out except for what I specified in contentDescription in XML file. The value of "@string/compass" is "wind speed and direction", and my goal is to add actual values of wind speed and direction after those words. </p>

<pre><code> &lt;com.example.android.sunshine.app.MyCompass
      android:focusable="true"
      android:contentDescription="@string/compass"
      android:layout_gravity="center_horizontal"
      android:id="@+id/detail_wind_direction_compass"
      android:layout_marginTop="4dp"
      android:layout_height="wrap_content"
      android:layout_width="wrap_content"/&gt;;
</code></pre>

<p>Here is the code. Thanks for your help.</p>

<pre><code>package com.example.android.sunshine.app;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;

public class MyCompass extends View {
    private static final String LOG_TAG = MyCompass.class.getSimpleName();
    private static final int COMPASS_WIDTH = 400;
    private static final int COMPASS_HEIGHT = 400;
    private static final int MAX_HAND_LENGTH = 200;
    private static final int HAND_WIDTH = 10;
    private static final int COMPASS_RADIUS = MAX_HAND_LENGTH / 2;
    private static final float HAND_MAX_M_PER_SEC = 10;
    private static final float WIND_SPEED_GREEN = 4;
    private static final float WIND_SPEED_YELLOW = 6;
    private static final float WIND_SPEED_RED = 8;
    private static final int GREEN = 0xff00ff00;
    private static final int BLUE = 0xff0000ff;
    private static final int YELLOW = 0xffffff00;
    private static final int RED = 0xffff0000;
    private static final Paint BLUE_PAINT = new Paint();
    private static final Paint GREEN_PAINT = new Paint();
    private static final Paint YELLOW_PAINT = new Paint();
    private static final Paint RED_PAINT = new Paint();

    private ShapeDrawable mGreenCircle;
    private ShapeDrawable mYellowCircle;
    private ShapeDrawable mRedCircle;
    private float mDirection = 0;
    private float mSpeed = 0;
    private int centerX = COMPASS_WIDTH / 2;
    private int centerY = COMPASS_HEIGHT / 2;


    // for code
    public MyCompass(Context context) {
        super(context);
    }

    // for XML file
    public MyCompass(Context context, AttributeSet attrs) {
        super(context, attrs);

        BLUE_PAINT.setColor(BLUE);
        BLUE_PAINT.setStyle(Paint.Style.STROKE);
        BLUE_PAINT.setStrokeWidth(HAND_WIDTH);
        GREEN_PAINT.setColor(GREEN);
        YELLOW_PAINT.setColor(YELLOW);
        RED_PAINT.setColor(RED);

        mGreenCircle = new ShapeDrawable(new OvalShape());
        mYellowCircle = new ShapeDrawable(new OvalShape());
        mRedCircle = new ShapeDrawable(new OvalShape());
        drawCircle(mGreenCircle, Math.round(MAX_HAND_LENGTH / HAND_MAX_M_PER_SEC * WIND_SPEED_GREEN), GREEN);
        drawCircle(mYellowCircle, Math.round(MAX_HAND_LENGTH / HAND_MAX_M_PER_SEC * WIND_SPEED_YELLOW), YELLOW);
        drawCircle(mRedCircle, Math.round(MAX_HAND_LENGTH / HAND_MAX_M_PER_SEC * WIND_SPEED_RED), RED);

    }

    private void drawCircle(ShapeDrawable drawable, int radius, int color) {
        drawable.getPaint().setColor(color);
        drawable.setBounds(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
    }

    // for inflation
    public MyCompass(Context context, AttributeSet attrs, int defaultStyle) {
        super(context, attrs, defaultStyle);
    }

    // speed is in km/h
    public void setDirectionAndSpeed(float direction, float speed) {
        mDirection = direction;
        mSpeed = speed * 1000 / 3600; // convert km/h to m/s
        MyCompass compass = (MyCompass) findViewById(R.id.detail_wind_direction_compass);
        //compass.setContentDescription(compass.getContentDescription() + " is " + mSpeed + " m/s at " + mDirection);


        Context context = getContext();
        AccessibilityManager accessibilityManager =
            (AccessibilityManager) context.getSystemService(
                Context.ACCESSIBILITY_SERVICE);
        if (accessibilityManager.isEnabled()) {
            sendAccessibilityEvent(
                AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
            Log.d(LOG_TAG, "accessibility event sent");
        }

        invalidate();
    }

    @Override
    protected void onMeasure(int wMeasureSpec, int hMeasureSpec) {
        int wSpecMode = MeasureSpec.getMode(wMeasureSpec);
        int wSpecSize = MeasureSpec.getSize(wMeasureSpec);
        int myWidth = wSpecSize;

        int hSpecMode = MeasureSpec.getMode(hMeasureSpec);
        int hSpecSize = MeasureSpec.getSize(hMeasureSpec);
        int myHeight = hSpecSize;

        if (wSpecMode == MeasureSpec.EXACTLY) {
            myWidth = wSpecSize;
        } else if (wSpecMode == MeasureSpec.AT_MOST || wSpecMode == MeasureSpec.UNSPECIFIED) {
            // Wrap Content
            myWidth = COMPASS_WIDTH;
        }

        if (hSpecMode == MeasureSpec.EXACTLY) {
            myHeight = hSpecSize;
        } else if (hSpecMode == MeasureSpec.AT_MOST || hSpecMode == MeasureSpec.UNSPECIFIED) {
            // Wrap Content
            myHeight = COMPASS_HEIGHT;
        }
        setMeasuredDimension(myWidth, myHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        mRedCircle.draw(canvas);
        mYellowCircle.draw(canvas);
        mGreenCircle.draw(canvas);
        int handLength = (int) (mSpeed / HAND_MAX_M_PER_SEC * MAX_HAND_LENGTH);
        canvas.drawLine(
                centerX,
                centerY,
                (float) (centerX + handLength * Math.sin(mDirection / 180 * Math.PI)),
                (float) (centerY - handLength * Math.cos(mDirection / 180 * Math.PI)),
                BLUE_PAINT
        );

    }

    @Override
    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent ev) {
        super.dispatchPopulateAccessibilityEvent(ev);
        if (ev.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) {
            Log.d(LOG_TAG, "populate with " + mSpeed + ", " + mDirection);
            ev.getText().add(String.valueOf(mSpeed) + " m/s from " + String.valueOf(mDirection));
        }

        return true;
    }

}
</code></pre>