Creator Creator - 3 months ago 37
Java Question

Read Notification Bar title, message using Accessibility Service Programmatically

Using Accessibility Service I am being able to read notification bar title & message, the issue I am facing is when first notification appear I am reading all these perfectly but after first notification & onward I am only getting title & text "you have 2 messages" and so on, not the entire message.
Waiting for your expert advice.

Code :

@Override
protected void onServiceConnected()
{
Log.d("AccessibilityServiceNotification", "ServiceConnected");
try
{
AccessibilityServiceInfo info = new AccessibilityServiceInfo();

info.eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;

info.feedbackType = AccessibilityServiceInfo.FEEDBACK_ALL_MASK;

info.notificationTimeout = 100;

setServiceInfo(info);
}
catch(Exception e)
{
Log.d("ERROR onServiceConnected", e.toString());
}
}

@Override
public void onAccessibilityEvent(AccessibilityEvent event)
{
try
{
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

Parcelable data = event.getParcelableData();

if(data !=null)
{
Notification notification = (Notification) data;

RemoteViews remoteView = notification.bigContentView;

ViewGroup localView = (ViewGroup) inflater.inflate(remoteView.getLayoutId(), null);

remoteView.reapply(getApplicationContext(), localView);

Resources resources = null;

PackageManager pkm = getPackageManager();

try
{
resources = pkm.getResourcesForApplication("com.user.package");
}
catch (NameNotFoundException e)
{
e.printStackTrace();
}

if (resources == null)
return;

int TITLE = resources.getIdentifier("android:id/title", null, null);

int INBOX = resources.getIdentifier("android:id/big_text", null, null);

int TEXT = resources.getIdentifier("android:id/text", null, null);

String packagename = String.valueOf(event.getPackageName());

title = (TextView) localView.findViewById(TITLE);

inbox = (TextView) localView.findViewById(INBOX);

text = (TextView) localView.findViewById(TEXT);

Log.d("NOTIFICATION Package : ", packagename);

Log.d("NOTIFICATION Title : ", title.getText().toString());

Log.d("NOTIFICATION You have got x messages : ", text.getText().toString());

Log.d("NOTIFICATION inbox : ", inbox.getText().toString());
}
}
catch(Exception e)
{
Log.e("onAccessibilityEvent ERROR", e.toString());
}
}


Example Notification 1:

package : com.whatsapp,
title : Hello,
message: How are you

Example Notification 2:

package : com.whatsapp,
title : Hello,
message: you have 2 messages (instead of : What are you doing)

Answer

try this, below code works for me -

Notification notification = (Notification) event.getParcelableData();
RemoteViews views = notification.contentView;
Class secretClass = views.getClass();

try {
    Map<Integer, String> text = new HashMap<Integer, String>();

    Field outerFields[] = secretClass.getDeclaredFields();
    for (int i = 0; i < outerFields.length; i++) {
        if (!outerFields[i].getName().equals("mActions")) continue;

        outerFields[i].setAccessible(true);

        ArrayList<Object> actions = (ArrayList<Object>) outerFields[i]
                .get(views);
        for (Object action : actions) {
            Field innerFields[] = action.getClass().getDeclaredFields();

            Object value = null;
            Integer type = null;
            Integer viewId = null;
            for (Field field : innerFields) {
                field.setAccessible(true);
                if (field.getName().equals("value")) {
                    value = field.get(action);
                } else if (field.getName().equals("type")) {
                    type = field.getInt(action);
                } else if (field.getName().equals("viewId")) {
                    viewId = field.getInt(action);
                }
            }

            if (type == 9 || type == 10) {
                text.put(viewId, value.toString());
            }
        }

        System.out.println("title is: " + text.get(16908310));
        System.out.println("info is: " + text.get(16909082));
        System.out.println("text is: " + text.get(16908358));
    }
} catch (Exception e) {
    e.printStackTrace();
}

hope it will help you.

EDITED

create a folder named xml inside your res folder - create a xml in it named -"accessibilityservice" and paste below code -

<?xml version="1.0" encoding="utf-8"?>
  <accessibility-service  xmlns:android="http://schemas.android.com/apk/res/android"
 android:accessibilityEventTypes="typeNotificationStateChanged"
 android:accessibilityFeedbackType="feedbackSpoken"
 android:notificationTimeout="100" />

and inside manifest update your service tag to below code -

<service
        android:name=".YourServiceClassName"
        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" >
        <intent-filter>
            <action android:name="android.accessibilityservice.AccessibilityService" />
        </intent-filter>

        <meta-data
            android:name="android.accessibilityservice"
            android:resource="@xml/accessibilityservice" />
   </service>