1. 程式人生 > >Android 使用 WindowManager 實現懸浮窗監控 cpu 溫度

Android 使用 WindowManager 實現懸浮窗監控 cpu 溫度

前文概要
連續四篇介紹了車載設定,主要都是和原始碼相關,還未看過的,可以參考借鑑學習一下原始碼知識。車載設定–按鍵提示音

本文開始進入下一個篇章,主要是和 camera 相關,例如倒車,TV ,360 全景等,其主要實現原理是基於 WindowManager 來顯示全屏視窗,在視窗中載入 camera 傳遞的資料。基於此,有必要先介紹一下 WindowManager 和 camera 相關的知識點,本文先從 WindowManager 開始。

WindowManager 類結構

public interface WindowManager implements ViewManager

WindowManager 是視窗管理器,所有顯示視窗都可以通過它來控制。通常我們呼叫的是 WindowManager 繼承自基類的 addView 方法和 removeView 方法來顯示和隱藏視窗:

  • addView(View view, ViewGroup.LayoutParams params)
    Assign the passed LayoutParams to the passed View and add the view to the window. 用於新增一個視窗
  • removeView(View view) 移除一個視窗
  • updateViewLayout(View view, ViewGroup.LayoutParams params) 更新視窗的引數

WindowManager 主要是通過 Context.getSystemService(Context.WINDOW_SERVICE) 來獲取。

WindowManager.LayoutParams 引數介紹
WindowManager.LayoutParams 這個類用於提供懸浮窗所需的引數,其中有幾個經常會用到的變數:

  • x 值用於確定懸浮窗的位置,如果要橫向移動懸浮窗,就需要改變這個值。
  • y 值用於確定懸浮窗的位置,如果要縱向移動懸浮窗,就需要改變這個值。
  • gravity 值用於確定懸浮窗的對齊方式及設定 x 和 y 值的參考系。
  • format 值用於確定視窗背景遮罩點陣圖格式,預設為黑色,一般設定為半透明 (PixelFormat.TRANSLUCENT)
  • alpha 值用於確定這個視窗的透明值,1.0表示不透明,0.0表示全透明
  • width 值用於指定懸浮窗的寬度。
  • height 值用於指定懸浮窗的高度。
  • type 值用於確定視窗在螢幕上的顯示層次,值越高,顯示層次越高。一般設為 TYPE_PHONE,表示在所有應用程式之上,但在狀態列之下。
  • flags 值用於確定懸浮窗的行為,比如說不可聚焦,非模態對話方塊等等。

permission denied 解決辦法

1.建立懸浮窗這種窗體需要向用戶申請許可權才可以的,因此還需要在 AndroidManifest.xml中加入 。

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

2.手機端設定允許除錯應用在其他應用顯示懸浮窗。例如有以下提示:

android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl[email protected] -- permission denied for window type 2038
                                                                                        at android.view.ViewRootImpl.setView(ViewRootImpl.java:806)
                                                                                        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:373)
                                                                                        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:114)

那麼 將 type 改為TYPE_PHONE ,並且在手機端開啟 許可權管理–>懸浮窗管理–>除錯應用勾選。
這樣除錯應用就能顯示在其他應用之上。

懸浮窗示例
1. 對 WindowManager.LayoutParams 引數進行設定:

   mWindo wManager = (WindowManager) getApplication().getSystemService(Context.WINDOW_SERVICE);
        mLayoutParams = new WindowManager.LayoutParams();
        // 設定懸浮窗顯示層次,在應用層之上,狀態列之下
        mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
        //懸浮窗遮罩背景  半透明
        mLayoutParams.format = PixelFormat.TRANSLUCENT;
        // 懸浮窗曲奇方式,以螢幕左上角對齊
        mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
        mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
       //FLAG_NOT_TOUCH_MODAL不阻塞事件傳遞到後面的視窗
        mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
  1. 對小球增加拖動事件,主要是在 onTouch 方法中根據手指移動距離更新 WindowManager.LayoutParams 引數:
 mLlRoot.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        mStartX = (int) event.getRawX();
                        mStartY = (int) event.getRawY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        mEndX = (int) event.getRawX();
                        mEndY = (int) event.getRawY();
                        //getRawX是觸控位置相對於螢幕的座標,getX是相對於按鈕的座標
                        mLayoutParams.x = (int) event.getRawX() - mLlRoot.getMeasuredWidth() / 2;
                        mLayoutParams.y = (int) event.getRawY() - mLlRoot.getMeasuredHeight() / 2;
                        mWindowManager.updateViewLayout(mWindowView, mLayoutParams);
                        return true;


                }
                return false;
            }
        });

3.通過定時任務去獲取 CPU 溫度並顯示出來:

 private String getCputemp(){
        String path = "/sys/class/thermal/thermal_zone0/temp";
        StringBuffer sb = new StringBuffer();
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(path));
            String readline = "";

            while ((readline = br.readLine()) != null) {
                System.out.println("readline:" + readline);
                sb.append(readline);
            }
            br.close();
            Log.d("Bradley", "onCreate: "+sb.toString());

        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

總結
通過本文大致瞭解懸浮效果背後是通過 WindowManager 來新增 view 實現的,同時對 WindowManager.LayoutParams 引數有個大致瞭解,後續還會繼續講解 WindowManager 相關的文章,敬請期待!

happy a nice day!