据我所知,这是可能的,从这里开始 Detecting toast messages 但我无法通过链接捕获任何带有代码片段的事件。
MyAccessibilityService.java
package com.test.toasts2;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Notification;
import android.os.Parcelable;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Toast;
public class MyAccessibilityService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
System.out.println("event catched");
Toast.makeText(this, "catched " + "!", Toast.LENGTH_SHORT).show();
if(event.getEventType() != AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED)
return; // event is not a notification
String sourcePackageName = (String)event.getPackageName();
Parcelable parcelable = event.getParcelableData();
if(parcelable instanceof Notification){
// Statusbar Notification
}
else{
// something else, e.g. a Toast message
String log = "Message: "+event.getText().get(0)+" [Source: "+sourcePackageName+"]";
System.out.println(log);
// write `log` to file...
}
}
@Override
public void onInterrupt() {
// TODO Auto-generated method stub
}
@Override
protected void onServiceConnected() {
// TODO Auto-generated method stub
super.onServiceConnected();
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.feedbackType = AccessibilityServiceInfo.DEFAULT;
setServiceInfo(info);
}
}
的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.toasts2"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="15" />
<application>
<service android:name=".MyAccessibilityService"
android:label="label">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
</service>
</application>
</manifest>
似乎这项服务根本没有启动。我做错了什么?
为什么我这样做: 我在我的应用程序的库存启动器上安装了许多快捷方式。我遇到的问题是,theese快捷方式在一个单元格中一个接一个地放置(即使Sleep 500没有帮助)。所以我找到了一种方法来逐个安装它们。但是如何知道何时成功安装了快捷方式?我发现只有ics启动器向用户显示的消息。
答案 0 :(得分:3)
TYPE_NOTIFICATION_STATE_CHANGED通常是指状态栏中放置的NotificationManager和图标。尽管如此,下面的代码应该有助于阐明Toast消息的来源。在Android 4.0.4 ICS上,Toast的类为android.widget.Toast
,因此getClassName
应该可以解决问题。
为了它的价值,似乎在Android 4.0.3中进行了更改,以便在Toast.TN
private void trySendAccessibilityEvent() {
AccessibilityManager accessibilityManager =
AccessibilityManager.getInstance(mView.getContext());
if (!accessibilityManager.isEnabled()) {
return;
}
// treat toasts as notifications since they are used to
// announce a transient piece of information to the user
AccessibilityEvent event = AccessibilityEvent.obtain(
AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
event.setClassName(getClass().getName());
event.setPackageName(mView.getContext().getPackageName());
mView.dispatchPopulateAccessibilityEvent(event);
accessibilityManager.sendAccessibilityEvent(event);
}
您可以在所有版本的Android Toast
中看到here课程。
private final 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_VIEW_SCROLLED:
return "TYPE_VIEW_SCROLLED";
case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT:
return "TYPE_VIEW_HOVER_EXIT";
case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
return "TYPE_VIEW_HOVER_ENTER";
case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
return "TYPE_TOUCH_EXPLORATION_GESTURE_START";
case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
return "TYPE_WINDOW_STATE_CHANGED";
case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
return "TYPE_WINDOW_CONTENT_CHANGED";
case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED:
return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
return "TYPE_VIEW_TEXT_CHANGED";
}
return "default";
}
private final String getEventText(AccessibilityEvent event) {
StringBuilder sb = new StringBuilder();
for (CharSequence s : event.getText()) {
sb.append(s);
sb.append('\n');
}
return sb.toString();
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event)
{
Log.v(TAG, String.format(
"onAccessibilityEvent: [type] %s [class] %s [package] %s [time]
%s [fullscreen] %s [text] %s", getEventType(event), event.getClassName(),
event.getPackageName(), event.getEventTime(), Boolean.toString(
event.isFullScreen()), getEventText(event)));
if (android.os.Build.VERSION.SDK_INT >= 14)
Log.v(TAG, "Window ID: " + Integer.toString(event.getWindowId()) + ".");
}
private void setServiceInfo(int feedbackType)
{
final AccessibilityServiceInfo info = new AccessibilityServiceInfo();
// We are interested in all types of accessibility events.
info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
// We want to provide specific type of feedback.
info.feedbackType = feedbackType;
// We want to receive events in a certain interval.
// info.notificationTimeout = EVENT_NOTIFICATION_TIMEOUT_MILLIS;
// We want to receive accessibility events only from certain packages.
// info.packageNames = PACKAGE_NAMES;
setServiceInfo(info);
}
private boolean isInfrastructureInitialized = false;
@Override
public void onServiceConnected()
{
if (isInfrastructureInitialized) return;
// Claim the events with which to listen to.
setServiceInfo(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
// We are in an initialized state now.
isInfrastructureInitialized = true;
}
来源:个人经历。
答案 1 :(得分:0)
创建一个活动,该活动将构建一个意图并使用它来启动您的服务。
这样的事情将是活动中的代码。
Intent i = new Intent(YourActivity.this, MyAccessibilityService.class);
startService(i);
在清单中,活动的intent过滤器中包含MAIN和LAUNCHER,以便在用户(或adb)启动应用程序时运行Activity。然后,该活动将为您启动服务。
编辑:我假设您在帖子中看到了此链接。并且你不是在2.2上尝试这个吗?
注意:这在Android 2.2上对我不起作用(它似乎没有捕获Toasts),但它适用于Android 4.0。
答案 2 :(得分:0)
首先你不应该试图抓住Toast,因为这是一个异步调用,它会在屏幕上显示Toast,并且它会根据Timing保留在屏幕上,可以离开应用程序仍然有吐司出现。当吐司完成时你不应该在乎,因为这是无关紧要的。所有Toast应该用于 JUST ,以提供有关正在进行/已完成的特定进程或仅信息的用户信息。它不适合你想要做的事情。
为什么不直接向您的应用程序发送内部广播并通过Intent Filter捕获它,然后在收到该广播时,您应该启动该服务。