Skip to content

Commit

Permalink
add new function: runWatchersOnWindowsChanged
Browse files Browse the repository at this point in the history
  • Loading branch information
codeskyblue committed Apr 26, 2018
1 parent 5ec2a90 commit b191a65
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
package com.github.uiautomator.stub;

import android.app.Instrumentation;
import android.app.UiAutomation;
import android.text.TextUtils;
import android.support.test.uiautomator.UiDevice;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Button;

import org.w3c.dom.Text;

import java.util.HashMap;
import java.util.List;

/**
Expand All @@ -20,30 +15,19 @@
*/

public class AccessibilityEventListener implements UiAutomation.OnAccessibilityEventListener {
// private String[] buttonTexts; // For example: "确定", "安装", "继续安装", "下一步", "完成"
private HashMap<String, String[]> patterns;
private Selector[] selectors;
private HashMap<String, List<Selector>> selectorMap;
private Instrumentation mInstrumentation;

public AccessibilityEventListener(HashMap<String, String[]> patterns) {
this.patterns = patterns;
private UiDevice device;

// this.selectors = selectors;
public AccessibilityEventListener(UiDevice device) {
this.device = device;
}

@Override
public void onAccessibilityEvent(final AccessibilityEvent event) {
if (event.getPackageName() == null) {
return;
}
CharSequence eventPackageName = event.getPackageName();
for (String packageName : this.patterns.keySet()){
if (packageName.equals(eventPackageName)){
String[] labels = patterns.get(eventPackageName);
boolean r = performInstallation(event, labels);
Log.d("Action perform: "+ TextUtils.join(", ", labels) + " " + r);
}
if ((event.getEventType() & (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) != 0) {
device.runWatchers();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
import com.googlecode.jsonrpc4j.JsonRpcError;
import com.googlecode.jsonrpc4j.JsonRpcErrors;

import java.util.HashMap;

public interface AutomatorService {
final static int ERROR_CODE_BASE = -32000;

Expand All @@ -44,10 +42,10 @@ public interface AutomatorService {
/**
* Auto click permission popups
*
* @param patterns key is packageName, values is button names
* @param enabled to enable runWatches on windowChanged
* @throws NotImplementedException
*/
void setAccessibilityPatterns(HashMap<String, String[]> patterns, Selector[] selectors);
void runWatchersOnWindowsChanged(boolean enabled);

/**
* show toast text in seconds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.Direction;
import android.support.test.uiautomator.StaleObjectException;
import android.support.test.uiautomator.UiCollection;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
Expand All @@ -52,7 +53,6 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.Timer;
Expand Down Expand Up @@ -96,21 +96,21 @@ public DeviceInfo deviceInfo() {

/**
* Enable or disable auto install
*
* @param patterns is trigger conditions
*/
@Override
public void setAccessibilityPatterns(HashMap<String, String[]> patterns, Selector[] selectors) {
public void runWatchersOnWindowsChanged(boolean enabled) {
// Important: UiAutomator2 is based on accessibility. so we should keep the old eventTypes.
// and keep serviceInfo.packageNames unchanged.
AccessibilityServiceInfo serviceInfo = uiAutomation.getServiceInfo();
serviceInfo.eventTypes |= AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
uiAutomation.setServiceInfo(serviceInfo);

if (patterns.isEmpty()) {
uiAutomation.setOnAccessibilityEventListener(null);
final int windowChangeEventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
if (enabled) {
serviceInfo.eventTypes |= windowChangeEventTypes;
uiAutomation.setServiceInfo(serviceInfo);
uiAutomation.setOnAccessibilityEventListener(new AccessibilityEventListener(device));
} else {
uiAutomation.setOnAccessibilityEventListener(new AccessibilityEventListener(patterns));
serviceInfo.eventTypes &= ~windowChangeEventTypes;
uiAutomation.setServiceInfo(serviceInfo);
uiAutomation.setOnAccessibilityEventListener(null);
}
}

Expand Down Expand Up @@ -552,7 +552,7 @@ public boolean waitForWindowUpdate(String packageName, long timeout) {
public void clearTextField(Selector obj) throws UiObjectNotFoundException {
try {
obj.toUiObject2().clear();
} catch (NullPointerException e) {
} catch (NullPointerException | StaleObjectException e) {
device.findObject(obj.toUiSelector()).clearTextField();
}

Expand Down Expand Up @@ -588,7 +588,7 @@ public boolean setText(Selector obj, String text) throws UiObjectNotFoundExcepti
obj.toUiObject2().click();
obj.toUiObject2().setText(text);
return true;
} catch (NullPointerException e) {
} catch (NullPointerException | StaleObjectException e) {
return device.findObject(obj.toUiSelector()).setText(text);
}
}
Expand Down
108 changes: 102 additions & 6 deletions app/src/main/java/com/github/uiautomator/FastInputIME.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Base64;
import android.util.Log;
import android.view.KeyEvent;
Expand All @@ -16,12 +19,14 @@
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;

import com.github.uiautomator.monitor.HttpPostNotifier;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.Socket;
import java.util.Random;

import okhttp3.Call;
Expand All @@ -36,6 +41,24 @@ public class FastInputIME extends InputMethodService {
private static final String TAG = "FastInputIME";
private BroadcastReceiver mReceiver = null;
protected OkHttpClient httpClient = new OkHttpClient();
protected static final int INPUT_EDIT = 1;
Socket socketClient;
WhatsInputThread inputThread;

private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case INPUT_EDIT:
String text = msg.getData().getString("text");
setText(text);
break;
default:
break;
}
}
};

@Override
public View onCreateInputView() {
Expand All @@ -58,18 +81,81 @@ public View onCreateInputView() {
return keyboardView;
}

class WhatsInputThread extends Thread {
private Socket socketClient;

public void stopThread() {
try {
if (this.socketClient != null) {
this.socketClient.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public void run() {
try {
socketClient = new Socket("127.0.0.1", 7912);
Writer writer = new OutputStreamWriter(socketClient.getOutputStream());
writer.write("CONNECT /whatsinput HTTP/1.1\r\nHost: FastInputIME\r\n\r\n");
writer.flush();
Log.i(TAG, "/whatsinput connected");
BufferedReader reader = new BufferedReader(new InputStreamReader(socketClient.getInputStream()));
while (!Thread.currentThread().isInterrupted()) {
String line = reader.readLine();
if (line == null || "".equals(line)) {
Log.i(TAG, "Read line empty, maybe disconnected");
break;
}
if (line.charAt(0) == 'I') {
line = line.substring(1);
Log.i(TAG, "Raw data: " + line);
String text = new String(Base64.decode(line, Base64.DEFAULT), "UTF-8");
Log.i(TAG, "Real data: " + text);

Bundle data = new Bundle();
data.putString("text", text);
Message message = new Message();
message.what = INPUT_EDIT;
message.setData(data);
handler.sendMessage(message);
} else {
break;
}
}

socketClient.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
Log.i(TAG, "/whatsinput disconnected");
}
}
}

@Override
public void onCreate() {
super.onCreate();
inputThread = new WhatsInputThread();
inputThread.start();
}

@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
Log.i(TAG, "input destroyed");
inputThread.stopThread();
}

@Override
public void onStartInputView(EditorInfo info, boolean restarting) {
super.onStartInputView(info, restarting);
String text = getText();
makeToast("StartInputView: text -- " + text);
sendRequestToATXAgent("I"+text);
sendRequestToATXAgent("I" + text);
}

@Override
Expand Down Expand Up @@ -200,7 +286,6 @@ private void clearText() {
// Refs: https://stackoverflow.com/questions/33082004/android-custom-soft-keyboard-how-to-clear-edit-text-commited-text
InputConnection ic = getCurrentInputConnection();
CharSequence currentText = ic.getExtractedText(new ExtractedTextRequest(), 0).text;
Log.d(TAG, "Current text: " + currentText);
CharSequence beforCursorText = ic.getTextBeforeCursor(currentText.length(), 0);
CharSequence afterCursorText = ic.getTextAfterCursor(currentText.length(), 0);
ic.deleteSurroundingText(beforCursorText.length(), afterCursorText.length());
Expand All @@ -221,6 +306,17 @@ private String getText() {
return text;
}

private void setText(String text) {
InputConnection ic = getCurrentInputConnection();
if (ic == null) {
return;
}
ic.beginBatchEdit();
clearText();
ic.commitText(text, 1);
ic.endBatchEdit();
}

private void changeInputMethod() {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showInputMethodPicker();
Expand All @@ -233,7 +329,7 @@ private void switchToLastInputMethod() {
}

private void makeToast(String msg) {
// Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
// Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}

private void sendRequestToATXAgent(String text) {
Expand Down

0 comments on commit b191a65

Please sign in to comment.