एक सिस्टम ओवरले विंडो बनाना (हमेशा शीर्ष पर)


285

मैं हमेशा ऑप-टॉप बटन / क्लिक करने योग्य छवि बनाने की कोशिश कर रहा हूं, जो हर समय सभी खिड़कियों के ऊपर रहता है।

अवधारणा का प्रमाण है

मैं सफल रहा हूं और अभी एक सेवा चल रही है। सेवा हर समय स्क्रीन के ऊपरी बाएँ कोने पर कुछ पाठ प्रदर्शित करती है जबकि उपयोगकर्ता स्वतंत्र रूप से बाकी ऐप्स के साथ सामान्य तरीके से बातचीत कर सकता है।

मैं जो कर रहा हूं वह उपवर्ग है ViewGroupऔर इसे झंडे के साथ रूट विंडो मैनेजर में जोड़ें TYPE_SYSTEM_OVERLAY। अब मैं इस पाठ के स्थान पर एक बटन / क्लिक करने योग्य छवि जोड़ना चाहता हूं जो स्वयं पर स्पर्श की घटनाओं को प्राप्त कर सकता है। मैंने पूरे के लिए "onTouchEvent" को ओवरराइड करने की कोशिश की, ViewGroupलेकिन यह किसी भी घटना को प्राप्त नहीं करता है।

मैं अपने हमेशा-ऑन-टॉप व्यू समूह के कुछ हिस्सों पर ही ईवेंट कैसे प्राप्त कर सकता हूं? कृपया सुझाव दें।

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, मुझे आशा है कि आपको जवाब मिल जाएगा, मेरे अजीब तरह के सवालों का कोई जवाब नहीं मिला। :) +1
st0le

3
@ st0le मैं वादा करता हूं कि मैं अपना रात और दिन तब तक व्यतीत करूंगा जब तक कि मैं समाधान नहीं
ढूंढता

1
@ st0le ठीक है, शायद आप और मैं इसे एक साथ खोद सकते हैं, मुझे अपने सवाल का लिंक दे सकते हैं और मुझे बता सकते हैं कि आप कितनी प्रगति कर पाए ...
coreSOLO

इसकी ज्यादा नहीं: - \ stackoverflow.com/questions/3732935/…
st0le

3
यह आश्चर्य की बात है कि आपका onDraw()कहा जा रहा है। dispatchDraw()इसके बजाय ओवरराइड नहीं किया जाना चाहिए ? देखें groups.google.com/forum/?fromgroups#!topic/android-developers/...
फैजल

जवाबों:


158

यह एक बेवकूफ समाधान हो सकता है। लेकिन यह काम करता है। यदि आप इसे सुधार सकते हैं, तो कृपया मुझे बताएं।

आपकी सेवा का लाभ: मैंने WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCHध्वज का उपयोग किया है । यह सेवा में एकमात्र परिवर्तन है।

@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);
    }

अब, आपको प्रत्येक क्लिक इवेंट मिलना शुरू हो जाएगा। तो, आपको अपने ईवेंट हैंडलर में सुधार करना होगा।

आपके व्यूग्रुप टच इवेंट में

@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;
}

इसके अलावा आपको अपनी अनुमति को अपनी घोषणा में जोड़ने की आवश्यकता हो सकती है:

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

1
@ पेंगवांग: आपको क्या त्रुटियां हो रही हैं? यह कोड स्वतंत्र नहीं है, आपको उन्हें उपयुक्त प्रोजेक्ट के तहत उपयुक्त फ़ाइल नामों के साथ अपनी परियोजना में रखने की आवश्यकता है।
सरवर इरफान

4
@ पेंगवांग: यहां सरलतम कार्यान्वयन खोजें: docs.google.com/…
सरवर इरफान

6
पूरा कोड सही है, मुझे अपनी गलती लगती है, मैं लिंक भूल जाता हूं <उपयोग-अनुमति एंड्रॉइड: नाम = "android.permission.SYSTEM_ALERT_WINDOW" /> सरवर इरफान मुझे लगता है कि आप अपना उत्तर संपादित करते हैं, यह अधिक अद्भुत हो सकता है
पेंगवांग

1
यह उत्तर एक बात को छोड़कर, बहुत सहायक है। जैसा कि कोड में इस्तेमाल किया गया है, WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, प्रलेखन के अनुसार, "पूर्ण अप / मूव / डाउन जेस्चर प्राप्त नहीं होगा"। दूसरे शब्दों में, ACTION_DOWN के अलावा स्वाइप या किसी अन्य चीज़ का पता लगाना संभव नहीं है। वैसे मुझे पता है कि स्वाइप्स का पता लगाना संभव है क्योंकि वेव लॉन्चर इस समान अवधारणा का उपयोग करता है और वे स्वाइप्स का पता लगाने में सक्षम हैं। क्या कोई मुझे समझा सकता है कि यह कैसे काम करता है?
ब्रायन

6
@SarwarErfan - मैंने इसका इस्तेमाल पूरी तरह से 2.3 पर किया है, लेकिन ऑनटच इवेंट को एंड्रॉइड 4.0, 1 और 4.1 पर लागू नहीं किया गया है। कृपया मदद करें
संजय सिंह

66

@Sam लू के उत्तर के बाद, वास्तव में Android 4.x कुछ प्रकारों को बाहरी स्पर्श घटनाओं को सुनने से रोकता है, लेकिन कुछ प्रकार, जैसे TYPE_SYSTEM_ALERT, अभी भी काम करते हैं।

उदाहरण

    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);

अनुमतियां

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

5
इसकी स्क्रीनिंग को मेरी फांसी बना दिया गया .. कोई भी विचार
विश्वनाथ लीक्षमान

महान पद। उम्मीद है कि यह भविष्य के रिलीज में भी अक्षम नहीं है।
कुकस्टर

एनिमेशन इस पर काम नहीं करेगा ... :( और यह 4.2.X पर किसी भी दृश्य में क्लिक को पकड़ने में असमर्थ है। किसी भी सुझाव?
कामरान अहमद

यह काम करता है लेकिन जब मैं उस शॉर्टकट (यानी सिस्टम लेवल अलर्ट) का उपयोग कर रहा हूं, तो अन्य संवाद नहीं दिखाए जा रहे हैं। क्यों ?
चिमु

@ आरजू तुम्हारा क्या मतलब है? क्या आप इसे हटाने की कोशिश कर रहे हैं?
amirlazarovich

18

एंड्रॉइड 4.x से शुरू करते हुए, एंड्रॉइड टीम ने एक नया फ़ंक्शन जोड़कर एक संभावित सुरक्षा समस्या को ठीक किया adjustWindowParamsLw(), जिसमें यह विंडोज़ के लिए झंडे जोड़ देगा FLAG_NOT_FOCUSABLE, FLAG_NOT_TOUCHABLEऔर हटा देगा ।FLAG_WATCH_OUTSIDE_TOUCHTYPE_SYSTEM_OVERLAY

अर्थात्, TYPE_SYSTEM_OVERLAYICS प्लेटफ़ॉर्म पर किसी भी विंडो को कोई टच इवेंट नहीं मिलेगा और निश्चित रूप से, TYPE_SYSTEM_OVERLAYICS और भविष्य के उपकरणों के लिए उपयोग करने योग्य समाधान नहीं है।


4
तो फिर विकल्प क्या हैं?
राधू

1
ICS के बारे में यह सवाल देखें: stackoverflow.com/questions/9656185/type-system-overlay-in-ics
clemp6r

13

मैं टूलक एसडीके के डेवलपर्स में से एक हूं । हम डेवलपर्स को हमेशा शीर्ष खिड़कियों और बटनों पर प्रदर्शित करने का एक तरीका प्रदान करते हैं, और हमने एक समान स्थिति से निपटा है।

एक समस्या जिसका जवाब यहां नहीं दिया गया है वह है एंड्रॉइड "सिक्योर बटन"।

सुरक्षित बटन में वह filterTouchesWhenObscuredसंपत्ति होती है जिसका अर्थ है कि उनके साथ बातचीत नहीं की जा सकती है, अगर एक खिड़की के नीचे रखा जाता है, भले ही उस खिड़की को कोई स्पर्श न मिले। Android दस्तावेज़ का उद्धरण:

निर्दिष्ट करता है कि फ़िल्टर को तब स्पर्श करें जब दृश्य की विंडो किसी अन्य दृश्यमान विंडो द्वारा अस्पष्ट हो। जब सही पर सेट किया जाता है, तो जब भी टोस्ट, डायलॉग या अन्य विंडो दृश्य की विंडो के ऊपर दिखाई देती है, तो दृश्य स्पर्श प्राप्त नहीं करेगा। अधिक विवरण के लिए {@link android.view.View} सुरक्षा दस्तावेज देखें।

जब आप थर्ड पार्टी एप इंस्टॉल करने का प्रयास करते हैं तो ऐसे बटन का एक उदाहरण इंस्टाल बटन होता है। निम्न पंक्ति में व्यू लेआउट में जोड़ने पर कोई भी ऐप इस तरह का बटन प्रदर्शित कर सकता है:

android:filterTouchesWhenObscured="true"

यदि आप एक "सुरक्षित बटन" पर हमेशा एक-पर-ऊपर की खिड़की दिखाते हैं, तो एक उपरिशायी द्वारा कवर किए गए सभी सुरक्षित बटन भाग किसी भी स्पर्श को संभाल नहीं पाएंगे, भले ही वह ओवरले क्लिक करने योग्य न हो। इसलिए यदि आप ऐसी विंडो प्रदर्शित करने की योजना बना रहे हैं, तो आपको उपयोगकर्ता को इसे स्थानांतरित करने या खारिज करने का एक तरीका प्रदान करना चाहिए। और यदि आपके ओवरले का एक हिस्सा पारदर्शी है, तो ध्यान रखें कि आपका उपयोगकर्ता भ्रमित हो सकता है कि अंतर्निहित ऐप में एक निश्चित बटन उसके लिए अचानक काम क्यों नहीं कर रहा है।


क्या आप मेरे प्रश्न का उत्तर दे सकते हैं: stackoverflow.com/questions/28964771/…
Nauman Afzaal

एंड्रॉइड 10 में कुछ गतिविधि है जो ओवरले दृश्य उनके ऊपर नहीं दिखा सकता है क्या आप इसका कारण बता सकते हैं या मेरा प्रश्न यहां देख सकते हैं यह बहुत ही उपयोगी stackoverflow.com/questions/59598264/…
मतिन चौधरी

12

शीर्ष छवि बटन पर हमेशा काम कर रहा है

सबसे पहले मेरी अंग्रेजी के लिए खेद है

मैं आपके कोड्स को संपादित करता हूं और काम करने वाला इमेज बटन बनाता हूं जो उनके टच इवेंट को सुनता है, अपने बैकग्राउंड एलिमेंट्स को टच कंट्रोल नहीं देता है।

यह अन्य तत्वों में से स्पर्श श्रोताओं को भी देता है

बटन अलिंगमेंट नीचे और बाएं हैं

आप आरोपों का पीछा कर सकते हैं, लेकिन आपको अगर तत्व में स्पर्श घटना में कॉर्डिनेट्स का पीछा करने की आवश्यकता है

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;
    }
}

यह काम करता है, लेकिन मैं यह कैसे सुनिश्चित कर सकता हूं कि मेरी छवि पर क्लिक किया गया था और छवि के आसपास कुछ नहीं था?
लियाम डब्ल्यू।

@LiamW, स्पर्श के निर्देशांक की तुलना इस उदाहरण में kangaroo.getWidth () से की जाती है। आप अपनी छवि को आरेखित करने के आधार पर अपने स्वयं के कोड में इसकी तुलना करने के लिए क्या कर सकते हैं।
येवगेनी सिम्किन

बहुत अच्छा! अच्छी तरह से काम।
येवगेनी सिम्किन

यह काम करने वाला न्यूनतम Android संस्करण क्या है? Im इसे लिखने पर काम कर रहा हूं, लेकिन Android के लिए नया हूं इसलिए शुरुआती समय है।
Noitidart

6

दरअसल, आप TYPE_SYSTEM_OVERLAY की जगह WindowManager.LayoutParams.TYPE_SYSTEM_ERROR आज़मा सकते हैं। यह एक हैक की तरह लग सकता है, लेकिन यह आपको सब कुछ के शीर्ष पर दृश्य दिखाता है और अभी भी स्पर्श की घटनाओं को प्राप्त करता है।


1
मैंने इसे काम करने के लिए हर चीज़ की कोशिश की, लेकिन कोई सफलता नहीं मिली .... लेकिन TYPE_SYSTEM_ERROR को जोड़ने से काम चल गया .... वास्तव में TYPE_SYSTEM_OVERLAY स्पर्श को अवरुद्ध कर रहा था ..... + 1।
रॉबी कुमार तोमर

6

TYPE_SYSTEM_OVERLAY इस स्तर को API स्तर 26 के बाद से हटा दिया गया था। इसके बजाय TYPE_APPLICATION_OVERLAY का उपयोग करें। या नीचे और ऊपर Android 8 के उपयोगकर्ताओं के लिए **

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

5

इसे इस्तेमाल करे। आईसीएस में ठीक काम करता है। यदि आप सेवा को रोकना चाहते हैं, तो बस स्टेटसबार में उत्पन्न अधिसूचना पर क्लिक करें।

 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); 
    }
}

अपडेट करें

यहाँ नमूना

एक ओवरले दृश्य बनाने के लिए, जब LayoutParams DON'T टाइप करने के लिए टाइप करें TYPE_SYSTEM_OVERLAY सेट करें।

Instead set it to TYPE_PHONE.

Use the following flags:

FLAG_NOT_TOUCH_MODAL

FLAG_WATCH_OUTSIDE_TOUCH

यह मेरे लिए काम नहीं करता है, मेरी स्क्रीन पृष्ठभूमि के साथ बातचीत नहीं करती है। कोई और तरीका जो आप जानते हैं ...
विनुथन

@Vinuthan आपके आउटपुट को व्हाट्सएप करता है, यह जवाब देता है
विश्वनाथ लीक्षमान

नहीं, इसका कोई जवाब नहीं है। मैंने अपनी गतिविधि को आधे से ऊपर स्क्रीन पर रखा है ताकि मैं पृष्ठभूमि के साथ बातचीत कर सकूं, लेकिन मैं पृष्ठभूमि के साथ बातचीत नहीं कर सकता।
विनुथन

FLAG_WATCH_OUTSIDE_TOUCH आपको पृष्ठभूमि के साथ बातचीत करने से रोकता है
रिचर्ड ले मेसियर

1
TYPE_PHONE ने मेरे लिए काम किया - अब स्पर्श वितरित किए गए हैं - कम से कम मैं एक बटन टैप करने में सक्षम हूं;) धन्यवाद!
हमें

3

यहाँ कुछ सरल समाधान है, आपको बस XML लेआउट को फुलाए जाने की आवश्यकता है जैसे आप सूची एडेप्टर पर करते हैं, बस इसे बढ़ाने के लिए XML लेआउट बनाते हैं। यहाँ कोड है जो आपको चाहिए।

 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;
    }

}

3

एक पुस्तकालय मिला जो ऐसा करता है: https://github.com/recruit-lifestyle/FloatingView

रूट फ़ोल्डर में एक नमूना परियोजना है। मैंने इसे चलाया और यह आवश्यकतानुसार काम करता है। पृष्ठभूमि क्लिक करने योग्य है - भले ही वह दूसरा ऐप हो।

यहां छवि विवरण दर्ज करें


सिफारिश के लिए धन्यवाद, मैं बस इस महान परियोजना को खोजने की कोशिश कर रहा था।
जूल


1

अच्छी तरह से मेरे कोड का प्रयास करें, कम से कम यह आपको ओवरले के रूप में एक स्ट्रिंग देता है, आप इसे बहुत अच्छी तरह से एक बटन या एक छवि के साथ बदल सकते हैं। आपको विश्वास नहीं होगा कि यह मेरा पहला एंड्रॉइड ऐप LOL है। वैसे भी अगर आप मेरे से अधिक एंड्रॉइड ऐप के साथ अनुभवी हैं, तो कृपया प्रयास करें

  • 2 और 3 "नए WindowManager.LayoutParams" में बदलते पैरामीटर
  • कुछ अलग घटना दृष्टिकोण की कोशिश करो

मैं अंततः इसे आगे बढ़ाने के लिए समय नहीं मिला, इसलिए मैं अभी भी इसके विवरण पर दुर्लभ हूँ ...
st0le

1

अगर कोई अभी भी इस थ्रेड को पढ़ रहा है और इस काम को पाने में सक्षम नहीं है, तो मुझे बहुत खेद है कि आपको इस तरह की गति की घटना को रोकना बग के रूप में माना जाता है और एंड्रॉइड> = 4.2 में ठीक किया जाता है।

गति की घटना जिसे आपने रोका था, हालांकि ACTION_OUTSIDE के रूप में कार्रवाई की है, getX और getY में 0 लौटाएं। इसका मतलब है कि आप स्क्रीन पर सभी मोशन पोजीशन नहीं देख सकते हैं और न ही आप कुछ कर सकते हैं। मुझे पता है कि डॉक्टर ने कहा कि यह x और y मिलेगा, लेकिन सच्चाई यह है कि यह नहीं होगा। ऐसा लगता है कि यह कुंजी लकड़हारे को अवरुद्ध करना है।

यदि किसी के पास वर्कअराउंड नहीं है, तो कृपया अपनी टिप्पणी छोड़ दें।

रेफ: ACTION_OUTSIDE किटकैट 4.4.2 पर हर बार वापस क्यों आता है?

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


1

सेवा का उपयोग करके आप इसे प्राप्त कर सकते हैं:

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 का जवाब किसी भी तरह से काम नहीं करता है क्योंकि Android WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY के साथ दृश्य जोड़ने की अनुमति नहीं देता है विंडो के लिए भी अब WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH के साथ नहीं देखा जा सकता है।

मुझे इस समस्या का हल मिल गया। आप निम्नलिखित प्रश्न में इसे देख सकते हैं

WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY के साथ विंडो में दृश्य जोड़ने पर, यह स्पर्श ईवेंट नहीं हो रहा है


आपका निर्दिष्ट समाधान
मार्शमैलो

@AhmadShahwaiz कृपया लिंक को फिर से देखें मैंने आपके द्वारा बताई गई समस्या के लिए टिप्पणी जोड़ी है
patilmandar2007

हां, अब इसका काम है। लेकिन startActivityForResult (इरादा, OVERLAY_REQ_CODE) कॉल करने के बाद कॉलबैक प्रतिक्रिया नहीं मिल रही; संरक्षित शून्य onActivityResult (int requestCode, int resultCode, आशय डेटा) विधि में।
अहमद शाहवाइज़

लिंक में वर्णित @AhmadShahwaiz परिवर्तन का उपयोग करते हुए बुलाया जाना चाहिए जहां हमें onActivityResort पद्धति में कॉलबैक मिलता है। यदि आप सेवा में अनुमति से ऊपर की जाँच कर रहे हैं, तो आपको सेवा से शुरू करने के लिए एक डमी पारदर्शी गतिविधि जोड़ने की आवश्यकता हो सकती है, जो उपयोगकर्ता से अनुमति के लिए पूछ सकती है और फिर onActivityResult डमी गतिविधि में आपको उपयोगकर्ता से परिणाम मिलेगा। इसके बाद आपको विंडो को देखने के लिए अपनी सेवा को सूचित करने की आवश्यकता होगी या उपयोगकर्ता की प्रतिक्रिया पर निर्भर नहीं
करेगा

1

यह एक पुराना प्रश्न है लेकिन हाल ही में एंड्रॉइड में बुलबुले के लिए एक समर्थन है। बुलबुले जल्द ही लॉन्च होने वाले हैं, लेकिन वर्तमान में डेवलपर्स उनका उपयोग करना शुरू कर सकते हैं। वे उपयोग करने के लिए एक विकल्प के रूप में डिज़ाइन किए गए हैं SYSTEM_ALERT_WINDOW। (Facebook Messenger और MusiXMatch समान अवधारणा का उपयोग) जैसे ऐप्स।

बुलबुले

बुलबुले अधिसूचना एपीआई के माध्यम से बनाए जाते हैं, आप अपनी अधिसूचना को सामान्य रूप में भेजते हैं। यदि आप इसे बुलबुला बनाना चाहते हैं, तो आपको इसके लिए कुछ अतिरिक्त डेटा संलग्न करना होगा। बबल के बारे में अधिक जानकारी के लिए आप बबल्स पर आधिकारिक Android डेवलपर गाइड पर जा सकते हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.