mirror of
https://github.com/TonyJiangWJ/Auto.js.git
synced 2026-06-21 21:01:43 +08:00
add: notification listener service
This commit is contained in:
parent
bfd6a0c40a
commit
cbd2600c33
@ -212,6 +212,15 @@
|
||||
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="com.stardust.notification.NotificationListenerService"
|
||||
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>
|
||||
|
||||
<receiver android:name=".external.widget.ScriptWidget">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
package com.stardust.scriptdroid.ui.main.drawer;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
@ -13,6 +17,7 @@ import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.stardust.notification.NotificationListenerService;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.R;
|
||||
@ -55,6 +60,7 @@ import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/30.
|
||||
* TODO 侧拉菜单用RecyclerView
|
||||
*/
|
||||
@EFragment(R.layout.fragment_drawer)
|
||||
public class DrawerFragment extends android.support.v4.app.Fragment {
|
||||
@ -67,6 +73,9 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
||||
@ViewById(R.id.accessibility_service)
|
||||
DrawerMenuItem mAccessibilityServiceItem;
|
||||
|
||||
@ViewById(R.id.notification_service)
|
||||
DrawerMenuItem mNotificationPermissionItem;
|
||||
|
||||
@ViewById(R.id.floating_window)
|
||||
DrawerMenuItem mFloatingWindowItem;
|
||||
|
||||
@ -201,6 +210,19 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
@Click(R.id.notification_service)
|
||||
void goToNotificationServiceSettings() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
return;
|
||||
}
|
||||
boolean enabled = NotificationListenerService.getInstance() != null;
|
||||
boolean checked = mNotificationPermissionItem.getSwitchCompat().isChecked();
|
||||
if ((checked && !enabled) || (!checked && enabled)) {
|
||||
startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean isAccessibilityServiceEnabled() {
|
||||
return AccessibilityServiceTool.isAccessibilityServiceEnabled(getActivity());
|
||||
}
|
||||
@ -307,6 +329,10 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
||||
private void syncSwitchState() {
|
||||
mAccessibilityServiceItem.getSwitchCompat().setChecked(
|
||||
AccessibilityServiceTool.isAccessibilityServiceEnabled(getActivity()));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
mNotificationPermissionItem.getSwitchCompat().setChecked(NotificationListenerService.getInstance() != null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void enableAccessibilityService() {
|
||||
|
||||
BIN
app/src/main/res/drawable-xhdpi/ic_ali_notification.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_ali_notification.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
@ -15,7 +15,7 @@
|
||||
<com.stardust.scriptdroid.ui.main.drawer.DrawerMenuGroup
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:title="@string/text_accessibility_service">
|
||||
app:title="@string/text_service">
|
||||
|
||||
<com.stardust.scriptdroid.ui.main.drawer.DrawerMenuItem
|
||||
android:id="@+id/accessibility_service"
|
||||
@ -35,6 +35,14 @@
|
||||
app:title="@string/text_stable_mode"
|
||||
app:with_switch="true"/>
|
||||
|
||||
<com.stardust.scriptdroid.ui.main.drawer.DrawerMenuItem
|
||||
android:id="@+id/notification_service"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_ali_notification"
|
||||
app:title="@string/text_notification_permission"
|
||||
app:with_switch="true"/>
|
||||
|
||||
|
||||
</com.stardust.scriptdroid.ui.main.drawer.DrawerMenuGroup>
|
||||
|
||||
|
||||
@ -282,6 +282,8 @@
|
||||
<string name="text_reset_succeed">重置成功</string>
|
||||
<string name="text_cannot_read_file" formatted="true">无法读取文件: %s</string>
|
||||
<string name="text_connected">已连接</string>
|
||||
<string name="text_service">服务</string>
|
||||
<string name="text_notification_permission">通知权限</string>
|
||||
|
||||
|
||||
<string-array name="ad_showing_mode_keys">
|
||||
|
||||
@ -27,11 +27,11 @@ import com.stardust.util.ScreenMetrics;
|
||||
public class ScreenCapturer {
|
||||
|
||||
private static final String LOG_TAG = "ScreenCapturer";
|
||||
private final Object mCachedImageLock = new Object();
|
||||
private ImageReader mImageReader;
|
||||
private MediaProjection mMediaProjection;
|
||||
private VirtualDisplay mVirtualDisplay;
|
||||
private volatile Looper mImageAcquireLooper;
|
||||
private final Object mImageWaitingLock = new Object();
|
||||
private volatile Image mUnderUsingImage;
|
||||
private volatile Image mCachedImage;
|
||||
private final int mScreenWidth;
|
||||
@ -87,7 +87,13 @@ public class ScreenCapturer {
|
||||
@Override
|
||||
public void onImageAvailable(ImageReader reader) {
|
||||
if (mCachedImage != null) {
|
||||
return;
|
||||
synchronized (mCachedImageLock) {
|
||||
if (mCachedImage != null) {
|
||||
mCachedImage.close();
|
||||
}
|
||||
mCachedImage = reader.acquireLatestImage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
mCachedImage = reader.acquireLatestImage();
|
||||
}
|
||||
@ -99,8 +105,10 @@ public class ScreenCapturer {
|
||||
if (mCachedImage != null) {
|
||||
if (mUnderUsingImage != null)
|
||||
mUnderUsingImage.close();
|
||||
mUnderUsingImage = mCachedImage;
|
||||
mCachedImage = null;
|
||||
synchronized (mCachedImageLock) {
|
||||
mUnderUsingImage = mCachedImage;
|
||||
mCachedImage = null;
|
||||
}
|
||||
}
|
||||
return mUnderUsingImage;
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
package com.stardust.autojs.runtime.api;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
@ -11,6 +11,8 @@ import android.view.accessibility.AccessibilityEvent;
|
||||
import com.stardust.autojs.R;
|
||||
import com.stardust.autojs.core.accessibility.AccessibilityBridge;
|
||||
import com.stardust.autojs.core.eventloop.EventEmitter;
|
||||
import com.stardust.notification.Notification;
|
||||
import com.stardust.notification.NotificationListenerService;
|
||||
import com.stardust.autojs.runtime.ScriptBridges;
|
||||
import com.stardust.autojs.runtime.exception.ScriptException;
|
||||
import com.stardust.autojs.core.inputevent.InputEventObserver;
|
||||
@ -136,9 +138,14 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
mListeningNotification = true;
|
||||
ensureHandler();
|
||||
mLoopers.waitWhenIdle(true);
|
||||
mAccessibilityBridge.ensureServiceEnabled();
|
||||
mAccessibilityBridge.getNotificationObserver()
|
||||
.addListener(this);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2
|
||||
&& NotificationListenerService.getInstance() != null) {
|
||||
NotificationListenerService.getInstance().addListener(this);
|
||||
} else {
|
||||
mAccessibilityBridge.ensureServiceEnabled();
|
||||
mAccessibilityBridge.getNotificationObserver()
|
||||
.addListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
public Events onNotification(Object listener) {
|
||||
@ -165,6 +172,10 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
}
|
||||
if (mListeningNotification) {
|
||||
mAccessibilityBridge.getNotificationObserver().removeListener(this);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2
|
||||
&& NotificationListenerService.getInstance() != null) {
|
||||
NotificationListenerService.getInstance().removeListener(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,24 +212,11 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onNotification(final AccessibilityEvent event, final NotificationInfo notification) {
|
||||
public void onNotification(final Notification notification) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
emit("toast", notification);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotification(final AccessibilityEvent event, final Notification notification) {
|
||||
final NotificationInfo info = NotificationInfo.fromEvent(event);
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
emit("notification", info, notification);
|
||||
emit("notification", notification);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -99,7 +99,6 @@ public class Images {
|
||||
Image image = mScreenCapturer.capture();
|
||||
if (image != null) {
|
||||
saveImage(image, path);
|
||||
image.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -0,0 +1,92 @@
|
||||
package com.stardust.notification;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.support.annotation.RequiresApi;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/10/30.
|
||||
*/
|
||||
|
||||
public class Notification extends android.app.Notification {
|
||||
|
||||
private String mPackageName;
|
||||
|
||||
private Notification(String packageName) {
|
||||
mPackageName = packageName;
|
||||
}
|
||||
|
||||
public static Notification create(android.app.Notification n, String packageName) {
|
||||
Notification notification = new Notification(packageName);
|
||||
clone(n, notification);
|
||||
return notification;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public String getText() {
|
||||
return extras.getString(EXTRA_TEXT);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public String getTitle() {
|
||||
return extras.getString(EXTRA_TITLE);
|
||||
}
|
||||
|
||||
public void click() {
|
||||
try {
|
||||
this.contentIntent.send();
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
try {
|
||||
this.deleteIntent.send();
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void clone(android.app.Notification from, android.app.Notification to) {
|
||||
to.when = from.when;
|
||||
to.icon = from.icon;
|
||||
to.iconLevel = from.iconLevel;
|
||||
to.number = from.number;
|
||||
to.contentIntent = from.contentIntent;
|
||||
to.deleteIntent = from.deleteIntent;
|
||||
to.fullScreenIntent = from.fullScreenIntent;
|
||||
to.tickerText = from.tickerText;
|
||||
to.tickerView = from.tickerView;
|
||||
to.contentView = from.contentView;
|
||||
to.bigContentView = from.bigContentView;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
to.headsUpContentView = from.headsUpContentView;
|
||||
to.audioAttributes = from.audioAttributes;
|
||||
to.color = from.color;
|
||||
to.visibility = from.visibility;
|
||||
to.category = from.category;
|
||||
to.publicVersion = from.publicVersion;
|
||||
}
|
||||
to.largeIcon = from.largeIcon;
|
||||
to.sound = from.sound;
|
||||
to.audioStreamType = from.audioStreamType;
|
||||
to.vibrate = from.vibrate;
|
||||
to.ledARGB = from.ledARGB;
|
||||
to.ledOnMS = from.ledOnMS;
|
||||
to.ledOffMS = from.ledOffMS;
|
||||
to.defaults = from.defaults;
|
||||
to.flags = from.flags;
|
||||
to.priority = from.priority;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
to.extras = from.extras;
|
||||
to.actions = from.actions;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
package com.stardust.notification;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.support.annotation.RequiresApi;
|
||||
|
||||
import com.stardust.view.accessibility.NotificationListener;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/10/30.
|
||||
*/
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
public class NotificationListenerService extends android.service.notification.NotificationListenerService {
|
||||
|
||||
private CopyOnWriteArrayList<NotificationListener> mNotificationListeners = new CopyOnWriteArrayList<>();
|
||||
private static NotificationListenerService sInstance;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
sInstance = this;
|
||||
}
|
||||
|
||||
public static NotificationListenerService getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
|
||||
onNotificationPosted(sbn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationPosted(StatusBarNotification sbn) {
|
||||
for (NotificationListener listener : mNotificationListeners) {
|
||||
listener.onNotification(com.stardust.notification.Notification.create(
|
||||
sbn.getNotification(), sbn.getPackageName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationRemoved(StatusBarNotification sbn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
|
||||
}
|
||||
|
||||
public void addListener(NotificationListener listener) {
|
||||
mNotificationListeners.add(listener);
|
||||
}
|
||||
|
||||
public boolean removeListener(NotificationListener listener) {
|
||||
return mNotificationListeners.remove(listener);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
sInstance = null;
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,14 @@
|
||||
package com.stardust.view.accessibility;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import com.stardust.notification.Notification;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -19,6 +21,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public interface NotificationListener {
|
||||
|
||||
|
||||
class NotificationInfo {
|
||||
|
||||
private String mPackageName;
|
||||
@ -73,9 +76,9 @@ public interface NotificationListener {
|
||||
}
|
||||
}
|
||||
|
||||
void onNotification(AccessibilityEvent event, NotificationInfo notification);
|
||||
|
||||
void onNotification(AccessibilityEvent event, Notification notification);
|
||||
void onNotification(Notification notification);
|
||||
|
||||
|
||||
class Observer implements NotificationListener, AccessibilityDelegate {
|
||||
|
||||
@ -91,27 +94,6 @@ public interface NotificationListener {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotification(AccessibilityEvent event, NotificationInfo notification) {
|
||||
for (NotificationListener listener : mNotificationListeners) {
|
||||
try {
|
||||
listener.onNotification(event, notification);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error onNotification: " + notification + " Listener: " + listener, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotification(AccessibilityEvent event, Notification notification) {
|
||||
for (NotificationListener listener : mNotificationListeners) {
|
||||
try {
|
||||
listener.onNotification(event, notification);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error onNotification: " + notification + " Listener: " + listener, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(NotificationListener listener) {
|
||||
mNotificationListeners.add(listener);
|
||||
@ -124,18 +106,9 @@ public interface NotificationListener {
|
||||
@Override
|
||||
public boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event) {
|
||||
if (event.getParcelableData() instanceof Notification) {
|
||||
Notification notification = (Notification) event.getParcelableData();
|
||||
android.app.Notification notification = (android.app.Notification) event.getParcelableData();
|
||||
Log.d(TAG, "onNotification: " + notification + "; " + event);
|
||||
onNotification(event, notification);
|
||||
} else {
|
||||
List<CharSequence> list = event.getText();
|
||||
Log.d(TAG, "onNotification: " + list + "; " + event);
|
||||
if (event.getPackageName().equals(mContext.getPackageName())) {
|
||||
return false;
|
||||
}
|
||||
if (list != null) {
|
||||
onNotification(event, new NotificationInfo(event.getPackageName(), list));
|
||||
}
|
||||
onNotification(Notification.create(notification, event.getPackageName().toString()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -145,5 +118,16 @@ public interface NotificationListener {
|
||||
public Set<Integer> getEventTypes() {
|
||||
return EVENT_TYPES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotification(Notification notification) {
|
||||
for (NotificationListener listener : mNotificationListeners) {
|
||||
try {
|
||||
listener.onNotification(notification);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error onNotification: " + notification + " Listener: " + listener, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user