Android双屏异显以及原理分析
副屏顯示
android設(shè)備可以開啟模擬副屏,通過Presentation實(shí)現(xiàn)模擬副屏的畫面繪制。
進(jìn)入設(shè)置的開發(fā)者選項(xiàng),找到繪圖-模擬輔助顯示設(shè)備(英文為Simulate secondary displays)。
選擇輔助設(shè)備的分辨率。
需要申請顯示在其他應(yīng)用上層的權(quán)限,
跳轉(zhuǎn)設(shè)置以授權(quán):
if (!Settings.canDrawOverlays(this)) {Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));startActivityForResult(intent, 520);}接著初始化Presentation,代碼如下
private void initPresentation() {Display[] displays =mDisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);if (displays != null && displays.length > 0) {Display display = displays[0];mCustomPresentation = new CustomPresentation(this, display);mCustomPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);mCustomPresentation.setOnDismissListener(new DialogInterface.OnDismissListener() {@Overridepublic void onDismiss(DialogInterface dialogInterface) {Log.d(TAG, "onDismiss");}});mCustomPresentation.show();} else {Toast.makeText(this, "無副屏", Toast.LENGTH_SHORT).show();}}完整代碼如下:
package com.example.secondarydisplays;import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.util.Log; import android.view.Display; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.Toast;import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity implements View.OnClickListener {private static final String TAG = MainActivity.class.getSimpleName();protected CustomPresentation mCustomPresentation;private DisplayManager mDisplayManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button btnShow = findViewById(R.id.btn_show);Button btnDismiss = findViewById(R.id.btn_dismiss);btnShow.setOnClickListener(this);btnDismiss.setOnClickListener(this);mDisplayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);checkPermission();}private void checkPermission() {//需要顯示在其他應(yīng)用上層的權(quán)限,跳轉(zhuǎn)設(shè)置授權(quán)if (!Settings.canDrawOverlays(this)) {Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));startActivityForResult(intent, 520);} else {initPresentation();}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == 520 && resultCode == RESULT_OK) {if (Settings.canDrawOverlays(this)) {initPresentation();}}}private void initPresentation() {Display[] displays =mDisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);if (displays != null && displays.length > 0) {Display display = displays[0];mCustomPresentation = new CustomPresentation(this, display);mCustomPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);mCustomPresentation.setOnDismissListener(new DialogInterface.OnDismissListener() {@Overridepublic void onDismiss(DialogInterface dialogInterface) {Log.d(TAG, "onDismiss");}});mCustomPresentation.show();} else {Toast.makeText(this, "無副屏", Toast.LENGTH_SHORT).show();}}@Overridepublic void onClick(View view) {int id = view.getId();if (id == R.id.btn_show) {if (mCustomPresentation != null && mCustomPresentation.getDisplay().isValid()) {mCustomPresentation.show();} else {checkPermission();}} else if (id == R.id.btn_dismiss) {if (mCustomPresentation != null) {mCustomPresentation.dismiss();}}} }通過Presentation.show()和Presentation.dismiss()來控制畫面顯示,當(dāng)前副屏是否有效可通過Presentation.getDisplay().isValid()方法判斷。
自定義CustomPresentation 代碼如下:
當(dāng)副屏移除時(shí)回調(diào)onDisplayRemoved方法,同時(shí)Presentation.getDisplay().isValid()返回false。
可自定義布局,副屏將顯示自定義布局內(nèi)容。
可通過SurfaceView渲染地圖資源,顯示效果如下:
可顯示的內(nèi)容多樣,根據(jù)需求顯示內(nèi)容。Presentation繼承Dialog,屬于特殊的Dialog,它的目的是顯示內(nèi)容到第二屏幕。
Presentation依附在主屏的Activity上,所以Activity被銷毀Presentation也不會(huì)再顯示,主副屏內(nèi)容會(huì)再次恢復(fù)成相同的頁面。當(dāng)然也可以依附在Service上,就不會(huì)出現(xiàn)Activity銷毀后Presentation也銷毀的問題。
可應(yīng)用車載智能座艙多屏交互或者平板與手機(jī)設(shè)備的背屏顯示,依賴系統(tǒng)驅(qū)動(dòng)和芯片實(shí)現(xiàn)界面的渲染。
基本原理
DisplayManagerService 啟動(dòng)后從SurfaceFlinger當(dāng)中獲取到系統(tǒng)的Display信息,根據(jù)Display得到對應(yīng)的Context,依附應(yīng)用程序組件中,通過DisplayContext并獲得對應(yīng)配置Surface,對應(yīng)于SurfaceFlinger中的Layer。再得到Display對應(yīng)的WindowManager,通過addWindow函數(shù),WMS首先找到窗口所在的Display,創(chuàng)建WindowState,然后將窗口加到Display中的WindowLst當(dāng)中。SurfaceFlinger需要利用HWC輸出到具體的Display設(shè)備中。
Hardware Composer HAL (HWC) 是 SurfaceFlinger 用來將 Surface 合成到屏幕。
SurfaceFlinger是一個(gè)系統(tǒng)服務(wù),其作用是接受來自多個(gè)源的Buffer數(shù)據(jù),對它們進(jìn)行合成,然后發(fā)送到顯示設(shè)備進(jìn)行顯示。
總結(jié)
以上是生活随笔為你收集整理的Android双屏异显以及原理分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 4.7 网络命令
- 下一篇: ora-12514TNS 监听程序当前无