HDMI(二):LVDS、HDMI双屏异显
一、隐藏上方TitleBar
在AndroidManifest.xml的配置文件里面的<activity>标签添加属性:
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
示例:
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
二、daemon,副屏显示图片
2.1、权限
<!-- 读写存储卡权限的问题 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <!-- 显示系统窗口权限 --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 在 屏幕最顶部显示addview --> <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
2.2、显示类,显示副屏
@SuppressLint("NewApi") public class XHPresentation extends Presentation { public XHPresentation(Context outerContext, Display display) { super(outerContext, display); // TODO Auto-generated constructor stub } @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.second_screen); } }
2.3、在主程序中显示副显示器
// 双屏显示 DisplayManager mDisplayManager;// 屏幕管理类 Display[] displays;// 屏幕数组 mDisplayManager = (DisplayManager) MainActivity.this.getSystemService(Context.DISPLAY_SERVICE); displays = mDisplayManager.getDisplays(); // 得到显示器数组 XHPresentation mPresentation = new XHPresentation(getApplicationContext(), displays[1]);// displays[1]是副屏 mPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); mPresentation.show();
三、daemon,副屏播放视频
3.1、MainActivity.java
package com.gatsby.dualscreen; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.hardware.display.DisplayManager; import android.os.Bundle; import android.util.Log; import android.view.Display; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener { Button btn1, btn2; Intent intentService; private final static String SERVICE_ACTION = "com.xh.dualscreen.actions"; private boolean isShowSecondScreen = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_screen); btn1 = (Button) findViewById(R.id.btn1); btn2 = (Button) findViewById(R.id.btn2); btn1.setOnClickListener(this); btn2.setOnClickListener(this); intentService = new Intent(MainActivity.this, XHShowService.class); startService(intentService); isShowSecondScreen = true; } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.btn1: // 双屏显示 break; case R.id.btn2: if (!isShowSecondScreen) { Log.d("gatsby", "gatsby XHShowService!"); Intent i = new Intent(MainActivity.this, XHShowService.class); startService(i); isShowSecondScreen = true; } else { Log.d("gatsby", "gatsby XHShowService is started!"); Intent i = new Intent(SERVICE_ACTION); i.putExtra("receiver_key", 0); sendBroadcast(i); isShowSecondScreen = false; } break; } } @Override protected void onDestroy() { super.onDestroy(); Intent i = new Intent(SERVICE_ACTION); i.putExtra("receiver_key", 0); sendBroadcast(i); isShowSecondScreen = false; } }
3.2、XHShowService.java
package com.gatsby.dualscreen; import java.io.IOException; import java.util.ArrayList; import java.util.List; import android.annotation.SuppressLint; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.graphics.PixelFormat; import android.hardware.display.DisplayManager; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.IBinder; import android.util.Log; import android.view.Display; import android.view.Gravity; import android.view.LayoutInflater; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.WindowManager; import android.widget.LinearLayout; public class XHShowService extends Service { private static final String TAG = "gatsby"; // public final static String HDMI_PATH = "/mnt/sdcard/hdmi.mp4"; public final static String HDMI_PATH = "/mnt/sdcard/hdmi"; private List<String> hdmiVideoPath = new ArrayList<>(); private Display[] displays; private MediaPlayer mBackgroundPlayer; private SurfaceView presentSurface; private XHPresentation myPresentation; private DisplayManager mDisplayManager; private int nowHdmiPosition = 0; MsgReceiver receiver; private final static String SERVICE_ACTION = "com.xh.dualscreen.actions"; // 接收activity 发送过来的广播,来作相应的播放处理。目前就做了一个切换功能。可以加上下一曲和暂停等一些功能。 class MsgReceiver extends BroadcastReceiver { @SuppressLint("NewApi") @Override public void onReceive(Context context, Intent intent) { Log.d(TAG, "XHShowService onReceive-->" + intent.getAction()); if (intent != null) { if (intent.getIntExtra("receiver_key", -1) == 0) { Log.d(TAG, "XHShowService onReceive getIntExtra "); myPresentation.dismiss(); unregisterReceiver(receiver); stopSelf(); } } } } @Override public IBinder onBind(Intent intent) { return null; } @SuppressLint("NewApi") @Override public void onCreate() { super.onCreate(); Log.d(TAG, "XHShowService onCreate!!!"); // 获取显示设备 mDisplayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE); displays = mDisplayManager.getDisplays();// get the number of displays Log.d(TAG, "xhDisplays=" + displays.length); if (displays.length > 1) { showPresentation(displays[1]);// displays[0]:main_screen displays[1]:second_screen // 注册广播 receiver = new MsgReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(SERVICE_ACTION); registerReceiver(receiver, intentFilter); initViewSurface(); } } @SuppressLint({ "InflateParams", "NewApi" }) private void initViewSurface() { mBackgroundPlayer = new MediaPlayer(); // ָ指定流媒体类型 mBackgroundPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); hdmiVideoPath = XHFileUtils.getPaths(HDMI_PATH); WindowManager mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); // 获取LayoutParams对象 WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams(); wmParams.type = WindowManager.LayoutParams.TYPE_PHONE; wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; wmParams.format = PixelFormat.RGBA_8888; wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; wmParams.gravity = Gravity.LEFT | Gravity.TOP; wmParams.x = 0; wmParams.y = 0; // 宽度和高度为0, 可以避免主屏退出后出现的主屏触摸和点击问题 wmParams.width = 0; wmParams.height = 0; LayoutInflater inflater = LayoutInflater.from(this); LinearLayout presentationLayout = (LinearLayout) inflater.inflate(R.layout.second_screen, null); presentationLayout.setFocusable(false); mWindowManager.addView(presentationLayout, wmParams); playVideo(mBackgroundPlayer, nowHdmiPosition, true); } // 将内容显示到display上面。 @SuppressLint("NewApi") private void showPresentation(Display display) { myPresentation = new XHPresentation(this, display, true); myPresentation.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { // 监听消失,保存当前播放位置。 } }); myPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE); myPresentation.show(); presentSurface = myPresentation.getSurface(); presentSurface.getHolder().addCallback(new MySurfaceCallback()); } // 统一的播放界面 private void playVideo(MediaPlayer mediaPlayer, int pathIndex, boolean isFirstPlay) { if (isFirstPlay) { mediaPlayer.setOnCompletionListener(new MyVideoFinishListener()); try { nowHdmiPosition = 0; if ((hdmiVideoPath != null) && (hdmiVideoPath.size() > 0)) { // mediaPlayer.setDataSource(HDMI_PATH); mediaPlayer.setDataSource(hdmiVideoPath.get(0)); } } catch (IOException e) { e.printStackTrace(); } try { mediaPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { } mediaPlayer.start(); } else { mediaPlayer.reset(); mediaPlayer.setOnCompletionListener(new MyVideoFinishListener()); try { // mediaPlayer.setDataSource(HDMI_PATH); mediaPlayer.setDataSource(hdmiVideoPath.get(pathIndex)); } catch (IOException e) { e.printStackTrace(); } try { mediaPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { } mediaPlayer.start(); } } class MyVideoFinishListener implements MediaPlayer.OnCompletionListener { @Override public void onCompletion(MediaPlayer mp) { nowHdmiPosition++; if (nowHdmiPosition >= hdmiVideoPath.size()) { nowHdmiPosition = 0; } playVideo(mp, nowHdmiPosition, false); } } class MySurfaceCallback implements SurfaceHolder.Callback { @Override public void surfaceCreated(SurfaceHolder holder) { mBackgroundPlayer.setDisplay(presentSurface.getHolder()); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { } } @Override public void onDestroy() { super.onDestroy(); mBackgroundPlayer.release(); } }
https://download.csdn.net/download/qq_40949012/12651236