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。

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

假装多好123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值