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)
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>
It is rather simple by using the extras
field in the notification. The key that holds the expanded text lines is EXTRA_TEXT_LINES
.
This is working for me:
Notification notification = (Notification) event.getParcelableData();
CharSequence[] lines = notification.extras.getCharSequenceArray(Notification.EXTRA_TEXT_LINES);
int i = 0;
for(CharSequence msg : lines)
{
Log.d("Line " + i, (String) msg);
i += 1;
}
This code works perfectly for me:
List<String> msgs = new ArrayList<String>();
msgs.add("Info: " + notif.extras.getString(Notification.EXTRA_INFO_TEXT));
msgs.add("Title: " + notif.extras.getString(Notification.EXTRA_TITLE));
msgs.add("Text: " + notif.extras.getString(Notification.EXTRA_TEXT));
I researched some days to get this method, i have tested it on Android 4.4, 5.5 and 6.0. You can also use the method
if(event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED){
if(event.getPackageName().toString().equalsIgnoreCase("com.whatsapp")){
Log.d("msg", event.getText().toString().replace("[", "]").replaceAll("]", ""), Logger.EXTRA_LOG);
}
}
Then you can get all written messages. Hope it helps.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="deepak.com.androidnotification">
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name="deepak.com.androidnotification.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="deepak.com.androidnotification.NotificationService"
android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
</application>
</manifest>
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.support.v4.content.LocalBroadcastManager;
import java.io.ByteArrayOutputStream;
public class NotificationService extends NotificationListenerService {
Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
String pack = sbn.getPackageName();
String ticker ="";
if(sbn.getNotification().tickerText !=null) {
ticker = sbn.getNotification().tickerText.toString();
}
Bundle extras = sbn.getNotification().extras;
String title = extras.getString("android.title");
String text = extras.getCharSequence("android.text").toString();
int id1 = extras.getInt(Notification.EXTRA_SMALL_ICON);
Log.i("Package",pack);
Log.i("Ticker",ticker);
Log.i("Title",title);
Log.i("Text",text);
Intent msgrcv = new Intent("Msg");
msgrcv.putExtra("package", pack);
msgrcv.putExtra("ticker", ticker);
msgrcv.putExtra("title", title);
msgrcv.putExtra("text", text);
LocalBroadcastManager.getInstance(context).sendBroadcast(msgrcv);
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn) {
Log.i("Msg","Notification Removed");
}
}
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by Deepak on 8/30/2017.
*/
public class CustomListAdapter extends BaseAdapter {
int mResource;
ArrayList<Data> arrayList;
Context context;
public CustomListAdapter(Context context,int resource, ArrayList<Data> arrayList) {
this.context = context;
this.arrayList = arrayList;
this.mResource=resource;
}
@Override
public int getCount() {
return arrayList.size();
}
@Override
public Object getItem(int position) {
return arrayList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Data data = (Data) getItem(position);
LayoutInflater inflater =LayoutInflater.from(context);
convertView=inflater.inflate(mResource,parent,false);
TextView textView=(TextView)convertView.findViewById(R.id.textView);
TextView textView1=(TextView)convertView.findViewById(R.id.textView2);
TextView textView2=(TextView)convertView.findViewById(R.id.textView3);
textView.setText(data.getName());
textView1.setText(data.getPack());
textView2.setText(data.getText());
return convertView;
}
}
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.ListView;
import java.util.ArrayList;
public class MainActivity extends Activity {
ListView listView;
ArrayList<Data> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView=(ListView)findViewById(R.id.list) ;
LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, new IntentFilter("Msg"));
}
private BroadcastReceiver onNotice= new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String title = intent.getStringExtra("title");
String pack= intent.getStringExtra("package");
String text = intent.getStringExtra("text");
Log.d("Title",title);
Data data=new Data();
data.setName(title);
data.setPack(pack);
data.setText(text);
list=new ArrayList<Data>();
list.add(data);
listView.setAdapter(new CustomListAdapter(MainActivity.this,R.layout.list_view,list));
}
};
}
public class Data {
private String name;
private String pack;
private String text;
public Data() {
}
public Data(String name, String pack, String text) {
this.name = name;
this.pack = pack;
this.text = text;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPack() {
return pack;
}
public void setPack(String pack) {
this.pack = pack;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="26dp"
android:gravity="center"
android:text="TextView" />
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_centerHorizontal="true"
android:layout_marginTop="26dp"
android:gravity="center"
android:text="TextView" />
<TextView
android:id="@+id/textView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView2"
android:layout_alignStart="@+id/textView2"
android:layout_below="@+id/textView2"
android:layout_marginTop="24dp"
android:gravity="center"
android:text="TextView"/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:id="@+id/list"
android:layout_height="wrap_content"/>
</RelativeLayout>
来源:https://stackoverflow.com/questions/28980078/read-notification-bar-title-message-using-accessibility-service-programmaticall