问题
I am trying to access the notifications on my android phone using the AccessibilityService.
I tried making a service and calling it from the main activity. I've also added meta for the service. It's not working. I cannot see the triggering of the service.
I'm using Android L for testing. In accessibility settings I've added my app 'Notify' as on.
Thanks in advance.
My main Activity
package com.example.tony.notify;
import android.content.Intent;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// startActivityForResult(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0);
Intent i = new Intent(this, MyAccessibilityService.class);
startService(i);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
This is my service class
package com.example.tony.notify;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Toast;
/**
* Created by tony on 9/7/15.
*/
public class MyAccessibilityService extends AccessibilityService {
final String TAG = "Notification service";
private String getEventType(AccessibilityEvent event) {
switch (event.getEventType()) {
case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
return "TYPE_NOTIFICATION_STATE_CHANGED";
case AccessibilityEvent.TYPE_VIEW_CLICKED:
return "TYPE_VIEW_CLICKED";
case AccessibilityEvent.TYPE_VIEW_FOCUSED:
return "TYPE_VIEW_FOCUSED";
case AccessibilityEvent.TYPE_VIEW_LONG_CLICKED:
return "TYPE_VIEW_LONG_CLICKED";
case AccessibilityEvent.TYPE_VIEW_SELECTED:
return "TYPE_VIEW_SELECTED";
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
return "TYPE_WINDOW_STATE_CHANGED";
case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
return "TYPE_VIEW_TEXT_CHANGED";
}
return "default";
}
private String getEventText(AccessibilityEvent event) {
StringBuilder sb = new StringBuilder();
for (CharSequence s : event.getText()) {
sb.append(s);
}
return sb.toString();
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
Log.v(TAG, String.format(
"onAccessibilityEvent: [type] %s [class] %s [package] %s [time] %s [text] %s",
getEventType(event), event.getClassName(), event.getPackageName(),
event.getEventTime(), getEventText(event)));
}
@Override
public void onInterrupt() {
Log.v(TAG, "onInterrupt");
}
@Override
protected void onServiceConnected() {
Toast.makeText(getApplicationContext(),"connected",Toast.LENGTH_SHORT).show();
super.onServiceConnected();
Log.v(TAG, "onServiceConnected");
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.flags = AccessibilityServiceInfo.DEFAULT;
info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
setServiceInfo(info);
}
}
My manifest for declaring service
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tony.notify" >
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<service android:name=".MyAccessibilityService"
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>
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Please help. Thanks in advance. I've tried looking into some examples. I couldn't find errors.
回答1:
I got it working on L though, it's not really working on api 16, I tested on one. Can anyone suggest an addition to make it work on api 14+
Manifest File
package com.example.tony.acctest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import com.example.tony.acctest.MyAccessibilityService.Constants;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MA LOG";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final IntentFilter mIntentFilter = new IntentFilter(Constants.ACTION_CATCH_NOTIFICATION);
registerReceiver(NotificationCatcherReceiver, mIntentFilter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(NotificationCatcherReceiver);
}
private final BroadcastReceiver NotificationCatcherReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, intent.getStringExtra(Constants.EXTRA_PACKAGE));
Log.v(TAG, intent.getStringExtra(Constants.EXTRA_MESSAGE));
}
};
}
My service class
package com.example.tony.acctest;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.TargetApi;
import android.app.Notification;
import android.content.Intent;
import android.os.Build;
import android.os.Parcelable;
import android.view.accessibility.AccessibilityEvent;
import java.util.List;
public class MyAccessibilityService extends AccessibilityService {
private final AccessibilityServiceInfo info = new AccessibilityServiceInfo();
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
final int eventType = event.getEventType();
if (eventType == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
final String sourcePackageName = (String)event.getPackageName();
Parcelable parcelable = event.getParcelableData();
if (parcelable instanceof Notification) {
List<CharSequence> messages = event.getText();
if (messages.size() > 0) {
try {
final String notificationMsg = (String) messages.get(0);
Intent mIntent = new Intent(Constants.ACTION_CATCH_NOTIFICATION);
mIntent.putExtra(Constants.EXTRA_PACKAGE, sourcePackageName);
mIntent.putExtra(Constants.EXTRA_MESSAGE, notificationMsg);
MyAccessibilityService.this.getApplicationContext().sendBroadcast(mIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
@Override
public void onInterrupt() {
}
@Override
public void onServiceConnected() {
info.eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
} else {
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
}
info.notificationTimeout = 100;
this.setServiceInfo(info);
}
public static final class Constants {
public static final String EXTRA_MESSAGE = "extra_message";
public static final String EXTRA_PACKAGE = "extra_package";
public static final String ACTION_CATCH_NOTIFICATION = "com.example.tony.acctest.CATCH_NOTIFICATION";
}
}
This is my Main activity package com.example.tony.acctest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import com.example.tony.acctest.MyAccessibilityService.Constants;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MA LOG";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final IntentFilter mIntentFilter = new IntentFilter(Constants.ACTION_CATCH_NOTIFICATION);
registerReceiver(NotificationCatcherReceiver, mIntentFilter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(NotificationCatcherReceiver);
}
private final BroadcastReceiver NotificationCatcherReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, intent.getStringExtra(Constants.EXTRA_PACKAGE));
Log.v(TAG, intent.getStringExtra(Constants.EXTRA_MESSAGE));
}
};
}
回答2:
I had done this when my widget got enabled:
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
String enabledListeners = Settings.Secure.getString(
context.getContentResolver(), "enabled_notification_listeners");
if (!enabledListeners.contains("Myalert")) {
Intent i = new Intent(
"android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
And in my manifest:
<service
android:name="com.edgealert.NotificationMonitor"
android:label="MyAlert"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" >
</action>
</intent-filter>
</service>
<receiver android:name=".MyReceiver" >
<intent-filter>
<action android:name="com.samsung.android.cocktail.action.COCKTAIL_UPDATE" />
</intent-filter>
<meta-data
android:name="com.samsung.android.cocktail.provider"
android:resource="@xml/single_cocktail" />
</receiver>
来源:https://stackoverflow.com/questions/31308841/cannot-access-notification-through-android-accessibilityservice