서비스는 터치 제스처 / 이벤트를 어떻게 수신 할 수 있습니까?
SwipePad 및 Wave Launcher와 같은 앱이 단순히 서비스를 통해 터치 제스처 / 이벤트를 감지 할 수 있는지 궁금합니다. 이러한 앱은 자체 활동에 있지 않더라도 터치 제스처를 감지 할 수 있습니다. 나는 인터넷을 샅샅이 살펴 봤지만 그들이 어떻게 할 수 있는지 찾지 못했습니다.
내 주요 질문은 서비스가 원래 활동 또는 컨텍스트에 있지 않더라도 일반 활동이 MotionEvents를 수신 할 수있는 것처럼 터치 게스트 / 이벤트에서 수신 할 수있는 방법입니다. 나는 본질적으로 어떤 활동이 위에 있는지에 관계없이 사용자의 특정 터치 제스처를 인식하고 해당 제스처가 인식되면 무언가를 수행하는 앱을 빌드하려고합니다. 터치 인식은 백그라운드에서 서비스로 실행되는 스레드입니다.
나는 똑같은 문제가 있었고 마침내 그것을 알아 냈습니다! 이 게시물 덕분에 시스템 오버레이 창 만들기 (항상 맨 위에) . 오버레이 대신 경고 창을 사용해야합니다 (이는 Andoid ICS에서도 사용할 수 있음을 의미 함).
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
그런 다음 다음과 같이 GestureListener를 연결하면됩니다.
GestureDetector gestureDetector = new GestureDetector(this, new AwesomeGestureListener());
View.OnTouchListener gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
overlayView.setOnTouchListener(gestureListener);
예이!
흥미로운 질문입니다. 나는 그들이 어떻게했는지 모르고 글로벌 터치 리스너가 없다는 것을 알려주는 Google 그룹 게시물을 찾았습니다. 하지만 어쨌든 아이디어가 있습니다 ...
누군가가 서비스에서 팝업 창을 표시하는 데 성공한 이 게시물을 찾았 습니다 . 팝업을 투명하고 전체 화면으로 만들면 터치 인터셉터 를 설정할 수 있으므로 터치 를 캡처 할 수 있습니다.
편집 : 당신이 그것을 시도 할 때 결과를보고하십시오, 이것이 작동하는지 아는 것이 흥미로울 것입니다 ...
나는 가능한 모든 솔루션을 테스트했지만 일부는 화면을 frozed 한 터치 이벤트를 발생시키지 않았습니다.
그래서 리버스 엔지니어링을했고 이제는 작동하는 솔루션을 게시했습니다.
WindowManager.LayoutParams params = new android.view.WindowManager.LayoutParams(0, 0, 0, 0, 2003, 0x40028, -3);
View mView = new View(this);
mView.setOnTouchListener(this);
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);
API 21과 nexus 5에서이를 테스트했고 시스템에서 터치 이벤트가 발생했을 때 서비스에서 기록 할 수있었습니다. 그러나 MotionEvent 객체 내부의 데이터 (예 : 좌표)는 내 앱의 패키지로 보이는 것의 외부인 경우 0.0을 반환합니다.
서비스가있는 앱의 활동이 아닐 때 event.getX (), event.getY () 및 event.getPressure ()가 0.0을 반환하는 이유가 궁금합니다.
편집하다
이 솔루션은 다른 리스너가 서비스에 의해 캡처 된 터치 이벤트를 수신하는 것을 방지하지 않습니다.
public boolean onTouch(View v, MotionEvent e){
Log.d(LOG_TAG, "Touch event captured");
return false;
false를 반환하면 다른 리스너가 이벤트를받을 수 있습니다.
편집 2
분명히 OS의 입력 디스패처는 현재 활동과 리스너가 UID를 공유하지 않는 경우 좌표와 압력을 0으로 설정합니다. 여기에 소스가 있습니다.
많은 SO 스레드를 검색했지만 보안상의 이유로 시스템의 모든 패키지에 대해 이것이 가능하다고 생각하지 않습니다. 그것은 확실히 당신 자신의 앱을위한 것입니다.
WindowManager
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
플로팅 / 오버레이 레이아웃
floatyView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate
(R.layout.floating_view, null);
floatyView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d(TAG, "event.x " + event.getX());
Log.d(TAG, "event.y " + event.getY());
if (event.getAction() == MotionEvent.ACTION_UP) {
v.performClick();
}
return false;
}
});
형세
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@android:color/transparent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
참고 URL : https://stackoverflow.com/questions/6714020/how-can-a-service-listen-for-touch-gestures-events
'IT Share you' 카테고리의 다른 글
입력 끝 잭슨 파서로 인해 매핑 할 콘텐츠가 없습니다. (0) | 2020.12.05 |
---|---|
변수의 전체 유형 결정 (0) | 2020.12.05 |
SQL을 Linq 왼쪽 조인으로 변환 (0) | 2020.12.04 |
Graphviz : 전체 그래프의 글꼴을 변경 하시겠습니까? (0) | 2020.12.04 |
Vagrant 공유 및 동기화 폴더 (0) | 2020.12.04 |