Skip to content

Instantly share code, notes, and snippets.

@architjn
Created June 9, 2017 17:39
Show Gist options
  • Save architjn/af76d790fb9073d6786b99e5c4c2e13c to your computer and use it in GitHub Desktop.
Save architjn/af76d790fb9073d6786b99e5c4c2e13c to your computer and use it in GitHub Desktop.
package com.viztushar.myaccessibility;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import static com.viztushar.myaccessibility.Style.NORMAL;
/**
* Created by Tushar on 24-05-2017.
*/
public class GlobalActionBarService extends AccessibilityService implements View.OnClickListener, View.OnTouchListener {
private static final String TAG = GlobalActionBarService.class.getSimpleName();
RelativeLayout mLayout;
WindowManager.LayoutParams lp;
WindowManager wm;
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
String string;
AccessibilityNodeInfo infos;
AccessibilityEvent accessibilityEvent;
public Context context;
private FloatingActionButton powerButton;
@SuppressLint({"Range", "ClickableViewAccessibility"})
@Override
protected void onServiceConnected() {
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.flags = AccessibilityServiceInfo.DEFAULT;
info.eventTypes = AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
setServiceInfo(info);
context = getBaseContext();
context.setTheme(R.style.AppTheme);
// Create an overlay and display the action bar
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
mLayout = new RelativeLayout(this);
lp = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
// |
lp.gravity = Gravity.TOP | Gravity.LEFT;
lp.x = 0;
lp.y = 100;
LayoutInflater inflater = LayoutInflater.from(this);
inflater.inflate(R.layout.button, mLayout);
mLayout.setAlpha(190);
wm.addView(mLayout, lp);
configurePowerButton();
}
/*
@Override
public void onCreate() {
super.onCreate();
// checkForKeyboard();
// checkForKeyboard2();
}*/
private void checkForKeyboard2() {
KeyboardUtils.addKeyboardToggleListener((Activity) context, new KeyboardUtils.SoftKeyboardToggleListener() {
@Override
public void onToggleSoftKeyboard(boolean isVisible) {
if (isVisible) {
if (powerButton != null)
powerButton.show();
} else {
if (powerButton != null)
powerButton.hide();
}
}
});
}
private void checkForKeyboard() {
mLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
mLayout.getWindowVisibleDisplayFrame(r);
int screenHeight = mLayout.getRootView().getHeight();
// r.bottom is the position above soft keypad or device button.
// if keypad is shown, the r.bottom is smaller than that before.
int keypadHeight = screenHeight - r.bottom;
Log.d(TAG, "keypadHeight = " + keypadHeight);
if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
if (powerButton != null)
powerButton.show();
} else {
if (powerButton != null)
powerButton.hide();
}
}
});
}
@SuppressLint("ClickableViewAccessibility")
private void configurePowerButton() {
powerButton = (FloatingActionButton) mLayout.findViewById(R.id.fab);
powerButton.setImageResource(R.drawable.ic_b_activated);
powerButton.setImageAlpha(190);
powerButton.getBackground().setAlpha(230);
powerButton.setOnClickListener(this);
powerButton.setOnTouchListener(this);
}
public static String textToAscii(String text) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
result.append((int) text.charAt(i)).append(" ");
//result.appendCodePoint(text.charAt(i));
}
return result.toString().replace("[", "").replace("]", "");
}
public static String convert(String text, int to) {
String result = "";
char letter;
for (int i = 0; i < text.length(); i++) {
letter = text.charAt(i);
int a = NORMAL.indexOf(letter);
result += (a != -1) ? Style.get(a, to) : letter;
}
return String.valueOf(result);
}
public 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 null;
}
public String getEventText(AccessibilityEvent accessibilityEvent) {
StringBuilder sb = new StringBuilder();
for (CharSequence s : accessibilityEvent.getText()) {
sb.append(s);
}
return sb.toString();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
infos = event.getSource();
accessibilityEvent = event;
infos = event.getSource();
String s = getEventText(event);
string = convert(s, 2);
Log.d(TAG, String.format("onAccessibilityEvent: type: %s text %s ASCII %s con text %s ",
getEventType(event), getEventText(event), textToAscii(s), convert(s, 2)));
}
@Override
public void onInterrupt() {
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onClick(View v) {
clickAction();
}
private void clickAction() {
performGlobalAction(AccessibilityNodeInfoCompat.ACTION_SET_TEXT);
Bundle bundle;
if (infos != null && infos.getClassName().equals("android.widget.EditText")) {
bundle = new Bundle();
bundle.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
string);
infos.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, bundle);
Toast.makeText(this, string, Toast.LENGTH_LONG).show();
}
}
private int CLICK_ACTION_THRESHHOLD = 200;
private float startX;
private float startY;
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
initialX = lp.x;
initialY = lp.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
float endX = event.getX();
float endY = event.getY();
int Xdiff = (int) (event.getRawX() - initialTouchX);
int Ydiff = (int) (event.getRawY() - initialTouchY);
if (Xdiff < 10 && Ydiff < 10) {
}
if (isAClick(startX, endX, startY, endY)) {
clickAction();
}
return true;
case MotionEvent.ACTION_MOVE:
lp.x = initialX + (int) (event.getRawX() - initialTouchX);
lp.y = initialY + (int) (event.getRawY() - initialTouchY);
wm.updateViewLayout(mLayout, lp);
return true;
}
return true;
}
private boolean isAClick(float startX, float endX, float startY, float endY) {
float differenceX = Math.abs(startX - endX);
float differenceY = Math.abs(startY - endY);
if (differenceX > CLICK_ACTION_THRESHHOLD/* =5 */ || differenceY > CLICK_ACTION_THRESHHOLD) {
return false;
}
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment