2014-05-13 59 views
2

我需要在任何正在運行的應用程序之上顯示系統覆蓋窗口。它工作正常,但只有當我的應用程序的活動在前臺。下面是我的代碼使用方法:Android系統覆蓋圖未顯示在我的應用程序之外

params = new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT, 
        WindowManager.LayoutParams.WRAP_CONTENT, 
        WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, 
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 
        WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | 
        WindowManager.LayoutParams.FLAG_DIM_BEHIND | 
        WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | 
        WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | 
        WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | 
        WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD, 
        PixelFormat.TRANSLUCENT); 

params.gravity = Gravity.CENTER | Gravity.TOP; 
params.dimAmount = 0.3f; 
wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE); 

    mainAlertView = View.inflate(ctx, R.layout.system_alert_view, null); 

    wm.addView(mainAlertView, params); 

視圖添加到窗口管理器包含了空的LinearLayout,而我在運行時添加子視圖:

mainAlertLayout.addView(childView); 

清單XML定義SYSTEM_ALERT_WINDOW權限:

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

當我的活動在前臺運行時,這一切都非常有效。只要我切換到任何其他應用程序或主屏幕,不顯示重疊。我調試了代碼,它確實運行了wm.addView(),並且沒有拋出任何異常。我也玩過LayoutParams標誌(刪除KEEP_SCREEN_ON和相關的等),但沒有任何區別。

的是Android 4.4.2 FWIW

+0

我記得,當我試圖做的那些東西,只要我還記得,在'上下文'必須是應用程序上下文。我不能成爲活動。你在用什麼? – Budius

+0

「ctx」包含主要活動getApplicationContext()返回的內容,即調用 – rootkit

+0

即應用程序上下文。祝你好運。 – Budius

回答

0

問題是,我是跑addView()調用在主視圖的post()方法:

mainView.post(new Runnable() { 
public void run() { 
    wm.add(mainView); 
} 
); 

相反,如果我只是運行在主線程中正常工作。我用de.greenrobot.eventbus和非常簡單的發佈了Runnable到事件總線,並確保其在主線程中執行:

public void onEventMainThread(UIRunnableEvent event) { 
    event.r.run(); 
} 

public static class UIRunnableEvent { 
    protected Runnable r; 

    protected UIRunnableEvent(Runnable r) { 
     this.r = r; 
    } 
} 
5

你需要創建一個service保持系統的覆蓋(警告)顯示,即使你的應用程序關閉。

創建一個簡單的服務,我將打電話爲FloatingService,當調用onStartCommand時,將顯示覆蓋(警報)。返回START_STICKY以保持服務在後臺運行。

public class FloatingService extends Service { 
     private WindowManager windowManager; 
     private View floatingView; 

    WindowManager.LayoutParams params; 
    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
     } 

    @Override 
    public int onStartCommand(Intent intent, int flag, int startId){ 
     // show the alert her 
     windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); 
     // use your custom view here 
     floatingView = View.inflate(getBaseContext(),R.layout.floating_layout,null);   //floatingView.setOnTouchListener(mOnTouchListener); 
     params = new WindowManager.LayoutParams(
       WindowManager.LayoutParams.WRAP_CONTENT, 
       WindowManager.LayoutParams.WRAP_CONTENT, 
       WindowManager.LayoutParams.TYPE_PHONE, 
       WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD, 
       PixelFormat.TRANSLUCENT); 
      params.gravity = Gravity.CENTER | Gravity.CENTER; 
     // add the view to window manger 
     windowManager.addView(floatingView, params); 
     return START_STICKY; 
    } 
} 

添加監聽器視圖,以便需要

 floatingView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       windowManager.removeView(floatingView); 
       floatingView = null; 
      } 
     }); 

當最後你可以關閉覆蓋(警報),在明顯的

<service android:name="com.example.app.services.FloatingService" /> 

而且System Alert許可

註冊服務
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> 
+0

服務的問題是它不一定在UI線程中運行,因此我無法直接使用addView調用。無論哪種方式,我不明白爲什麼它必須是服務?我已經有一個後臺服務運行,通過eventbus與我的「系統覆蓋」管理器進行通信,是不是夠了? – rootkit

+0

我想通了。我會發布我自己的答案,但是提高了你的清晰度和廣泛的指示 – rootkit

相關問題