概述
前言
- 更新日志
- 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 副屏开发开发说明所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复