我是靠谱客的博主 呆萌流沙,最近开发中收集的这篇文章主要介绍Android 副屏开发开发说明,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

  • 更新日志
  • 2020-03-07 初稿 MainActivity
  • 2021-11-02 更新优化版本客屏显示ScreenActivity

开发说明

Android中的副屏开发Android版本需要权限
涉及权限

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

activity_screen.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.thomas.android.base.screen.ScreenActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/change_presentation_data"
        android:onClick="changePresentationDataClick"/>


</LinearLayout>

副屏类似dialog和activity
CustomPresentation



import android.app.Presentation;
import android.content.Context;
import android.os.Bundle;
import android.view.Display;
import android.widget.TextView;

import com.thomas.android.base.two.R;

/**
 * 副屏
 */
public class CustomPresentation extends Presentation {
    private boolean isChange;
    private int changeCount;

    private TextView tv_vice_change;

    boolean isChange() {
        return isChange;
    }

    void setChange(){
        changeCount ++ ;
        tv_vice_change.setText(String.valueOf(changeCount));
    }


    CustomPresentation(Context outerContext, Display display) {
        super(outerContext, display);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_presentation);
        tv_vice_change = findViewById(R.id.tv_vice_change);

    }

    /**
     * 副屏发生改变调用(息屏触发)
     */
    @Override
    public void onDisplayChanged() {
        super.onDisplayChanged();
        isChange = true;
        dismiss();
    }
}

原本旧的显示客屏方式(MainActivity),不建议使用




package com.thomas.screen;

import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.media.MediaRouter;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;


import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;


/**
 * 不建议在onResume中处理客屏,延时操作虽然可行,但是无法灭屏再亮屏马上显示客屏
 */
public class MainActivity extends AppCompatActivity
{
    private DisplayManager displayManager;
    private MediaRouter mediaRouter;
    private CustomPresentation customPresentation;
    private boolean hasPermission;


    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ){
            displayManager = (DisplayManager) getSystemService(DISPLAY_SERVICE);
            mediaRouter = (MediaRouter) getSystemService(MEDIA_ROUTER_SERVICE);
            // 初始化权限
            initPermission();
        }

    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    private void initPermission() {
        if (!Settings.canDrawOverlays(this)){
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:"+getPackageName()));
            startActivityForResult(intent,10);
        }else {
            hasPermission = true;
        }

    }
    private Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(@NonNull Message msg) {
            initDisplay();
            return false;
        }
    });

    @Override
    protected void onResume() {
        super.onResume();
        // 这里延时的原因是因为可能是息屏后又开屏需要时间获取屏幕,如果直接获取可能获取不到多个屏幕
        if (hasPermission){
            mHandler.sendEmptyMessageDelayed(1,2000);
        }
    }

    /**
     * 初始化副屏
     * 为什么放在onResume中执行呢?为了防止息屏后客屏消失
     */
    private void initViceScreen(final Display display) {
        // 屏幕发生改变时副屏会自动消失,因此需要将原本显示的副屏置为空避免占用
        if (customPresentation != null && customPresentation.isChange()){
            customPresentation.dismiss();
            customPresentation = null;
        }
        // 屏幕发生改变时需要重新创建
        if (customPresentation == null ){
            customPresentation = new CustomPresentation(this,display);
            if (customPresentation.getWindow() != null){
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
                    customPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
                }else {
                    customPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                }
                customPresentation.show();
            }
        }
    }


    /**
     * 获取屏幕数量
     */
    private void initDisplay() {
        Display[] displays = displayManager.getDisplays();
        // 说明有副屏
        if (displays.length >1){
            initViceScreen(displays[1]);
        }else {
            // 获取屏幕方式一
            //displays = displayManager.getDisplays();
            // 获取屏幕方式二
            displays = displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
            if (displays.length > 1){
                initViceScreen(displays[1]);
            }else {
                // 获取客屏方式三
                MediaRouter.RouteInfo route = mediaRouter.getSelectedRoute(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                Display display = route.getPresentationDisplay();
                if (display != null) {
                    initViceScreen(display);
                }
            }


        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (customPresentation != null){
            customPresentation.dismiss();
        }
        mHandler.removeCallbacksAndMessages(null);
    }



    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (Settings.canDrawOverlays(this)) {
            hasPermission = true;
            mHandler.sendEmptyMessage(1);
        }
    }

    public void openClick(View view) {
        customPresentation.setChange();
    }
}

优化版本客屏显示ScreenActivity

package com.thomas.screen;

import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.media.MediaRouter;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

/**
 * 显示两种方式DisplayManager MediaRouter
 */
public class ScreenActivity extends AppCompatActivity {

    private CustomPresentation customPresentation;
    private DisplayManager.DisplayListener mDisplayListener;
    // request code for permission
    private final int DISPLAY_PERMISSION = 10;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_screen);
        initPermission();
        initDisplayListener();

    }

    private void initPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(this)){
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                        Uri.parse("package:"+getPackageName()));
                startActivityForResult(intent,DISPLAY_PERMISSION);
            }else {
                handlePresentationDisplay();
            }
        }else {
            handlePresentationDisplay();
        }
    }

    /**
     * <p>一共有三种方式获取副屏,这里我使用第三种方式,多种方式详细见 MainActivity
     * {@link com.thomas.screen.MainActivity}.</p>
     * <p>There are three ways to get the screen, and I'm use the MediaRouter here
     * {@link com.thomas.screen.MainActivity}.</p>
     *
     */
    private void handlePresentationDisplay() {
        MediaRouter mediaRouter = (MediaRouter) getSystemService(MEDIA_ROUTER_SERVICE);
        MediaRouter.RouteInfo route = mediaRouter.getSelectedRoute(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        Display display = route.getPresentationDisplay();
        System.out.println("presentation display information" + display);
        if (display != null) {
            createDisplay(display.getDisplayId());
        }
    }

    /**
     * 这里创建熄屏时候的监听,当然你也可以使用广播的方式
     */
    private void initDisplayListener() {
        mDisplayListener = new DisplayManager.DisplayListener() {
            /**
             * 客屏屏幕信息发生添加改变会触发一次
             */
            @Override
            public void onDisplayAdded(int displayId) {
                createDisplay(displayId);
            }

            /**
             * 客屏屏幕信息发生添加改变会触发一次
             */
            @Override
            public void onDisplayRemoved(int displayId) {
                if (customPresentation != null){
                    customPresentation.dismiss();
                }
                customPresentation = null;
            }

            /**
             * 这个会触发多次尽量请不要在这里做任何操作,部分机型会改变displayId,部分机型是固定的id数值进行变化
             * @param displayId 屏幕ID
             */
            @Override
            public void onDisplayChanged(int displayId) {
                System.out.println("display changed" + displayId);
            }
        };
        DisplayManager displayManager = (DisplayManager) getSystemService(DISPLAY_SERVICE);
        displayManager.registerDisplayListener(mDisplayListener,null);
    }

    /**
     * 这里创建副屏
     * @param displayId 屏幕ID
     */
    private void createDisplay(int displayId) {
        DisplayManager displayManager = (DisplayManager) getSystemService(DISPLAY_SERVICE);
        Display display = displayManager.getDisplay(displayId);
        if (display != null){
            customPresentation = new CustomPresentation(this,display);
            if (customPresentation.getWindow() != null){
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
                    customPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
                }else {
                    customPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                }
                customPresentation.show();
            }
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (customPresentation != null){
            customPresentation.dismiss();
        }
        DisplayManager displayManager = (DisplayManager) getSystemService(DISPLAY_SERVICE);
        if (displayManager != null){
            displayManager.unregisterDisplayListener(mDisplayListener);
        }
    }

    public void changePresentationDataClick(View view) {
        if (customPresentation != null){
            // 如果想要交互或者使用事件,或者使用以下方式交互
            customPresentation.setChange();
        }
    }

    /**
     * activity permission result
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == DISPLAY_PERMISSION){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (Settings.canDrawOverlays(this)) {
                    handlePresentationDisplay();
                }
            }
        }

    }

}

如果有需要更多其他源码加Q875831461获取,备注来意

最后

以上就是呆萌流沙为你收集整理的Android 副屏开发开发说明的全部内容,希望文章能够帮你解决Android 副屏开发开发说明所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部