Sistem yer paylaşımı penceresi oluşturma (her zaman üstte)


285

Her zaman tüm pencerelerin üstünde kalır her zaman op-top düğmesi / tıklanabilir görüntü oluşturmaya çalışıyorum.

Kavramın kanıtı

Başarılı oldum ve şimdi çalışan bir hizmetim var. Kullanıcı her zaman ekranın sol üst köşesinde bazı metinler görüntülerken kullanıcı diğer uygulamalarla normal şekilde serbestçe etkileşime girebilir.

Yaptığım şey alt sınıf ViewGroupve bayraklı kök pencere yöneticisine eklemek TYPE_SYSTEM_OVERLAY. Şimdi bu metnin yerine dokunma olayları alabilen bir düğme / tıklanabilir görüntü eklemek istiyorum. Bütün "onTouchEvent" geçersiz kılmayı denedim ViewGroupama herhangi bir olay almaz.

Her zaman üstte görüntüleme grubumun yalnızca belirli bölümlerinde nasıl etkinlik alabilirim? Nazikçe öneririz.

public class HUD extends Service {
    HUDView mView;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
        mView = new HUDView(this);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                0,
//              WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
//                      | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.RIGHT | Gravity.TOP;
        params.setTitle("Load Average");
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.addView(mView, params);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(getBaseContext(),"onDestroy", Toast.LENGTH_LONG).show();
        if(mView != null)
        {
            ((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(mView);
            mView = null;
        }
    }
}

class HUDView extends ViewGroup {
    private Paint mLoadPaint;

    public HUDView(Context context) {
        super(context);
        Toast.makeText(getContext(),"HUDView", Toast.LENGTH_LONG).show();

        mLoadPaint = new Paint();
        mLoadPaint.setAntiAlias(true);
        mLoadPaint.setTextSize(10);
        mLoadPaint.setARGB(255, 255, 0, 0);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText("Hello World", 5, 15, mLoadPaint);
    }

    @Override
    protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //return super.onTouchEvent(event);
        Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
        return true;
    }
}

2
@coreSOLO, umarım cevap alırsınız, tuhaf benzer sorularım yanıt alamadı. :) +1
st0le

3
@ st0le Çözümü bulana ve sizinle paylaşana kadar gece ve gündemi geçireceğime söz veriyorum :)
coreSOLO

1
@ st0le Tamam belki sen ve ben birlikte kazabiliriz, bana sorunuzun bağlantısını verebilir ve ne kadar ilerleme
kaydedebileceğinizi bildirebilirsiniz


3
Aramanız şaşırtıcı onDraw(). Bunun dispatchDraw()yerine geçersiz kılınmamalı mı? Bkz. Groups.google.com/forum/?fromgroups#!topic/android-developers/…
faizal

Yanıtlar:


158

Bu aptalca bir çözüm olabilir. Ama işe yarıyor. Eğer geliştirebilirseniz, lütfen bana bildirin.

OnCreate Hizmetinizin: WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCHBayrağı kullandım . Hizmetteki tek değişiklik budur.

@Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
        mView = new HUDView(this);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.RIGHT | Gravity.TOP;
        params.setTitle("Load Average");
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.addView(mView, params);
    }

Şimdi, her tıklama etkinliğini almaya başlayacaksınız. Bu nedenle, olay işleyicinizde düzeltmeniz gerekir.

ViewGroup dokunma etkinliğinizde

@Override
public boolean onTouchEvent(MotionEvent event) {

    // ATTENTION: GET THE X,Y OF EVENT FROM THE PARAMETER
    // THEN CHECK IF THAT IS INSIDE YOUR DESIRED AREA


    Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
    return true;
}

Ayrıca bu izni bildiriminize eklemeniz gerekebilir:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

1
@pengwang: hangi hataları alıyorsunuz? Bu kod bağımsız değildir, bunları uygun proje altında uygun dosya adlarıyla projenize yerleştirmeniz gerekir.
Sarwar Erfan

4
@pengwang: En basit uygulamayı burada bulabilirsiniz: docs.google.com/…
Sarwar Erfan

6
tüm kod doğru, benim hatamı buluyorum, bağlantıyı unutuyorum <kullanımları izin android: name = "android.permission.SYSTEM_ALERT_WINDOW" /> Sarwar Erfan Cevabınızı düzenlediğinizi düşünüyorum, daha harika olabilir
pengwang

1
Bu cevap bir şey dışında çok faydalıdır. Kodda kullanıldığı gibi, WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, belgelere göre "tam yukarı / aşağı / aşağı hareketini almayacak". Başka bir deyişle, çekme hareketlerini veya ACTION_DOWN dışında başka bir şeyi algılamak mümkün değildir. Sweat'ları tespit etmenin mümkün olduğunu biliyorum çünkü Wave Launcher bu benzer konsepti kullanıyor ve swipeleri tespit edebiliyorlar. Biri bana bunun nasıl çalıştığını açıklayabilir mi?
Brian

6
@SarwarErfan - Bunu 2.3 üzerinde mükemmel bir şekilde kullandım, ancak onTouch olayı Android 4.0, 1. 4.1'de faturalandırılmıyor. Lütfen yardım
Sanjay Singh

66

@Sam Lu'nun cevabını takiben, Android 4.x, belirli türlerin dış dokunma olaylarını dinlemesini engeller, ancak bazı türler, TYPE_SYSTEM_ALERT hala işi yapıyor.

Misal

    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
            PixelFormat.TRANSLUCENT);

    WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
    LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
    View myView = inflater.inflate(R.layout.my_view, null);
    myView.setOnTouchListener(new OnTouchListener() {
       @Override
       public boolean onTouch(View v, MotionEvent event) {
           Log.d(TAG, "touch me");
           return true;
       }
     });

    // Add layout to window manager
    wm.addView(myView, params);

İzinler

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

5
Benim ekran
askıda

Harika gönderi. Umarım bu, gelecek sürümlerde de devre dışı değildir.
Cookster

Animasyonlar üzerinde çalışmaz ... :( Ve 4.2.X üzerinde herhangi bir görünümde tıklamaları yakalayamıyor. Herhangi bir öneriniz var mı?
Kamran Ahmed

Çalışıyor ama bu kısayolu (yani Sistem Düzeyi Uyarısı) kullandığımda, Diğer iletişim kutuları gösterilmiyor. Neden ?
Chimu

@Arju ne demek istiyorsun? kaldırmaya mı çalışıyorsun?
amirlazarovich

18

Android 4.x ile başlayarak, Android ekibi yeni bir fonksiyon ekleyerek potansiyel bir güvenlik sorunu giderilmiştir adjustWindowParamsLw()o kadar yüksek olur ki FLAG_NOT_FOCUSABLE, FLAG_NOT_TOUCHABLEve kaldır FLAG_WATCH_OUTSIDE_TOUCHbayrakları içinTYPE_SYSTEM_OVERLAY Windows .

Yani, bir TYPE_SYSTEM_OVERLAYpencere ICS platformunda herhangi bir dokunma olayı almaz ve elbette kullanmak TYPE_SYSTEM_OVERLAYICS ve gelecekteki cihazlar için uygulanabilir bir çözüm değildir.


4
öyleyse alternatifler neler?
radhoo


13

Tooleap SDK'nın geliştiricilerinden biriyim . Ayrıca, geliştiricilere her zaman en üstteki pencerelerde ve düğmelerde görüntülenmeleri için bir yol sağlıyoruz ve benzer bir durumla uğraştık.

Buradaki yanıtların ele almadığı bir sorun, Android "Güvenli Düğmeler" sorusudur.

Güvenli düğmeler, filterTouchesWhenObscuredbir pencerenin altına yerleştirilirse, bu pencere herhangi bir dokunuş almasa bile etkileşimde bulunamayacakları anlamına gelir. Android dokümanlarından alıntı:

Görünümün penceresi başka bir görünür pencere tarafından gizlendiğinde dokunmaların filtrelenip filtrelenmeyeceğini belirtir. True olarak ayarlandığında, görünümün penceresinin üstünde bir tost, iletişim kutusu veya başka bir pencere göründüğünde görünüm dokunuş almaz. Daha fazla ayrıntı için {@link android.view.View} güvenlik belgelerine bakın.

Üçüncü taraf uygulamalarını yüklemeye çalıştığınızda böyle bir düğmeye örnek olarak yükleme düğmesi verilebilir . Herhangi bir uygulama, görünüm düzenine aşağıdaki satırı eklerse böyle bir düğme görüntüleyebilir:

android:filterTouchesWhenObscured="true"

Bir "Güvenli Düğme" üzerinde her zaman üstte bir pencere görüntülerseniz, bir kaplama tarafından kapsanan tüm güvenli düğme parçaları, bu kaplama tıklanabilir olmasa bile herhangi bir dokunuşu işlemez. Dolayısıyla, böyle bir pencere görüntülemeyi planlıyorsanız, kullanıcının pencereyi taşıması veya kapatması için bir yol sağlamalısınız. Ve yer paylaşımınızın bir kısmı şeffafsa, kullanıcınızın kafası karışmış olabileceğini göz önünde bulundurun, temel uygulamadaki belirli bir düğmenin neden aniden onun için çalışmadığını.


Soruma cevap verebilir misiniz: stackoverflow.com/questions/28964771/…
Nauman Afzaal

Android 10'da üst üste bindirme görünümünün üstlerinde gösteremeyeceği bir etkinlik var, lütfen sebebini söyleyebilir veya sorumu burada görebilirsiniz çok yararlı olacaktır stackoverflow.com/questions/59598264/…
Mateen Chaudhry

12

HER ZAMAN ÜST GÖRÜNTÜ DÜĞMESİNDE ÇALIŞMAK

her şeyden önce ingilizcem için özür dilerim

i kodlarınızı düzenlemek ve onun dokunma olayını dinleyen çalışma görüntü düğmesi yapmak onun arka plan öğeleri dokunma kontrolü vermeyin.

ayrıca diğer öğelerin dışına dokunma dinleyicileri verir

düğme ayarları altta ve solda

değişiklikleri değiştirebilirsiniz ancak if öğesinde dokunma olayında cordinat'ları değiştirmeniz gerekir

import android.annotation.SuppressLint;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Toast;

public class HepUstte extends Service {
    HUDView mView;

    @Override
    public void onCreate() {
        super.onCreate();   

        Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();

        final Bitmap kangoo = BitmapFactory.decodeResource(getResources(),
                R.drawable.logo_l);


        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                kangoo.getWidth(), 
                kangoo.getHeight(),
                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                |WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                 PixelFormat.TRANSLUCENT);






        params.gravity = Gravity.LEFT | Gravity.BOTTOM;
        params.setTitle("Load Average");
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);



        mView = new HUDView(this,kangoo);

        mView.setOnTouchListener(new OnTouchListener() {


            @Override
            public boolean onTouch(View arg0, MotionEvent arg1) {
                // TODO Auto-generated method stub
                //Log.e("kordinatlar", arg1.getX()+":"+arg1.getY()+":"+display.getHeight()+":"+kangoo.getHeight());
                if(arg1.getX()<kangoo.getWidth() & arg1.getY()>0)
                {
                 Log.d("tıklandı", "touch me");
                }
                return false;
            }
             });


        wm.addView(mView, params);



        }



    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

}



@SuppressLint("DrawAllocation")
class HUDView extends ViewGroup {


    Bitmap kangoo;

    public HUDView(Context context,Bitmap kangoo) {
        super(context);

        this.kangoo=kangoo;



    }


    protected void onDraw(Canvas canvas) {
        //super.onDraw(canvas);


        // delete below line if you want transparent back color, but to understand the sizes use back color
        canvas.drawColor(Color.BLACK);

        canvas.drawBitmap(kangoo,0 , 0, null); 


        //canvas.drawText("Hello World", 5, 15, mLoadPaint);

    }


    protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
    }

    public boolean onTouchEvent(MotionEvent event) {
        //return super.onTouchEvent(event);
       // Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();

        return true;
    }
}

Bu işe yarar, ancak resmimin etrafında bir şey değil, resmimin tıklandığından nasıl emin olabilirim?
Liam W

@ LiamW, dokunuşun koordinatları bu örnekte kangaroo.getWidth () ile karşılaştırılmıştır. Resminizi nereye çizdiğinize bağlı olarak, kendi kodunuzla neyi karşılaştıracağınızı belirleyebilirsiniz.
Yevgeny Simkin

Çok hoş! Mükemmel çalışıyor.
Yevgeny Simkin

Bunun üzerinde çalıştığı minimum android sürümü nedir? Im bu yazma üzerinde çalışıyor ama android için yeni im çok yeni başlayanlar zaman yaşıyorum.
Noitidart

6

Aslında, TYPE_SYSTEM_OVERLAY yerine WindowManager.LayoutParams.TYPE_SYSTEM_ERROR'u deneyebilirsiniz. Bir saldırı gibi gelebilir, ancak her şeyin üstünde görünümü görüntülemenize ve yine de dokunma olayları almanıza izin verir.


1
Çalışmak için her şeyi denedim, ama başarı yok .... ama TYPE_SYSTEM_ERROR ekleyerek işi yaptı .... Aslında TYPE_SYSTEM_OVERLAY dokunma engelliyordu ..... + 1.
Robi Kumar Tomar

6

TYPE_SYSTEM_OVERLAY Bu sabit, API düzey 26'dan bu yana kullanımdan kaldırıldı. Bunun yerine TYPE_APPLICATION_OVERLAY kullanın. veya ** android 8 altındaki ve üstü kullanıcılar için

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
    LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}

5

Bunu dene. ICS'de iyi çalışıyor. Hizmeti durdurmak istiyorsanız, durum çubuğunda oluşturulan bildirimi tıklamanız yeterlidir.

 public class HUD extends Service
 {
    protected boolean foreground = false;
    protected boolean cancelNotification = false;
    private Notification notification;
    private View myView;
    protected int id = 0;
    private WindowManager wm;
    private WindowManager.LayoutParams params;
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public void onCreate() {
        super.onCreate();
       // System.exit(0);
        Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_SHORT).show();
        params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
        params.gravity=Gravity.TOP|Gravity.LEFT;
    wm = (WindowManager) getSystemService(WINDOW_SERVICE);
    inflateview();
    foregroundNotification(1);
    //moveToForeground(1,n,true);
    }     
   @Override
    public void onDestroy() {
        super.onDestroy();
        ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancel(0);
        Toast.makeText(getBaseContext(),"onDestroy", Toast.LENGTH_SHORT).show();
        if(myView != null)
        {
            ((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(myView);
            myView = null;
        }
    }
    protected Notification foregroundNotification(int notificationId) 
   {    
    notification = new Notification(R.drawable.ic_launcher, "my Notification", System.currentTimeMillis());    
        notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT | Notification.FLAG_ONLY_ALERT_ONCE;   
        notification.setLatestEventInfo(this, "my Notification", "my Notification", notificationIntent());          
        ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).notify(id, notification);            
        return notification;
    }
    private PendingIntent notificationIntent() {
        Intent intent = new Intent(this, stopservice.class);    
        PendingIntent pending = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);    
        return pending;
    }
    public void inflateview()
    {
         LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
            myView = inflater.inflate(R.layout.activity_button, null);
            myView.setOnTouchListener(new OnTouchListener() {
               @Override
               public boolean onTouch(View v, MotionEvent event) {
                   Toast.makeText(getBaseContext(),"onToasttt", Toast.LENGTH_SHORT).show();
                   return false;
               }
             });
            // Add layout to window manager
            wm.addView(myView, params); 
    }
}

GÜNCELLEME

Buradan örnek alın

Bir bindirme görünümü oluşturmak için LayoutParams'ı ayarlarken türü TYPE_SYSTEM_OVERLAY olarak ayarlayın.

Instead set it to TYPE_PHONE.

Use the following flags:

FLAG_NOT_TOUCH_MODAL

FLAG_WATCH_OUTSIDE_TOUCH

Bu benim için çalışmıyor, Ekranım arka planla etkileşime girmiyor. Bildiğiniz başka bir yöntem ...
Vinuthan

@Vinuthan Çıktınız nedir, cevap
veriyor mu

Hayır, yanıt vermiyor. Arka planla etkileşime girebilmem için ekranın yarısının üzerinde aktivitemi doldurdum, ancak arka planla etkileşime giremiyorum.
Vinuthan

FLAG_WATCH_OUTSIDE_TOUCH arka planla etkileşime girmenizi engelliyor
Richard Le Mesurier

1
TYPE_PHONE benim için çalıştı - dokunuşlar teslim edildi - en azından bir düğmeye dokunabiliyorum;) teşekkürler!
vir us

3

İşte basit bir çözüm, İhtiyacınız olan tek şey XML düzenini liste adaptörlerinde yaptığınız gibi şişirmek, sadece şişirmek için XML düzeni yapmak. İşte ihtiyacınız olan kod.

 public class HUD extends Service {
    View mView;

    LayoutInflater inflate;
    TextView t;
    Button b;

    @Override
    public void onCreate() {
        super.onCreate();   

        Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();


        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);

        Display display = wm.getDefaultDisplay();  get phone display size
        int width = display.getWidth();  // deprecated - get phone display width
        int height = display.getHeight(); // deprecated - get phone display height 


        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                width, 
                height,
                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                |WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                 PixelFormat.TRANSLUCENT);


        params.gravity = Gravity.LEFT | Gravity.CENTER;
        params.setTitle("Load Average");

        inflate = (LayoutInflater) getBaseContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        mView = inflate.inflate(R.layout.canvas, null);

        b =  (Button) mView.findViewById(R.id.button1);
        t = (TextView) mView.findViewById(R.id.textView1);
        b.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
            // TODO Auto-generated method stub
            t.setText("yes you click me ");
        }
       });

        wm.addView(mView, params);

        }



    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

}



1

Kodumu deneyin, en azından bindirme olarak bir dize verir, çok iyi bir düğme veya resim ile değiştirebilirsiniz. Bu benim ilk android uygulaması LOL olduğuna inanmayacaksınız. Her neyse, benden daha fazla android uygulaması ile deneyimli iseniz, lütfen deneyin

  • "new WindowManager.LayoutParams" içindeki parametre 2 ve 3'ü değiştirme
  • farklı bir olay yaklaşımı dene

i dolayısıyla ben ... hala ayrıntıları kıt bu sürdürmeye nihayetinde daha hiç bulabilirsiniz süresini değilim
st0le

1

Herkes hala bu iş parçacığı okuma ve bu çalışma elde edemiyorum, ben hareket olayı durdurmak için bu şekilde söylemek için üzgünüm android> = 4.2 hata ve düzeltme olarak kabul edilir.

ACTION_OUTSIDE olarak eylemi olmasına rağmen, ele aldığınız motion olayı getX ve getY'de 0 döndür. Bu, ekranda tüm hareket konumunu göremeyeceğiniz veya hiçbir şey yapamayacağınız anlamına gelir. Doktorun x ve y elde edeceğini söylediğini biliyorum, ama gerçek şu ki olmayacak. Bu tuş kaydediciyi engellemek gibi görünüyor.

Herhangi birinin geçici bir çözümü varsa, lütfen yorumunuzu bırakın.

ref: KitKat 4.4.2'de neden ACTION_OUTSIDE her defasında 0 döndürüyor?

https://code.google.com/p/android/issues/detail?id=72746


1

servisi kullanarak bunu başarabilirsiniz:

public class PopupService extends Service{

    private static final String TAG = PopupService.class.getSimpleName();
    WindowManager mWindowManager;
    View mView;
    String type ;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
//        registerOverlayReceiver();
        type = intent.getStringExtra("type");
        Utils.printLog("type = "+type);
        showDialog(intent.getStringExtra("msg"));
        return super.onStartCommand(intent, flags, startId);
    }

    private void showDialog(String aTitle)
    {
        if(type.equals("when screen is off") | type.equals("always"))
        {
            Utils.printLog("type = "+type);
            PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
            WakeLock mWakeLock = pm.newWakeLock((PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "YourServie");
            mWakeLock.acquire();
            mWakeLock.release();
        }

        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        mView = View.inflate(getApplicationContext(), R.layout.dialog_popup_notification_received, null);
        mView.setTag(TAG);

        int top = getApplicationContext().getResources().getDisplayMetrics().heightPixels / 2;

        LinearLayout dialog = (LinearLayout) mView.findViewById(R.id.pop_exit);
//        android.widget.LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) dialog.getLayoutParams();
//        lp.topMargin = top;
//        lp.bottomMargin = top;
//        mView.setLayoutParams(lp);

        final EditText etMassage = (EditText) mView.findViewById(R.id.editTextInPopupMessageReceived);

        ImageButton imageButtonSend = (ImageButton) mView.findViewById(R.id.imageButtonSendInPopupMessageReceived);
//        lp = (LayoutParams) imageButton.getLayoutParams();
//        lp.topMargin = top - 58;
//        imageButton.setLayoutParams(lp);
        imageButtonSend.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Utils.printLog("clicked");
//                mView.setVisibility(View.INVISIBLE);
                if(!etMassage.getText().toString().equals(""))
                {
                    Utils.printLog("sent");
                    etMassage.setText("");
                }
            }
        });

        TextView close = (TextView) mView.findViewById(R.id.TextViewCloseInPopupMessageReceived);
        close.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                hideDialog();   
            }
        });

        TextView view = (TextView) mView.findViewById(R.id.textviewViewInPopupMessageReceived);
        view.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                hideDialog();   
            }
        });

        TextView message = (TextView) mView.findViewById(R.id.TextViewMessageInPopupMessageReceived);
        message.setText(aTitle);

        final WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
        WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
        WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
//                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON ,
        PixelFormat.RGBA_8888);

        mView.setVisibility(View.VISIBLE);
        mWindowManager.addView(mView, mLayoutParams);
        mWindowManager.updateViewLayout(mView, mLayoutParams);

    }

    private void hideDialog(){
        if(mView != null && mWindowManager != null){
            mWindowManager.removeView(mView);
            mView = null;
        }
    }
}

1

@Sarwar Erfan'ın cevabı artık Android WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH ile pencereye artık dokunulmaz olmak için artık WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY ile görünüm eklenmesine izin vermediği için artık çalışmıyor.

Bu sorunun çözümünü buldum. Aşağıdaki soruya göz atabilirsiniz

WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY ile pencereye görünüm eklerken, dokunma olayı almıyor



@AhmadShahwaiz Lütfen bağlantıyı tekrar kontrol edin Burada bahsettiğiniz sorun için yorum ekledim
patilmandar2007

Evet, şimdi çalışıyor. Ancak startActivityForResult (intent, OVERLAY_REQ_CODE) çağrıldıktan sonra geri arama yanıtı alınamıyor; korumalı void onActivityResult (int requestCode, int sonuçKodu, Niyet verisi) yöntemi.
Ahmad Shahwaiz

@AhmadShahwaiz Bağlantıda belirtilen değişiklikler onActivityResult yönteminde geri çağrı aldığımız etkinlik kullanılarak çağrılmalıdır. Hizmette yukarıdaki izni kontrol ediyorsanız, hizmetten başlayabilmeniz için kukla şeffaf bir etkinlik eklemeniz gerekebilir; bu, kullanıcıdan İzin isteyebilir ve ardından onActivityResult kukla etkinliğinde kullanıcıdan sonuç alırsınız. Kullanıcıların yanıtına bağlı olarak pencereye görünüm eklemek ya da eklememek için hizmetinizi bilgilendirmeniz gerekecek
patilmandar2007

1

Bu eski bir Soru ama son zamanlarda Android Bubbles için bir destek var. Baloncuklar yakında piyasaya sürülecek, ancak şu anda geliştiriciler bunları kullanmaya başlayabilirler SYSTEM_ALERT_WINDOW. (Facebook Messenger ve MusiXMatch gibi uygulamalar aynı konsepti kullanır).

Kabarcıklar

Kabarcıklar Bildirim API'sı aracılığıyla oluşturulur, bildiriminizi normal şekilde gönderirsiniz. Eğer kabarcık olmasını istiyorsanız, ona fazladan veri eklemeniz gerekir. Bubbles hakkında daha fazla bilgi için Bubbles'ın resmi Android Geliştirici Kılavuzu'na gidebilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.