Как сделать JavaCameraView невидимым без отключения камеры в службе специальных возможностей Android? - PullRequest
0 голосов
/ 09 ноября 2018

Я пытаюсь создать службу доступности для Android, которая использует ручные волны OpenCV для базового управления другими приложениями (например, прокруткой). В настоящее время я использую NewHandWave для распознавания ручных волн. Это работало отлично, за исключением одной большой проблемы; JavaCameraView создает очень большой черный прямоугольник на большей части экрана . Это распознавание ручных волн, и все, что находится под прямоугольником, все еще может взаимодействовать.

Соответствующий код из файла сервиса java:

package com.example.android.handgestureservice;

import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.GestureDescription;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.view.Gravity;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;

import edu.washington.cs.touchfreelibrary.sensors.CameraGestureSensor;
import edu.washington.cs.touchfreelibrary.sensors.ClickSensor;
import edu.washington.cs.touchfreelibrary.utilities.LocalOpenCV;

import java.util.ArrayDeque;
import java.util.Deque;

public class HandGestureService extends AccessibilityService implements CameraGestureSensor.Listener, ClickSensor.Listener{


@Override
public void onGestureUp(CameraGestureSensor caller, long gestureLength) {
    AccessibilityNodeInfo scrollable = findScrollableNode(getRootInActiveWindow());
    if (scrollable != null) {
        scrollable.performAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD.getId());
    }


}

@Override
public void onGestureDown(CameraGestureSensor caller, long gestureLength) {
    AccessibilityNodeInfo scrollable = findScrollableNode(getRootInActiveWindow());
    if (scrollable != null) {
        scrollable.performAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD.getId());
    }


}

@Override
public void onGestureLeft(CameraGestureSensor caller, long gestureLength) {
    AccessibilityNodeInfo scrollable = findScrollableNode(getRootInActiveWindow());

    Path swipePath = new Path();
    swipePath.moveTo(100, 1000);
    swipePath.lineTo(1000, 1000);
    GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
    gestureBuilder.addStroke(new GestureDescription.StrokeDescription(swipePath, 0, 500));
    dispatchGesture(gestureBuilder.build(), null, null);

}

@Override
public void onGestureRight(CameraGestureSensor caller, long gestureLength) {
    AccessibilityNodeInfo scrollable = findScrollableNode(getRootInActiveWindow());


    Path swipePath = new Path();
    swipePath.moveTo(1000, 1000);
    swipePath.lineTo(100, 1000);
    GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
    gestureBuilder.addStroke(new GestureDescription.StrokeDescription(swipePath, 0, 500));
    dispatchGesture(gestureBuilder.build(), null, null);

}

@Override
public void onSensorClick(ClickSensor caller) {

}


// Figures out if scrolling is possible.
private AccessibilityNodeInfo findScrollableNode(AccessibilityNodeInfo root) {
    Deque<AccessibilityNodeInfo> deque = new ArrayDeque<>();
    deque.add(root);
    while (!deque.isEmpty()) {
        AccessibilityNodeInfo node = deque.removeFirst();
        if (node.getActionList().contains(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD)) {
            return node;
        }
        for (int i = 0; i < node.getChildCount(); i++) {
            deque.addLast(node.getChild(i));
        }
    }
    return null;
}



@Override
protected void onServiceConnected() {

    // Load OpenCV
    LocalOpenCV loader = new LocalOpenCV(this,this,this);

    // Get window manager to be able to bind layouts to service
    WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);

    // Set up layout parameters
    WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
    lp.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
    lp.format = PixelFormat.TRANSPARENT;
    lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
    lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
    lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
    lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
    lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
    lp.gravity = Gravity.TOP;

    // Add view to service
    wm.addView(loader.CameraLayout,lp);

}

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {

}

@Override
public void onInterrupt() {

}

}

С LocalOpenCV.java с NewHandWave

// Added so that the service can bind the layout
public RelativeLayout CameraLayout = null;


// Modified to accept any context instead of Activity contexts
public LocalOpenCV(Context context, CameraGestureSensor.Listener gestureListener, ClickSensor.Listener clickListener) {
    this.context = context;
    this.gestureListener = gestureListener;
    this.clickListener = clickListener;
    doLoad(context, gestureListener, clickListener);
}

// Modified to accept any context instead of just Activity contexts
public void doLoad(Context context, CameraGestureSensor.Listener listeners, ClickSensor.Listener clickListener) {
    this.CameraLayout = new BackendGestureCamera().getJavaCameraViewWrappedInRelativeLayout(context);
    this.mCamera = (JavaCameraView) this.CameraLayout.findViewById(R.id.camera);
    makeGenericLoaderCallback();
    loadOpenCV(context);
}

С BackendGestureDetector.java с NewHandWave

public class BackendGestureCamera {

// Modified to accept any context instead of just Activity
public RelativeLayout getJavaCameraViewWrappedInRelativeLayout(Context context) {
    LayoutInflater inflater = LayoutInflater.from(context);
    RelativeLayout layout = (RelativeLayout) inflater.inflate(R.layout.item_java_camera_view, null);
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    layout.setLayoutParams(params);
    return layout;
    }
}

Пока я определил, что это CameraLayout, сгенерированный getJavaCameraViewWrappedInRelativeLayout, создающим большой черный прямоугольник. Я попытался установить альфа на 0 (который ничего не делал) и изменить видимость на INVISIBLE или GONE (который избавляется от прямоугольника, но отключает камеру).

TLDR: в поисках способа сделать макет невидимым без отключения OpenCV JavaCameraView.

...