前言

项目开发中遇到需要解析播放m3u8视频流的情况,但是原生的PlayerView非常慢,使用起来复杂,不适合上手,这里找到一款ijkplayer是Bilibili基于ffmpeg开发并开源的轻量级视频播放器,支持播放本地网络视频,也支持流媒体播放。支持Android&iOS。
这里感谢jjdxmashl基于ijkplayer封装了支持简单界面UI定制的视频播放器,操作简单实用,推荐大家使用。

简介

当前项目是基于ijkplayer项目进行的播放器界面UI封装。
是一个适用于 Android 的 RTMP 直播推流 SDK,可高度定制化和二次开发。特色是同时支持 H.264 软编/硬编和 AAC 软编/硬编。主要是支持RIMP、HLS、MP4、M4A等视频格式的播放。
作者项目地址:http://www.github.com/jjdxmashl/jjdxm_ijkplayer
作者简书地址:http://www.jianshu.com/p/6c938df18413

特性

  • 基于ijkplayer封装的视频播放器界面,支持 RTMP , HLS (http & https) , MP4,M4A 等;
  • 可根据需求去定制部分界面样式;
  • 常用的手势操作左边上下亮度,右边上下声音,左右滑动播放进度调整;
  • 支持多种分辨率流的切换播放;
  • 播放出错尝试重连;
  • 界面裁剪显示样式;

快速开始

step1:导入依赖

该项目已经打包到jcenter中心了,可以通过compile命令直接依赖,在主程序目录build.gradle中,添加以下代码:

compile ‘com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.0’ 

step2:简单的播放器实现

setContentView(R.layout.simple_player_view_player);
String url = "http://9890.vod.myqcloud.com/9890_9c1fa3e2aea011e59fc841df10c92278.f20.mp4";
player = new PlayerView(this).setTitle("什么").setScaleType(PlayStateParams.fitparent).hideMenu(true).forbidTouch(false).showThumbnail(new OnShowThumbnailListener() {@Overridepublic void onShowThumbnail(ImageView ivThumbnail) {Glide.with(mContext).load("http://pic2.nipic.com/20090413/406638_125424003_2.jpg").placeholder(R.color.cl_default).error(R.color.cl_error).into(ivThumbnail);}}).setPlaySource(url).startPlay();

step3:多种不同的分辨率流的播放器实现

在布局中使用simple_player_view_player.xml布局

<includelayout="@layout/simple_player_view_player"android:layout_width="match_parent"android:layout_height="180dp"/>

代码中创建一个播放器对象

/**播放资源*/
ist<VideoijkBean> list = new ArrayList<VideoijkBean>();
String url1 = "http://9890.vod.myqcloud.com/9890_4e292f9a3dd011e6b4078980237cc3d3.f20.mp4";
String url2 = "http://9890.vod.myqcloud.com/9890_4e292f9a3dd011e6b4078980237cc3d3.f30.mp4";
VideoijkBean m1 = new VideoijkBean();
m1.setStream("标清");
m1.setUrl(url1);
VideoijkBean m2 = new VideoijkBean();
m2.setStream("高清");
m2.setUrl(url2);
list.add(m1);
list.add(m2);
/**播放器*/
player = new PlayerView(this).setTitle("什么").setScaleType(PlayStateParams.fitparent).hideMenu(true).forbidTouch(false).showThumbnail(new OnShowThumbnailListener() {@Overridepublic void onShowThumbnail(ImageView ivThumbnail) {/**加载前显示的缩略图*/Glide.with(mContext).load("http://pic2.nipic.com/20090413/406638_125424003_2.jpg").placeholder(R.color.cl_default).error(R.color.cl_error).into(ivThumbnail);}}).setPlaySource(list).startPlay();

配置生命周期方法

为了让播放器同步Activity生命周期,建议以下方法都去配置,注释的代码,主要作用是播放时屏幕常亮和暂停其它媒体的播放。

@Override
protected void onPause() {super.onPause();if (player != null) {player.onPause();}/**demo的内容,恢复系统其它媒体的状态*///MediaUtils.muteAudioFocus(mContext, true);
}@Override
protected void onResume() {super.onResume();if (player != null) {player.onResume();}/**demo的内容,暂停系统其它媒体的状态*/MediaUtils.muteAudioFocus(mContext, false);/**demo的内容,激活设备常亮状态*///if (wakeLock != null) {//    wakeLock.acquire();//}
}@Override
protected void onDestroy() {super.onDestroy();if (player != null) {player.onDestroy();}
}@Override
public void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);if (player != null) {player.onConfigurationChanged(newConfig);}
}@Override
public void onBackPressed() {if (player != null && player.onBackPressed()) {return;}super.onBackPressed();/**demo的内容,恢复设备亮度状态*///if (wakeLock != null) {//    wakeLock.release();//}
}

更多UI样式的设置

1.视频界面裁剪设置

可通过方法setScaleType(int type)去设置

  • PlayStateParams.fitParent:可能会剪裁,保持原视频的大小,显示在中心,当原视频的大小超过view的大小超过部分裁剪处理
  • PlayStateParams.fillParent:可能会剪裁,等比例放大视频,直到填满View为止,超过View的部分作裁剪处理
  • PlayStateParams.wrapcontent:将视频的内容完整居中显示,如果视频大于view,则按比例缩视频直到完全显示在view中
  • PlayStateParams.fitXY:不剪裁,非等比例拉伸画面填满整个View
  • PlayStateParams.f16_9:不剪裁,非等比例拉伸画面到16:9,并完全显示在View中
  • PlayStateParams.f4_3:不剪裁,非等比例拉伸画面到4:3,并完全显示在View中

2.播放器底部bar播放进度条样式定制

默认的进度样式是竖屏为上下样式,即进度条在播放时长的上面,横屏为左右样式,即进度条在播放时长的中间。样式定制主要是两个方法搭配使用toggleProcessDurationOrientation方法和setProcessDurationOrientation方法,横竖屏切换2中情况,和3种进度条样式

/**上下样式*/
PlayStateParams.PROCESS_PORTRAIT
/**左右样式*/
PlayStateParams.PROCESS_LANDSCAPE
/**中间两边样式*/
PlayStateParams.PROCESS_CENTER

总共有2的3次方中样式,下面只罗列几种样式
(1).横竖屏都为上下样式

player = new PlayerView(this) {@Overridepublic PlayerView toggleProcessDurationOrientation() {return setProcessDurationOrientation(PlayStateParams.PROCESS_PORTRAIT);}}.setTitle("什么").setProcessDurationOrientation(PlayStateParams.PROCESS_PORTRAIT).setScaleType(PlayStateParams.fitparent).forbidTouch(false).hideCenterPlayer(true).setPlaySource(list).startPlay();

(2).横竖屏都为左右样式

player = new PlayerView(this) {@Overridepublic PlayerView toggleProcessDurationOrientation() {return setProcessDurationOrientation(PlayStateParams.PROCESS_LANDSCAPE);}}.setTitle("什么").setProcessDurationOrientation(PlayStateParams.PROCESS_LANDSCAPE).setScaleType(PlayStateParams.fitparent).forbidTouch(false).hideCenterPlayer(true).setPlaySource(list).startPlay();

(3).横屏为上下样式竖屏为左右样式

player = new PlayerView(this) {@Overridepublic PlayerView toggleProcessDurationOrientation() {return setProcessDurationOrientation(getScreenOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE?PlayStateParams.PROCESS_LANDSCAPE:PlayStateParams.PROCESS_PORTRAIT);}}.setTitle("什么").setProcessDurationOrientation(PlayStateParams.PROCESS_LANDSCAPE).setScaleType(PlayStateParams.fitparent).forbidTouch(false).hideCenterPlayer(true).setPlaySource(list).startPlay();

3.隐藏部分不想要的界面

//隐藏返回键,true隐藏,false为显示
PlayerView hideBack(boolean isHide)
//隐藏菜单键,true隐藏,false为显示
PlayerView hideMenu(boolean isHide)
//隐藏分辨率按钮,true隐藏,false为显示
PlayerView hideSteam(boolean isHide)
//隐藏旋转按钮,true隐藏,false为显示
PlayerView hideRotation(boolean isHide)
//隐藏全屏按钮,true隐藏,false为显示
PlayerView hideFullscreen(boolean isHide)
//隐藏中间播放按钮,ture为隐藏,false为不做隐藏处理,但不是显示
PlayerView hideCenterPlayer(boolean isHide)

4.视频移动流量是播放提醒

//设置2/3/4/5G和WiFi网络类型提示 true为进行2/3/4/5G网络类型提示 false 不进行网络类型提示
PlayerView setNetWorkTypeTie(boolean isGNetWork)

5.视频加载前显示缩略图

player.showThumbnail(new OnShowThumbnailListener() {@Overridepublic void onShowThumbnail(ImageView ivThumbnail) {/**加载前显示的缩略图*/Glide.with(mContext).load("http://pic2.nipic.com/20090413/406638_125424003_2.jpg").placeholder(R.color.cl_default).error(R.color.cl_error).into(ivThumbnail);}})

6.默认显示上下操作栏bar

//设置是否禁止隐藏bar,true为一直显示,false为点击可以隐藏或显示
PlayerView setForbidHideControlPanl(boolean flag)

7.设置播放出错后尝试重连的方式和重连的时间

//设置自动重连的模式或者重连时间,isAuto true 出错重连,false出错不重连,connectTime重连的时间
setAutoReConnect(boolean isAuto, int connectTime)

8.视频界面的旋转

当前默认使用setPlayerRotation方法为90、270、0轮询切换,如果需要指定角度旋转可以使用setPlayerRotation方法

//旋转角度
PlayerView setPlayerRotation()
//旋转指定角度
PlayerView setPlayerRotation(int rotation)

自定义视频界面

可以复制以下布局内容到自己的项目中,注意已有的id不能修改或删除,可以增加view,可以对以下布局内容调整显示位置或者自行隐藏

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:id="@+id/app_video_box"xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/black"android:orientation="vertical"><com.dou361.ijkplayer.widget.IjkVideoView
        android:id="@+id/video_view"android:layout_width="match_parent"android:layout_height="match_parent"/><LinearLayout
        android:id="@+id/ll_bg"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/black"android:orientation="vertical"><!-- 封面显示--><ImageView
            android:id="@+id/iv_trumb"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitXY"android:visibility="visible"/></LinearLayout><!--重新播放--><LinearLayout
        android:id="@+id/app_video_replay"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#33000000"android:gravity="center"android:orientation="vertical"android:visibility="gone"><!-- 播放状态--><TextView
            android:id="@+id/app_video_status_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/small_problem"android:textColor="@android:color/white"android:textSize="14dp"/><ImageView
            android:id="@+id/app_video_replay_icon"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:layout_marginTop="8dp"android:src="@drawable/simple_player_circle_outline_white_36dp"/></LinearLayout><!-- 网络提示--><LinearLayout
        android:id="@+id/app_video_netTie"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#33000000"android:gravity="center"android:orientation="vertical"android:visibility="gone"><TextView
            android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="8dp"android:gravity="center"android:paddingLeft="8dp"android:paddingRight="8dp"android:text="您正在使用移动网络播放视频\n可能产生较高流量费用"android:textColor="@android:color/white"/><TextView
            android:id="@+id/app_video_netTie_icon"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/simple_player_btn"android:gravity="center"android:paddingLeft="8dp"android:paddingRight="8dp"android:text="继续"android:textColor="@android:color/white"/></LinearLayout><!--加载中--><LinearLayout
        android:id="@+id/app_video_loading"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"android:visibility="gone"><ProgressBar
            android:layout_width="50dp"android:layout_height="50dp"android:indeterminateBehavior="repeat"android:indeterminateOnly="true"/><TextView
            android:id="@+id/app_video_speed"android:layout_width="wrap_content"android:layout_marginTop="4dp"android:layout_height="wrap_content"android:gravity="center"android:visibility="gone"android:text="188Kb/s"android:textColor="@android:color/white"/></LinearLayout><!-- 中间触摸提示--><include
        layout="@layout/simple_player_touch_gestures"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"/><!-- 顶部栏--><include layout="@layout/simple_player_topbar"/><!-- 底部栏--><include
        layout="@layout/simple_player_controlbar"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"/><!--声音亮度控制--><LinearLayout
        android:id="@+id/simple_player_settings_container"android:layout_width="250dp"android:layout_height="match_parent"android:layout_alignParentLeft="true"android:background="#80000000"android:gravity="center_vertical"android:orientation="vertical"android:visibility="visible"><LinearLayout
            android:id="@+id/simple_player_volume_controller_container"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:orientation="horizontal"><ImageView
                android:layout_width="30dp"android:layout_height="30dp"android:src="@drawable/qcloud_player_icon_audio_vol_mute"/><SeekBar
                android:id="@+id/simple_player_volume_controller"style="?android:attr/progressBarStyleHorizontal"android:layout_width="150dp"android:layout_height="wrap_content"/><ImageView
                android:layout_width="30dp"android:layout_height="30dp"android:src="@drawable/qcloud_player_icon_audio_vol"/></LinearLayout><LinearLayout
            android:id="@+id/simple_player_brightness_controller_container"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:gravity="center"android:orientation="horizontal"><ImageView
                android:layout_width="30dp"android:layout_height="30dp"android:padding="5dp"android:src="@drawable/qcloud_player_icon_brightness"/><SeekBar
                android:id="@+id/simple_player_brightness_controller"style="?android:attr/progressBarStyleHorizontal"android:layout_width="150dp"android:layout_height="wrap_content"/><ImageView
                android:layout_width="30dp"android:layout_height="30dp"android:src="@drawable/qcloud_player_icon_brightness"/></LinearLayout></LinearLayout><!--分辨率选择--><LinearLayout
        android:id="@+id/simple_player_select_stream_container"android:layout_width="150dp"android:layout_height="match_parent"android:layout_alignParentRight="true"android:background="#80000000"android:gravity="center_vertical"android:visibility="gone"><ListView
            android:id="@+id/simple_player_select_streams_list"android:layout_width="150dp"android:layout_height="wrap_content"/></LinearLayout><ImageView
        android:id="@+id/play_icon"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:layout_marginTop="8dp"android:src="@drawable/simple_player_center_play"/></RelativeLayout>

播放器PlayerView对象

PlayerView(Activity activity)//生命周期方法回调
PlayerView onPause()
PlayerView onResume()
PlayerView onDestroy()
PlayerView onConfigurationChanged(final Configuration newConfig)
boolean onBackPressed()
//显示缩略图
PlayerView showThumbnail(OnShowThumbnailListener onShowThumbnailListener)
//设置播放信息监听回调
PlayerView setOnInfoListener(IMediaPlayer.OnInfoListener onInfoListener)
//设置播放器中的返回键监听
PlayerView setPlayerBackListener(OnPlayerBackListener listener)
//设置控制面板显示隐藏监听
PlayerView setOnControlPanelVisibilityChangListenter(OnControlPanelVisibilityChangeListener listener)
//百分比显示切换
PlayerView toggleAspectRatio()
//设置播放区域拉伸类型
PlayerView setScaleType(int showType)
//旋转角度
PlayerView setPlayerRotation()
//旋转指定角度
PlayerView setPlayerRotation(int rotation)
//设置播放地址包括视频清晰度列表对应地址列表
PlayerView setPlaySource(List<VideoijkBean> list)
//设置播放地址单个视频VideoijkBean
PlayerView setPlaySource(VideoijkBean videoijkBean)
//设置播放地址单个视频地址时带流名称
PlayerView setPlaySource(String stream, String url)
//设置播放地址单个视频地址时
PlayerView setPlaySource(String url)
//自动播放
PlayerView autoPlay(String path)
//开始播放
PlayerView startPlay()
//设置视频名称
PlayerView setTitle(String title)
//选择要播放的流
PlayerView switchStream(int index)
//暂停播放
PlayerView pausePlay()
//停止播放
PlayerView stopPlay()
//设置播放位置
PlayerView seekTo(int playtime)
//获取当前播放位置
int getCurrentPosition()
//获取视频播放总时长
long getDuration()
//设置2/3/4/5G和WiFi网络类型提示 true为进行2/3/4/5G网络类型提示 false 不进行网络类型提示
PlayerView setNetWorkTypeTie(boolean isGNetWork)
//是否仅仅为全屏
PlayerView setOnlyFullScreen(boolean isFull)
//设置是否禁止双击
PlayerView setForbidDoulbeUp(boolean flag)
//设置是否禁止隐藏bar
PlayerView setForbidHideControlPanl(boolean flag)
//当前播放的是否是直播
boolean isLive()
//是否禁止触摸
PlayerView forbidTouch(boolean forbidTouch)
//隐藏所有状态界面
PlayerView hideAllUI()
获取顶部控制barview
View getTopBarView()
//获取底部控制barview
View getBottonBarView()
//获取旋转view
ImageView getRationView()
//获取返回view
ImageView getBackView()
//获取菜单view
ImageView getMenuView()
//获取全屏按钮view
ImageView getFullScreenView()
//获取底部bar的播放view
ImageView getBarPlayerView()
//获取中间的播放view
ImageView getPlayerView()
//隐藏返回键,true隐藏,false为显示
PlayerView hideBack(boolean isHide)
//隐藏菜单键,true隐藏,false为显示
PlayerView hideMenu(boolean isHide)
//隐藏分辨率按钮,true隐藏,false为显示
PlayerView hideSteam(boolean isHide)
//隐藏旋转按钮,true隐藏,false为显示
PlayerView hideRotation(boolean isHide)
//隐藏全屏按钮,true隐藏,false为显示
PlayerView hideFullscreen(boolean isHide)
//隐藏中间播放按钮,ture为隐藏,false为不做隐藏处理,但不是显示
PlayerView hideCenterPlayer(boolean isHide)
//显示或隐藏操作面板
PlayerView operatorPanl()
//全屏切换
PlayerView toggleFullScreen()
//设置自动重连的模式或者重连时间,isAuto true 出错重连,false出错不重连,connectTime重连的时间
setAutoReConnect(boolean isAuto, int connectTime)
//进度条和时长显示的方向切换
PlayerView toggleProcessDurationOrientation()
//设置进度条和时长显示的方向,默认为上下显示,PlayStateParams.PROCESS_PORTRAIT为上下显示PlayStateParams.PROCESS_LANDSCAPE为左右显示PlayStateParams.PROCESS_CENTER为中间两边样式
setProcessDurationOrientation(int portrait)
//显示菜单设置
showMenu()
//获取界面方向
int getScreenOrientation()
//显示加载网速
PlayerView setShowSpeed(boolean isShow)

ijkplayer封装的视频播放信息返回码监听

通过setOnInfoListener去监听

/** Do not change these values without updating their counterparts in native*/
int MEDIA_INFO_UNKNOWN = 1;//未知信息
int MEDIA_INFO_STARTED_AS_NEXT = 2;//播放下一条
int MEDIA_INFO_VIDEO_RENDERING_START = 3;//视频开始整备中
int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700;//视频日志跟踪
int MEDIA_INFO_BUFFERING_START = 701;//开始缓冲中
int MEDIA_INFO_BUFFERING_END = 702;//缓冲结束
int MEDIA_INFO_NETWORK_BANDWIDTH = 703;//网络带宽,网速方面
int MEDIA_INFO_BAD_INTERLEAVING = 800;//
int MEDIA_INFO_NOT_SEEKABLE = 801;//不可设置播放位置,直播方面
int MEDIA_INFO_METADATA_UPDATE = 802;//
int MEDIA_INFO_TIMED_TEXT_ERROR = 900;
int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901;//不支持字幕
int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902;//字幕超时int MEDIA_INFO_VIDEO_INTERRUPT= -10000;//数据连接中断
int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;//视频方向改变
int MEDIA_INFO_AUDIO_RENDERING_START = 10002;//音频开始整备中int MEDIA_ERROR_UNKNOWN = 1;//未知错误
int MEDIA_ERROR_SERVER_DIED = 100;//服务挂掉
int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;//数据错误没有有效的回收
int MEDIA_ERROR_IO = -1004;//IO错误
int MEDIA_ERROR_MALFORMED = -1007;
int MEDIA_ERROR_UNSUPPORTED = -1010;//数据不支持
int MEDIA_ERROR_TIMED_OUT = -110;//数据超时

参考自http://blog.csdn.net/jiujiedexiaoming/article/details/52319676

Android基础学习总结(十六)——基于ijkplayer封装支持简单界面UI定制的视频播放器相关推荐

  1. Java基础学习——第十六章 Java8新特性

    Java基础学习--第十六章 Java8 新特性 Java8(JDK8.0)较 JDK7.0 有很多变化或者说是优化,比如 interface 里可以有静态方法和默认方法,并且可以有方法体,这一点就颠 ...

  2. NDK学习笔记(十二) 原生图形api,使用AVILib创建一个AVI视频播放器

    文章目录 1.练练手,使用AVILib创建一个AVI视频播放器 (1)首先下载transcode,并配置avilib. (2)创建AbstractPlayerActivity并实现native方法 ( ...

  3. python基础学习(十六)——超详细!pickle模块的使用(pickle.dump()和pickle.load())

    python的pickle模块提供了一个简答的持久化功能,可以将对象以文件的形式存放在磁盘上. pickle模块实现了基本的数据序列化和反序列化 通过pickle模块的序列化操作pickle.dump ...

  4. Java学习系列(十六)Java面向对象之基于TCP协议的网络通信

    TCP/IP的网络分层模型:应用层(HTTP/FTP/SMTP/POPS...),传输层(TCP协议),网络层(IP协议,负责为网络上节点分配唯一标识),物理层+数据链路层). IP地址用于标识网络中 ...

  5. C1认证学习二十六(基础选择器)

    C1认证学习二十六(基础选择器) 任务背景 CSS选择器是CSS规则的一部分,用来指定需要设置的样式的HTML元素,通过选择器可以实现CSS对HTML元素一对一或者一对多或者多对一的控制了啦. 任务目 ...

  6. SAP UI5 应用开发教程之六十六 - 基于 OData V4 的 SAP UI5 表格控件如何实现删除功能试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  7. C/C++基础讲解(二十六)之数值计算与趣味数学篇(打鱼还是晒网与怎样存钱以获取最大利息)

    C/C++基础讲解(二十六)之数值计算与趣味数学篇(打鱼还是晒网与怎样存钱以获取最大利息) 程序之美 前言 很多时候,特别是刚步入大学的学子们,对于刚刚开展的计算机课程基本上是一团迷雾,想要弄明白其中 ...

  8. Java基础学习——第十四章 网络编程

    Java基础学习--第十四章 网络编程 一.网络编程概述 计算机网络: 把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大.功能强的网络系统,从而使众多的计算机可以方便地互相传递信 ...

  9. C/C++基础讲解(八十六)之游戏篇(解救人质游戏)

    C/C++基础讲解(八十六)之游戏篇(解救人质游戏) 程序之美 前言 很多时候,特别是刚步入大学的学子们,对于刚刚开展的计算机课程基本上是一团迷雾,想要弄明白其中的奥秘,真的要花费一些功夫,我和大家一 ...

  10. 学习笔记:CentOS7学习之十六:LVM管理和ssm存储管理器使用

    目录 学习笔记:CentOS7学习之十六:LVM管理和ssm存储管理器使用 16.1 LVM的工作原理 16.1.1 LVM常用术语 16.1.2 LVM优点 16.2 创建LVM的基本步骤 16.2 ...

最新文章

  1. 如何在企业推行OKR?
  2. mybatis对mysql if函数_Mybatis使用mysql函数if出现错误
  3. VTK:图片之ImageEllipsoidSource
  4. liunx命令(13)——df、free
  5. 内建控制结构之if表达式
  6. 『转载』hadoop2.x常用端口、定义方法及默认端口
  7. java的case_java中的switch case语句使用详解
  8. Kubernetes搭建可扩展的微服务系统
  9. Unity发布四款新产品,加速本土化技术研发
  10. 经典 55道 MySQL面试题及答案
  11. 黑马Python笔记4
  12. matlab求极值的函数
  13. 笔记-5:mysql数据更新
  14. Class34--猜字游戏
  15. 有了这个“神级”功能,会Excel就能轻松玩转BI数据可视化分析啦
  16. unity转微信小程序小游戏
  17. 主题:内存的管理 DATE:2004-09-17
  18. OV、DV、EV证书的区别
  19. 申请android11xColorOS,零时差适配安卓11!ColorOS 11升级公测版体验:丝滑顺畅
  20. labelshop更改打印机_LabelShop最新版

热门文章

  1. 一个线程OOM,进程里其他线程还能运行么?
  2. Android 程序员必须知道的 53 个知识点
  3. Cocos2d-x教程(33)-三维物体AABB碰撞检测算法
  4. gwas snp 和_如何利用分子实验验证GWAS发现的SNP?
  5. Linux 系统常见命令功能大全_【all】
  6. 实验二 分析1996~2015年人口数据各个特征的分布与分散状况
  7. R语言分类算法之距离判别(Distance Discrimination)
  8. bzoj3097 Hash Killer I
  9. PMSG孕马血清促性腺激素适用的应用方案
  10. 即时通讯软件会取代电子邮件吗?