Ho un servizio che avvia una sovrapposizione di sistema. Quando l'overlay è visibile, voglio che sia tangibile/rilevare tocchi, ma voglio preservare l'interazione con lo schermo dietro di esso (con dietro intendo l'attività sottostante, ad esempio l'overlay).Perché la sovrapposizione del sistema è in grado di catturare tutti i tocchi (non è possibile alcuna interazione con la vista sottostante)
Il mio overlay è un bitmap/PNG di 128x128px. Viene disegnato e quando clicco, ricevo il TOUCH! log, che è buono. Ma anche quando clicco su qualsiasi altra parte dello schermo (oltre all'overlay) ottengo il TOUCH! log e nessuna interazione con lo schermo sottostante è possibile.
Qui sono le parti del mio codice:
principale attività per avviare il servizio
buttonStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// start Service and return to Homescreen
Intent i = new Intent(MainActivity.this, MyService.class);
startService(i);
Intent newActivity = new Intent(Intent.ACTION_MAIN);
newActivity.addCategory(Intent.CATEGORY_HOME);
newActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newActivity);
}
});
Servizio/Mostra overlay
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
myOverlay = new Overlay(MyService.this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.TOP;
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(myOverlay, params);
myOverlay.setAnimation(new Waiting(MyService.this, 0, 0));
myOverlay.postInvalidate();
return super.onStartCommand(intent, flags, startId);
}
Overlay
public MyOverlay(Context context) {
super(context);
this.context = context;
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.i("TOUCH!", event.getAction() + ", x:"+event.getX()+", y:"+event.getY());
return false;
}
});
}
Cosa sto sbagliando? Ho provato anche WindowManager.LayoutParams.TYPE_PHONE invece di WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, ma lo stesso comportamento.
Non sto utilizzando il flag FLAG_WATCH_OUTSIDE_TOUCH, quindi perché i tocchi non sono registrati accanto all'overlay?
EDIT
Sembra che ho trovato il problema, ma ancora non so come risolverlo se ... L'immagine visualizzata nella sovrapposizione è molto piccolo e non il problema, ma (!) la sovrapposizione stessa è a schermo intero
ho aggiunto il seguente registro alla sovraimpressione/onTouch() evento:
Log.i("TOUCH!", "View: "+v.toString() +", size="+ v.getWidth()+"/"+v.getHeight());
che poi mi dice Vista: package.overlay.myOverlay, size = 480/762
Ora ho provato a forzarlo a non essere a schermo pieno aggiungendo la seguente riga nel Servizio:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
myOverlay = new Overlay(MyService.this);
//HERE
myOVerlay.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.TOP;
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(myOverlay, params);
myOverlay.setAnimation(new Waiting(MyService.this, 0, 0));
myOverlay.postInvalidate();
return super.onStartCommand(intent, flags, startId);
}
Ma non aiuta ... ancora myoverlay ha la dimensione di 480x762 ... Perché è così grande e come posso ottenere che abbia le dimensioni dell'immagine contenuta?
Quanto è grande il tuo overlay? Copre l'intero layout sottostante? È una cosa trasparente? – abbath
"ma voglio preservare l'interazione con lo schermo dietro di esso" - fortunatamente, questo non è più possibile a partire da Android 4.0.3, per prevenire attacchi di tipo "tapjacking", almeno per i tocchi sulla sovrapposizione stessa. Una sovrapposizione può ricevere eventi di tocco (e quelli che non vengono inoltrati insieme) o non ricevere eventi di tocco (simili a un 'Toast'). – CommonsWare
@abbath È una bitmap 128x128 px disegnata su una tela. Ha uno sfondo trasparente, sì, il che significa che probabilmente dovrei renderlo opaco per verificare se è davvero così piccolo ... lo proverò –