IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> android 投屏,华为手机的电脑模式是如何实现的 -> 正文阅读

[移动开发]android 投屏,华为手机的电脑模式是如何实现的

android 投屏,华为手机的电脑模式是如何实现的

1.前言

? 不知道大家在手机往家里电视投屏的时候有没有发现,华为手机和三星手机投屏成功后,会有手机和电脑两种模式,手机模式是将手机镜像投到屏幕上,而电脑模式,则是将大屏电视变为一个电脑一样,如果连接鼠标或者大屏支持触控,则通过电脑模式是可以直接操作手机的。此时手机只要不关机,是可以继续干其他事情的。这就相当于一个系统分两个用。真是不要太牛逼。

? 当然还有另外一种投屏方式,应该是大家用的最多的,就是使用DLNA 投屏,将手机播放的视屏,图片,音乐等多媒体投屏到大屏设备播放,此时手机还可以继续干其他事情,甚至关机,也不影响DLNA 的播放。

2. 投屏模式

    1. 手机模式
      在这里插入图片描述
    1. 电脑模式
      在这里插入图片描述
      在这里插入图片描述
    1. DLNA
      在这里插入图片描述
      如上图播放视屏时点击右上角TV 投屏按钮,即可开启DLNA投屏。

    3.投屏区分

1. DLNA

主要用于视屏,音乐,图片等多媒体的投射。投射时手机和大屏必须在同一局域网中。主要原理还是udp。手机投屏大屏后,手机就可干其他事情,哪怕手机关机,大屏也不会停止播放。

现今社会,基本上视屏,电视,电影,都不是免费的,都需要开会员,而且更可恶的是,同一家app,例如某讯,在电视端和手机端的资源是不互通的。这样就显得DLNA 尤为重要了。

2.Miracast

通过手机setting或者下拉菜单栏里面的投屏进行投屏的,就是用的miracast 协议。
这里面又分手机模式和电脑模式。google 原生支持手机模式镜像。电脑模式目前好像只有华为手机和三星手机支持。

手机模式也就是投屏手机镜像,会将手机的实时页面,同步投屏到大屏上,手机上显示什么,大屏上就显示什么,手机锁屏,大屏锁屏,手机息屏,大屏息屏。

而电脑模式就很像是上面的DLNA 一样,会将一个特定的页面投给大屏,而此时手机可以干其他的事,但不能断开投屏连接。我把这个说为静态页面,把DLNA 那个说为动态页面。

4.进入正题,miracast 投屏电脑模式实现。

与其说是电脑模式实现,不如说是对电脑模式实现的一点思路。因为我也不知道华为是怎么实现的。但我觉得他就说这么实现的。
下面直接上代码:

package com.example.miracast;

import android.app.Activity;
import android.app.Presentation;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.util.SparseArray;
import android.view.Display;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity {

    private DisplayManager mDisplayManager;
    private DisplayListAdapter mDisplayListAdapter;
    private ListView mListView;
    private final SparseArray<RemotePresentation> mActivePresentations = new SparseArray<RemotePresentation>();

    private final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() {
        @Override
        public void onDisplayAdded(int displayId) {
            mDisplayListAdapter.updateContents();
        }

        @Override
        public void onDisplayChanged(int displayId) {
            mDisplayListAdapter.updateContents();
        }

        @Override
        public void onDisplayRemoved(int displayId) {
            mDisplayListAdapter.updateContents();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.local_display);
        mDisplayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);

        mDisplayListAdapter = new DisplayListAdapter(this);
        mListView = (ListView) findViewById(R.id.display_list);
        mListView.setAdapter(mDisplayListAdapter);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mDisplayListAdapter.updateContents();
        mDisplayManager.registerDisplayListener(mDisplayListener, null);
    }

    private void showPresentation(Display display) {
        RemotePresentation presentation = new RemotePresentation(this, display);
        mActivePresentations.put(display.getDisplayId(), presentation);
        presentation.show();
    }

    private void hidePresentation(Display display) {
        final int displayId = display.getDisplayId();
        RemotePresentation presentation = mActivePresentations.get(displayId);
        if (presentation == null) {
            return;
        }

        presentation.dismiss();
        mActivePresentations.delete(displayId);
    }

    private final class DisplayListAdapter extends ArrayAdapter<Display> {
        final Context mContext;
        private OnCheckedChangeListener mCheckedRemoteDisplay = new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton view, boolean isChecked) {
                synchronized (mCheckedRemoteDisplay) {
                    final Display display = (Display) view.getTag();
                    if (isChecked) {
                        showPresentation(display);
                    } else {
                        hidePresentation(display);
                    }
                }
            }
        };

        public DisplayListAdapter(Context context) {
            super(context, R.layout.list_item);
            mContext = context;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final View v;
            if (convertView == null) {
                v = ((Activity) mContext).getLayoutInflater().inflate(R.layout.list_item, null);
            } else {
                v = convertView;
            }

            final Display display = getItem(position);

            //TITLE
            TextView tv = (TextView) v.findViewById(R.id.display_id);
            tv.setText(display.getName() + "( ID: " + display.getDisplayId() + " )");

            //DESCRIPTION
            tv = (TextView) v.findViewById(R.id.display_desc);
            tv.setText(display.toString());

            //SHOW or HIDE the presentation
            CheckBox cb = (CheckBox) v.findViewById(R.id.display_cb);
            cb.setTag(display);
            cb.setOnCheckedChangeListener(mCheckedRemoteDisplay);
            return v;
        }

        public void updateContents() {
            clear();

            Display[] displays = mDisplayManager.getDisplays();
            addAll(displays);
        }
    }

    private final class RemotePresentation extends Presentation {
        public RemotePresentation(Context context, Display display) {
            super(context, display);
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.remote_display);
        }
    }
}

remote_display.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    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:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:textSize="22sp"
        android:textStyle="bold"
        android:text="Hello world, Remote Display over Miracast!!" />

</RelativeLayout>

local_display.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <ListView
        android:id="@+id/display_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</RelativeLayout>

list_item.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="8dp">

    <CheckBox 
        android:id="@+id/display_cb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:checked="false"/>
    <TextView 
        android:id="@+id/display_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/display_cb"
        android:layout_alignBaseline="@+id/display_cb"
        android:textSize="18sp"
        android:textColor="#000000"/>
    
    <TextView 
        android:id="@+id/display_desc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/display_cb"
        android:textSize="14sp"
        android:textColor="#303030"/>
</RelativeLayout>

在这里插入图片描述
在这里插入图片描述
这样就实现了,投屏到大屏上后,小屏依然可以干其他事情。这样我们就可以把上面那个remote_display页面写成和电脑的window 桌面一样的launcher。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-15 11:39:14  更:2022-05-15 11:39:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:37:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码