[Transfer] The detailed steps of the simple multi-screen different display function based on Android Studio, and related simple arrangements

Table of contents

Steps to realize the simple multi-screen display function based on Android Studio, and related simple arrangements

1. Brief introduction

2. Implementation principle

3. Matters needing attention

4. Development environment

5. Implementation steps

6. Key code

appendix:

7. Error handling: Android: Unable to add window. Permission denied for this window type

8. Online information reference: Three ways to realize Android dual-screen different display

1. The first implementation method of dual-screen different display (officially provided Presentation)

2. Dual-screen different display (simultaneous display) realization method

3. There is another way to achieve dual-screen different display through projection. Every projection will pop up a prompt box for confirmation, which has certain limitations.


1. Brief introduction

Some basic operations in Android development are sorted out for later use.

This section introduces that in Android development, there is no unique way to simply realize the different display functions of multiple screens, and corrections are welcome.

2. Implementation principle

1. Inherit the official class provided by Presentation, which is equivalent to a special pop-up window

3. Matters needing attention

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

2. When the application is opened at the same time, obtain the ACTION_MANAGE_OVERLAY_PERMISSION permission

4. Development environment

Android Studio 4.1.1

5. Implementation steps

1. Open Android Studio and create a new project

2. Select Phone and Tablet - EmptyActivity, click Next

3. According to your own needs, make some related settings, and then Finish

4. Here, take dual screen as an example, create a new script and write logic code

5. Add code logic for obtaining relevant permissions and obtaining relevant screens in MainActivity.java, as follows

6. Because the development environment sdk version is 27 (Android 8.1), the setting type is WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, and you may need to make a slight difference according to your own sdk version

Otherwise, an error may be reported: for example android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@40ec8528 -- permission denied for this window type

7. Depending on the version, the corresponding application permission, otherwise an error may be reported, or different multi-screen displays

8. Because it is necessary to turn off the multi-screen different display function according to the background switching of the application and whether it is closed or not, the monitoring application status is displayed and canceled

Namely: show() or dismiss()

9. Add corresponding permissions to AndroidManifest.xml

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

10. The corresponding layout.xml is as shown in the figure below, which is convenient for multi-screen display

11. At this time, Build -Make project, connect multiple screens of the mobile phone, and you can see the effect of multi-screen different display

6. Key code

1、DifferentDislay.java

import android.app.Presentation;
import android.content.Context;
import android.os.Bundle;
import android.view.Display;
 
public class DifferentDislay extends Presentation {
 
    public DifferentDislay(Context outerContext, Display display) {
        super(outerContext,display);
 
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mylayout);
    }
}

2、MainActivity.java

 
import android.app.Activity;
import android.app.Application;
import android.app.Presentation;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
 
public class MainActivity extends AppCompatActivity {
 
    private static final String TAG = "XANTest";
    DifferentDislay mPresentation;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        GetPermission();
 
        multiScreenDisplay();
    }
 
    void multiScreenDisplay(){
        //双屏显示
        DisplayManager mDisplayManager;//屏幕管理类
        Display[] displays;//屏幕数组
 
        mDisplayManager =(DisplayManager)MainActivity.this.getSystemService(Context.DISPLAY_SERVICE);
        displays =mDisplayManager.getDisplays(); //得到显示器数组
 
        Log.i(TAG, "multiScreenDisplay: displays count = " + displays.length);
 
        if (displays.length > 1){
 
            mPresentation =new DifferentDislay
                    (getApplicationContext(),displays[1]);//displays[1]是副屏
 
            mPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
 
 
//            if you use apiLevel >= 19, don't use
//
//            WindowManager.LayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
//
//            which gets the following error:
//
//            android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@40ec8528 -- permission denied for this window type
//
//            Use this instead:
//
//            LayoutParams.TYPE_TOAST or TYPE_APPLICATION_PANEL
 
 
            mPresentation.show();
        }
 
 
    }
 
    void GetPermission(){
        if(Build.VERSION.SDK_INT >= 23) {
            if (!Settings.canDrawOverlays(this)) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                        Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, 1234);
            }
        }
        else
        {
            Intent intent = new Intent(this, Service.class);
            startService(intent);
        }
 
    }
 
    @Override
    protected void onStop() {
        super.onStop();
        if (mPresentation != null) {
            mPresentation.dismiss();
        }
    }
 
    @Override
    protected void onResume() {
        super.onResume();
        if (mPresentation != null) {
            mPresentation.show();
        }
    }
 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mPresentation != null) {
            mPresentation.dismiss();
        }
    }
 
 
}

3、AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testmultiscreendisplay0407">
 
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
 
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.TestMultiScreenDisplay0407">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
 
</manifest>

4、activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context=".MainActivity">
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
</android.support.constraint.ConstraintLayout>

5、mylayout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="658dp"
        android:layout_weight="1"
        android:text="MyTestScreen"
        android:textSize="100dp"
        />
</LinearLayout>

appendix:

7. Error handling: Android: Unable to add window. Permission denied for this window type

Reference: Android: Unable to add window. Permission denied for this window type - Stack Overflow

8. Online information reference: Three ways to realize Android dual-screen different display

Reference blog post address: Three ways to realize Android dual-screen different display_createdisplaycontext_I am actually a mortal blog-CSDN Blog

In the era when various products are full of ideas, the demand is also becoming more and more new. The author recently developed a set of dual-screen different display app. now to make some conclusions

1. The first implementation method of dual-screen different display (officially provided Presentation)

Android provides a class called Presentation to realize the second screen, inherit Presentation to realize the second screen, which is equivalent to a special pop-up window (specific implementation)

 public class DifferentDislay extends Presentation {
        public DifferentDislay(Context outerContext, Display display) {
            super(outerContext,display);
           
        }
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.diffrentdisplay);
        }
    }

Quote:

 //双屏显示
            DisplayManager mDisplayManager;//屏幕管理类
            Display[] displays;//屏幕数组
            mDisplayManager =(DisplayManager)MainActivity.this.getSystemService(Context.DISPLAY_SERVICE);
            displays =mDisplayManager.getDisplays(); //得到显示器数组
            DifferentDislay mPresentation =new DifferentDislay
            (getApplicationContext(),displays[1]);//displays[1]是副屏
            mPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
            mPresentation.show();

Required permissions:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
        <uses-permission android:name="android.permission.TYPE_APPLICATION_OVERLAY" />
        <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

Note: The above is the dual-screen different display implemented by Presentation. This method is more suitable for dual-screen independent operation without communication. If there is dual-screen simultaneous display, or some data synchronization between the two, it will be more troublesome.

For example: main screen playback adaptation -> projection to the second screen, the above method is not applicable, because it involves the adaptation of synchronous display, and the main and secondary screens must start a player to achieve it, which is a huge waste of performance. The performance of the device is relatively good, and it can also be realized in this way. If the performance of the device is not very good, the video will freeze after using this method. In severe cases, the decoding may fail, and the video cannot be played and other concurrent problems.

For the above-mentioned opening of the second screen with dual-screen simultaneous display and video playback, I have made a great improvement on the original basis, which can avoid the waste of performance caused by starting two players

2. Dual-screen different display (simultaneous display) realization method

I believe that compatriots who do dual-screen different display must have read the source code of Presentation. The source code shows that Presentation is realized by inheritance and Dialog. I also mentioned at the beginning of the article that the second screen can be regarded as a special Dialog. accomplish

When I was researching the source code of Presentation, I found that it obtained a window through Window w = getWindow();. We all know that Window is the top-level window of Android when we develop Android. Seeing this, I wonder why I can’t directly create a window. Then get the screen array and place it on the second screen? look down  

 public void addPresentation(Context paramContext) {
            Display display = ((MediaRouter) paramContext.getSystemService(Context.MEDIA_ROUTER_SERVICE)).getSelectedRoute(2).getPresentationDisplay();
            this.secondDisplay = display;
            if (display != null) {
                this.windowManager = (WindowManager) paramContext.createDisplayContext(display).getSystemService(Context.WINDOW_SERVICE);
                this.secondDisplayContext = paramContext.createDisplayContext(this.secondDisplay);
                return;
            }
        }

In the above code, we get the window manager and create the second screen through paramContext.createDisplayContext(this.secondDisplay);

After creating the second screen, let's add a view to the second screen      

 public View addView(int paramInt) {
            this.view = View.inflate(this.secondDisplayContext, paramInt, null);
            this.layoutParams = new WindowManager.LayoutParams(2003, 3, 3);
            if (Build.VERSION.SDK_INT >= 23) {
                this.layoutParams.type = 2038;
            } else {
                this.layoutParams.type = 2003;
            }
            this.windowManager.addView(this.view, this.layoutParams);
            return this.view;
        }

In this way, our second screen has been completed. We only need to create a layout according to our own needs, call the addView method to add it, return the added view, and operate in the main class to solve the problem of data synchronization.

The following is the complete code   

public class HelpHandPresentation {
        private WindowManager.LayoutParams layoutParams;
     
        private Display secondDisplay;
     
        private Context secondDisplayContext;
     
        private View view;
     
        private WindowManager windowManager;
     
        public void addPresentation(Context paramContext) {
            Display display = ((MediaRouter) paramContext.getSystemService(Context.MEDIA_ROUTER_SERVICE)).getSelectedRoute(2).getPresentationDisplay();
            this.secondDisplay = display;
            if (display != null) {
                this.windowManager = (WindowManager) paramContext.createDisplayContext(display).getSystemService(Context.WINDOW_SERVICE);
                this.secondDisplayContext = paramContext.createDisplayContext(this.secondDisplay);
                return;
            }
        }
     
        public View addView(int paramInt) {
            this.view = View.inflate(this.secondDisplayContext, paramInt, null);
            this.layoutParams = new WindowManager.LayoutParams(2003, 3, 3);
            if (Build.VERSION.SDK_INT >= 23) {
                this.layoutParams.type = 2038;
            } else {
                this.layoutParams.type = 2003;
            }
            this.windowManager.addView(this.view, this.layoutParams);
            return this.view;
        }
     
        public void presentationAddView() {
            this.windowManager.addView(this.view, this.layoutParams);
        }
     
        public void removeLayoutView() {
            this.windowManager.removeView(this.view);
        }
    }

Equivalent to a tool class, just copied to the project can be used directly

The following is how to call

    HelpHandPresentation helpHandPresentation = new HelpHandPresentation();
    helpHandPresentation.addPresentation(context);
    View view = helpHandPresentation.addView(layout);

Just three lines of code, easy to call

3. There is another way to achieve dual-screen different display through projection. Every projection will pop up a prompt box for confirmation, which has certain limitations.

 (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);

If you are interested, you can take a look at the source code implementation of MediaProjectionManager, which is described here

Guess you like

Origin blog.csdn.net/qq_27489007/article/details/131330444