Created
June 9, 2017 17:39
-
-
Save architjn/af76d790fb9073d6786b99e5c4c2e13c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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