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;
- 對小球增加拖動事件,主要是在 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!