简单 介绍

每天都能看到关于VR的新闻,但是在日常生活中,关于VR的相关却并不多见,虽说今年是VR爆发的元年,然而对普通消费者来说却毫无知觉,VR似乎离我们这么近,又那么的远。

目前VR设备主要分为三大类:VR头盔、VR一体机、VR盒子(类别名称还没有统一叫法)。

目前VR内容的平台虽然不多,但也足够体验用,而且资源也算丰富和全面。下面推荐的内容平台均为APP应用,基本大部分都支持iOS和安卓端使用,比较热门的有:UtoVR、3D%E6%92%AD%E6%92%AD/’ target=’_blank’>3D播播、暴风魔镜、橙子VR、VR热播等(具体见下截图)。

VR开发基础—全景图

搭建VR图片开发的环境

导入从github搜索下载的 google vr sdk (点击查看) 里面的引用库
1、导入谷歌官方提供的库:

commo
commonwidget
panowidget(全景图)
videowidget(全景视频)

2、出现类未定义错误的缺少库


compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'
compile project(':common')
compile project(':commonwidget')
compile project(':panowidget')

3、准备全景图片用来测试代码 放在assets目录下面,例assets/a.jpg
4、对当前应用进行内存设置,希望应用可使用最大内存 避免OOM

<application android:largeHeap="true"

例如:

 <applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"

加载全景图片到内存中成为Bitmap(bitmap是图片在内存中的表示对象),展示在全景图片控件

布局全景图片控件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.itheima.a001vrpanodemo.MainActivity"><com.google.vr.sdk.widgets.pano.VrPanoramaViewandroid:id="@+id/vr_pano"android:layout_width="match_parent"android:layout_height="match_parent"></com.google.vr.sdk.widgets.pano.VrPanoramaView>
</RelativeLayout>

查找控件

 vrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_pano);

因为图片比较大,希望在异步线程里面加载,防止占用主线程

imageTask = new ImageTask();
imageTask.execute("a.jpg");
private class ImageTask extends AsyncTask<String,Void,Bitmap>{//读取资产目录下面的a.jpg图片@Overrideprotected Bitmap doInBackground(String... params) {try {//获取文件流InputStream inputStream = getAssets().open(params[0]);//使用BitmapFactory可以将inputStream,file,byte[]-->BitmapBitmap bitmap = BitmapFactory.decodeStream(inputStream);return bitmap;} catch (IOException e) {e.printStackTrace();}return null;}//在主线程展示位图@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);if(bitmap!=null){//加载bitmap到vr图片控件  参1.BitmapVrPanoramaView.Options options=new VrPanoramaView.Options() ;//TYPE_STEREO_OVER_UNDER :立体图片:上半画面显示在左眼,下半画面显示在右眼//TYPE_MONO :普通图片options.inputType= VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER;//监听加载过程VrPanoramaEventListener listener=new VrPanoramaEventListener(){//加载bitmap异常@Overridepublic void onLoadError(String errorMessage) {super.onLoadError(errorMessage);Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_SHORT).show();}//加载bitmap成功@Overridepublic void onLoadSuccess() {super.onLoadSuccess();Toast.makeText(MainActivity.this, "进入VR图片显示...", Toast.LENGTH_SHORT).show();}};vrPanoramaView.setEventListener(listener);vrPanoramaView.loadImageFromBitmap(bitmap,options);}}}

处理全景控件展示细节

 //页面停到后台,暂停画面显示@Overrideprotected void onPause() {super.onPause();if (vrPanoramaView != null) {vrPanoramaView.pauseRendering();}}//页面回到屏幕,再继续显示@Overrideprotected void onResume() {super.onResume();if (vrPanoramaView != null) {vrPanoramaView.resumeRendering();}//按钮控制
//隐藏info按钮vrPanoramaView.setInfoButtonEnabled(false);//隐藏全屏按钮vrPanoramaView.setFullscreenButtonEnabled(false);//展示全屏//FULLSCREEN_MONO 全屏模式//FULLSCREEN_STEREO CardBoard 纸盒vrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_STEREO);}//页面关闭,销毁图片@Overrideprotected void onDestroy() {super.onDestroy();if (vrPanoramaView != null) {vrPanoramaView.shutdown();}if (imageTask != null && !imageTask.isCancelled()) {//防止页面退出AsyncTask引用的异常imageTask.cancel(true);imageTask = null;}}

完整代码Demo1

public class MainActivity extends AppCompatActivity {private VrPanoramaView vrPanoramaView;private ImageTask imageTask;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//步骤一。搭建VR图片开发的环境//1.1.导入从github搜索下载的google vr sdk 里面的引用库 common,commonwidget,panowidget(全景图片控件库)//1.2.当前这三个库里面缺少序列相关的api,容易引用类找不到,未定义异常//1.3.依赖三个库//1.4.准备全景图片用来测试代码 放在assets目录下面,例assets/a.jpg//1.5.对当前应用进行内存设置,希望应用可使用最大内存 避免OOM  <application android:largeHeap="true"//步骤二。加载全景图片到内存中成为Bitmap(bitmap是图片在内存中的表示对象),展示在全景图片控件//2.1.布局全景图片控件//2.2.查找控件vrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_pano);//2.3.因为图片比较大,希望在异步线程里面加载,防止占用主线程imageTask = new ImageTask();imageTask.execute("a.jpg");}private class ImageTask extends AsyncTask<String,Void,Bitmap>{//2.4.读取资产目录下面的a.jpg图片@Overrideprotected Bitmap doInBackground(String... params) {try {//2.4.1.获取文件流InputStream inputStream = getAssets().open(params[0]);//2.4.2.使用BitmapFactory可以将inputStream,file,byte[]-->BitmapBitmap bitmap = BitmapFactory.decodeStream(inputStream);return bitmap;} catch (IOException e) {e.printStackTrace();}return null;}//2.5.在主线程展示位图@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);if(bitmap!=null){//加载bitmap到vr图片控件  参1.BitmapVrPanoramaView.Options options=new VrPanoramaView.Options() ;//TYPE_STEREO_OVER_UNDER :立体图片:上半画面显示在左眼,下半画面显示在右眼//TYPE_MONO :普通图片options.inputType= VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER;//3.1.监听加载过程VrPanoramaEventListener listener=new VrPanoramaEventListener(){//3.1.1.加载bitmap异常@Overridepublic void onLoadError(String errorMessage) {super.onLoadError(errorMessage);Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_SHORT).show();}//3.1.2.加载bitmap成功@Overridepublic void onLoadSuccess() {super.onLoadSuccess();Toast.makeText(MainActivity.this, "进入VR图片显示...", Toast.LENGTH_SHORT).show();}};vrPanoramaView.setEventListener(listener);vrPanoramaView.loadImageFromBitmap(bitmap,options);}}}//步骤三。处理全景控件展示细节//3.2.页面停到后台,暂停画面显示@Overrideprotected void onPause() {super.onPause();if (vrPanoramaView != null) {vrPanoramaView.pauseRendering();}}//3.3.页面回到屏幕,再继续显示@Overrideprotected void onResume() {super.onResume();if (vrPanoramaView != null) {vrPanoramaView.resumeRendering();}//3.5.按钮控制//3.5.1隐藏info按钮vrPanoramaView.setInfoButtonEnabled(false);//3.5.2隐藏全屏按钮vrPanoramaView.setFullscreenButtonEnabled(false);//3.5.3.展示全屏//FULLSCREEN_MONO 全屏模式//FULLSCREEN_STEREO CardBoard 纸盒vrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_STEREO);}//3.4.页面关闭,销毁图片@Overrideprotected void onDestroy() {super.onDestroy();if (vrPanoramaView != null) {vrPanoramaView.shutdown();}if (imageTask != null && !imageTask.isCancelled()) {//防止页面退出AsyncTask引用的异常imageTask.cancel(true);imageTask = null;}}
}

全景视频展示

搭建全景视频开发环境

导入github搜索google vr sdk 的开发库 common,commonwidget,videowidget

导入API跟全景图片一样,特别是开发全景视频就导入videowidget(全景视频)、如果是开发全景图片就导入panowidget(全景图),根据开发的需要。

依赖 当前三个库缺少的api

compile 'com.google.android.exoplayer:exoplayer:r1.5.10'
compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'
compile project(':common')
compile project(':commonwidget')
compile project(':videowidget')

准备全景视频来测试程序 ,放到assets下面 例 assets/b.mp4
设置应用的内存选项,在内存不足时可以使用最大内存.

在线程加载全景视频,显示在全景视频控件上

界面布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"><com.google.vr.sdk.widgets.video.VrVideoView        android:id="@+id/vr_video_view"android:layout_width="match_parent"android:layout_height="match_parent"></com.google.vr.sdk.widgets.video.VrVideoView><LinearLayout        android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><SeekBar            android:id="@+id/seekbar"android:layout_width="match_parent"android:layout_height="wrap_content" /><TextView            android:id="@+id/time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#AEAEAE"android:gravity="center"android:text="00/100s"android:textColor="#FFFFFF" /></LinearLayout><ProgressBar        android:id="@+id/loading"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true" />
</RelativeLayout>

布局控件并查找

vrVideoView = (VrVideoView) findViewById(R.id.vr_video_view);seekBar = (SeekBar) findViewById(R.id.seekbar);
timeView = (TextView) findViewById(R.id.time);
progressBar = (ProgressBar) findViewById(R.id.loading);

创建子线程加载资源

  videoTask = new VideoTask();videoTask.execute("b.mp4");
private class VideoTask extends AsyncTask<String, Void, Void> {@Overrideprotected Void doInBackground(String... params) {//2.4.从资产目录加载全景视频(类似ProgressBar因为这种控件可以自己处理线程)VrVideoView.Options options = new VrVideoView.Options();//设置参数//立体视频:上半画面显示在左眼,下半画面显示在右眼//普通视频:options.inputType = VrVideoView.Options.TYPE_MONO;//FORMAT_DEFAULT:资源 sd assets//FORMAT_HLS :流媒体  直播options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT;//步骤四:监听加载过程 播放过程VrVideoEventListener listener = new VrVideoEventListener() {//4.1.加载成功 处理加载成的显示@Overridepublic void onLoadSuccess() {super.onLoadSuccess();progressBar.setVisibility(View.GONE);}//4.2.加载失败@Overridepublic void onLoadError(String errorMessage) {super.onLoadError(errorMessage);progressBar.setVisibility(View.GONE);Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_SHORT).show();}//4.3.播放中 onNewFrame执行一次,代表视频播了一个画面@Overridepublic void onNewFrame() {super.onNewFrame();//更新seekbarseekBar.setMax((int) vrVideoView.getDuration());seekBar.setProgress((int) vrVideoView.getCurrentPosition());//正则表达式 更新时间 23.323232323String curr = String.format("%.2f", vrVideoView.getCurrentPosition() / 1000f);String total = String.format("%.2f", vrVideoView.getDuration() / 1000f);timeView.setText(curr + "/" + total + "s");}//4.4.播放完成@Overridepublic void onCompletion() {super.onCompletion();//设置播放位置vrVideoView.seekTo(0);//暂停播放vrVideoView.pauseVideo();isPasuse = true;Toast.makeText(MainActivity.this, "播放完成,是否重播", Toast.LENGTH_SHORT).show();}private boolean isPasuse = false;//4.5.操作:点击继续播放@Overridepublic void onClick() {super.onClick();if (isPasuse) {vrVideoView.playVideo();isPasuse = false;} else {vrVideoView.pauseVideo();isPasuse = true;}}};try {vrVideoView.setEventListener(listener);//vrVideoView.loadVideoFromAsset(params[0], options);vrVideoView.loadVideo(Uri.parse(params[0]),options);} catch (Exception e) {e.printStackTrace();}return null;}}

根据用户的操作来调整显示(性能优化,防止黑屏)

 //3.1.页面 退到后台  暂停显示@Overrideprotected void onPause() {super.onPause();if (vrVideoView != null) {vrVideoView.pauseRendering();}}//3.2.页面 回到屏幕  打开显示@Overrideprotected void onResume() {super.onResume();if (vrVideoView != null) {vrVideoView.resumeRendering();}}//3.3.页面  退出页面 销毁@Overrideprotected void onDestroy() {super.onDestroy();if (vrVideoView != null) {vrVideoView.shutdown();}if (videoTask != null && !videoTask.isCancelled()) {videoTask.cancel(true);videoTask = null;}}

界面设置

在onCreate

  //5.1.设置隐藏infovrVideoView.setInfoButtonEnabled(false);//5.2.设置隐藏全屏vrVideoView.setFullscreenButtonEnabled(false);//5.3.显示全屏//FULLSCREEN_MONO全屏模式//FULLSCREEN_STEREO双眼模式vrVideoView.setDisplayMode(VrWidgetView.DisplayMode.EMBEDDED);

完整代码Demo2

public class MainActivity extends AppCompatActivity {private VrVideoView vrVideoView;private VideoTask videoTask;private ProgressBar progressBar;private TextView timeView;private SeekBar seekBar;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//步骤一。搭建全景视频的开发环境//1.1.导入github搜索google vr sdk 的开发库 common,commonwidget,videowidget//1.2.依赖 当前三个库缺少的api//1.3.准备全景视频来测试程序 ,放到assets下面 例 assets/b.mp4//1.4. 设置应用的内存选项,在内存不足时可以使用最大内存. <application  android:largeHeap="true"//步骤二。在线程加载全景视频,显示在全景视频控件上//2.1.布局控件并查找vrVideoView = (VrVideoView) findViewById(R.id.vr_video_view);//2.2 创建子线程加载资源videoTask = new VideoTask();//2.3.传入文件名
//        videoTask.execute("b.mp4");videoTask.execute("http://youkesvideo.oss-cn-hangzhou.aliyuncs.com/movie2/2016/10/11/%E6%B9%84%E5%85%AC%E6%B2%B3%E8%A1%8C%E5%8A%A8.Operation.Mekong.2016.TC720P.X264.AAC.Mandarin.CHS.Mp4Ba.mp4");seekBar = (SeekBar) findViewById(R.id.seekbar);timeView = (TextView) findViewById(R.id.time);progressBar = (ProgressBar) findViewById(R.id.loading);//步骤五。界面设置//5.1.设置隐藏infovrVideoView.setInfoButtonEnabled(false);//5.2.设置隐藏全屏vrVideoView.setFullscreenButtonEnabled(false);//5.3.显示全屏//FULLSCREEN_MONO全屏模式//FULLSCREEN_STEREO双眼模式vrVideoView.setDisplayMode(VrWidgetView.DisplayMode.EMBEDDED);}private class VideoTask extends AsyncTask<String, Void, Void> {@Overrideprotected Void doInBackground(String... params) {//2.4.从资产目录加载全景视频(类似ProgressBar因为这种控件可以自己处理线程)VrVideoView.Options options = new VrVideoView.Options();//设置参数//立体视频:上半画面显示在左眼,下半画面显示在右眼//普通视频:options.inputType = VrVideoView.Options.TYPE_MONO;//FORMAT_DEFAULT:资源 sd assets//FORMAT_HLS :流媒体  直播options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT;//步骤四:监听加载过程 播放过程VrVideoEventListener listener = new VrVideoEventListener() {//4.1.加载成功 处理加载成的显示@Overridepublic void onLoadSuccess() {super.onLoadSuccess();progressBar.setVisibility(View.GONE);}//4.2.加载失败@Overridepublic void onLoadError(String errorMessage) {super.onLoadError(errorMessage);progressBar.setVisibility(View.GONE);Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_SHORT).show();}//4.3.播放中 onNewFrame执行一次,代表视频播了一个画面@Overridepublic void onNewFrame() {super.onNewFrame();//更新seekbarseekBar.setMax((int) vrVideoView.getDuration());seekBar.setProgress((int) vrVideoView.getCurrentPosition());//更新时间 23.323232323String curr = String.format("%.2f", vrVideoView.getCurrentPosition() / 1000f);String total = String.format("%.2f", vrVideoView.getDuration() / 1000f);timeView.setText(curr + "/" + total + "s");}//4.4.播放完成@Overridepublic void onCompletion() {super.onCompletion();//设置播放位置vrVideoView.seekTo(0);//暂停播放vrVideoView.pauseVideo();isPasuse = true;Toast.makeText(MainActivity.this, "播放完成,是否重播", Toast.LENGTH_SHORT).show();}private boolean isPasuse = false;//4.5.操作:点击继续播放@Overridepublic void onClick() {super.onClick();if (isPasuse) {vrVideoView.playVideo();isPasuse = false;} else {vrVideoView.pauseVideo();isPasuse = true;}}};try {vrVideoView.setEventListener(listener);//vrVideoView.loadVideoFromAsset(params[0], options);vrVideoView.loadVideo(Uri.parse(params[0]),options);} catch (Exception e) {e.printStackTrace();}return null;}}//步骤三。根据用户的操作来调整显示(性能优化,防止黑屏)//3.1.页面 退到后台  暂停显示@Overrideprotected void onPause() {super.onPause();if (vrVideoView != null) {vrVideoView.pauseRendering();}}//3.2.页面 回到屏幕  打开显示@Overrideprotected void onResume() {super.onResume();if (vrVideoView != null) {vrVideoView.resumeRendering();}}//3.3.页面  退出页面 销毁@Overrideprotected void onDestroy() {super.onDestroy();if (vrVideoView != null) {vrVideoView.shutdown();}if (videoTask != null && !videoTask.isCancelled()) {videoTask.cancel(true);videoTask = null;}}
}

获取网络资源的全景图片和全景视频

1.要求获取网络图片,获取网络流是差别

//步骤二。 加载全景图片到内存中成为Bitmap(bitmap是图片在内存中的表示对象), 展示在全景图片控件
//2.1.布局全景图片控件
//2.2.查找控件
vrPanoramaView = new VrPanoramaView(this);
setContentView(vrPanoramaView);//2.3.因为图片比较大, 希望在异步线程里面加载, 防止占用主线程
imageTask = new ImageTask();
imageTask.execute(item.url);
} private class ImageTask extends AsyncTask<String,Void,Bitmap>
{
//2.4.读取资产目录下面的a.jpg图片
@Override
protected Bitmap doInBackground(String... params) {
try {
//2.4.1.获取网络流
URL url=new URL(params[0]);
HttpURLConnection connection= (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(10000);
InputStream inputStream =connection.getInputStream();//2.4.2.使用BitmapFactory可以将inputStream,file,byte[]-->Bitmap
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;} catch (IOException e) {
e.printStackTrace();
} return null;
} //2.5.在主线程展示位图
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if(bitmap!=null)
{
//加载bitmap到vr图片控件 参1.Bitmap
VrPanoramaView.Options options=new VrPanoramaView.Options() ;
//TYPE_STEREO_OVER_UNDER :立体图片: 上半画面显示在左眼, 下半画面显示在右眼
//TYPE_MONO :普通图片
options.inputType= VrPanoramaView.Options.TYPE_MONO;
//3.1.监听加载过程
VrPanoramaEventListener listener=new VrPanoramaEventListener(){
//3.1.1.加载bitmap异常
@Override
public void onLoadError(String errorMessage) {
super.onLoadError(errorMessage);
Toast.makeText(VrImagePlayActivity.this, errorMessage, Toast.LENGTH_SHORT).show();} /
/3.1.2.加载bitmap成功
@Override
public void onLoadSuccess() {
super.onLoadSuccess();
Toast.makeText(VrImagePlayActivity.this, "进入VR图片显示...", Toast.LENGTH_SHORT).show();
}
};
vrPanoramaView.setEventListener(listener);
vrPanoramaView.loadImageFromBitmap(bitmap,options);}}
}

2.全景的网络视频

 private class VideoTask extends AsyncTask<String, Void, Void> {@Overrideprotected Void doInBackground(String... params) {//2.4.从资产目录加载全景视频(类似ProgressBar因为这种控件可以自己处理线程)VrVideoView.Options options = new VrVideoView.Options();//设置参数//立体视频:上半画面显示在左眼,下半画面显示在右眼//普通视频:options.inputType = VrVideoView.Options.TYPE_MONO;//FORMAT_DEFAULT:资源 sd assets//FORMAT_HLS :流媒体  直播options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT;//步骤四:监听加载过程 播放过程VrVideoEventListener listener = new VrVideoEventListener() {//4.1.加载成功 处理加载成的显示@Overridepublic void onLoadSuccess() {super.onLoadSuccess();progressBar.setVisibility(View.GONE);}//4.2.加载失败@Overridepublic void onLoadError(String errorMessage) {super.onLoadError(errorMessage);progressBar.setVisibility(View.GONE);Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_SHORT).show();}//4.3.播放中 onNewFrame执行一次,代表视频播了一个画面@Overridepublic void onNewFrame() {super.onNewFrame();//更新seekbarseekBar.setMax((int) vrVideoView.getDuration());seekBar.setProgress((int) vrVideoView.getCurrentPosition());//更新时间 23.323232323String curr = String.format("%.2f", vrVideoView.getCurrentPosition() / 1000f);String total = String.format("%.2f", vrVideoView.getDuration() / 1000f);timeView.setText(curr + "/" + total + "s");}//4.4.播放完成@Overridepublic void onCompletion() {super.onCompletion();//设置播放位置vrVideoView.seekTo(0);//暂停播放vrVideoView.pauseVideo();isPasuse = true;Toast.makeText(MainActivity.this, "播放完成,是否重播", Toast.LENGTH_SHORT).show();}private boolean isPasuse = false;//4.5.操作:点击继续播放@Overridepublic void onClick() {super.onClick();if (isPasuse) {vrVideoView.playVideo();isPasuse = false;} else {vrVideoView.pauseVideo();isPasuse = true;}}};try {vrVideoView.setEventListener(listener);//vrVideoView.loadVideoFromAsset(params[0], options);vrVideoView.loadVideo(Uri.parse(params[0]),options);} catch (Exception e) {e.printStackTrace();}return null;}}
//加载网络视图 1.参数url 2.options
vrVideoView.loadVideo(Uri.parse(params[0]),options);

3.注意网络问题

权限

<!--联网-->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

手机联网
服务器开启

新技术VR—开发详细讲解相关推荐

  1. 万字以上的电商项目 Jmeter 脚本实战测试开发详细讲解

    目录 一.前置工作 1.黄金流程 2.Jmeter安装 二.脚本实战开发 1.用户注册链路 2.用户下单链路 一.前置工作 1.黄金流程 在做性能脚本之前,先了解下这本次性能实战业务,简要说明本次使用 ...

  2. Android 编程之入门开发文件夹管理器开发详细讲解-1

    在我们的手持设备中,一般都会自带设备公司自己开发的文件管理系统.拍照系统之类的东东,今天我给大伙说说入门级开发的文件夹管理器,代码贼少 总共就6个类吧,没有夹杂其他外部应用,就是一个纯文件夹管理器 A ...

  3. vue-trtc多人视频开发(从零开始)-有手就行篇-最详细讲解

    大家花个几分钟把帖子详细看完  新手也能做直播集成开发!一步到位  相信小编 最效率最省力最通透的文档! 甚至直接可以copy使用的哦!!但是记得给小编一个赞吧 孩子天天熬夜加班 还写博客确实不容易 ...

  4. Flowable 快速入门教程:Flowable 入门开发案例,结合流程设计器详细讲解

    Flowable 快速入门教程:Flowable 入门开发案例,结合流程设计器详细讲解 前言 流程设计器集成 整体流程图 流程节点说明 第一审核人节点:实际设置审核人 配置信息 说明 第二审核人:参数 ...

  5. Android架构详细讲解与C/C++开发支持原理

    Android架构详细讲解与C/C++开发支持原理 在Android 在NDK r5使用C/C++进行开发.(以前,Android 对C/C++开发的支持仅限于用C/C++开发动态链接库,然后在Jav ...

  6. Discuz二次开发基本知识详细讲解

    Discuz是国内最流行的论坛软件管理系统,今天小编跟大家分享一篇关于Discuz二次开发基本知识详细讲解,感兴趣的朋友跟小编一起来了解一下吧! 一) Discuz!的文件系统目录注:想搞DZ开发,就 ...

  7. IOS开发入门之Xcode使用教程详细讲解(全)

    摘要:本次的IOS开发入门学习中,Xcode使用教程详细讲解是本文要介绍的内容,Xcode是一个款强大的IDE开发环境,就像你在写Windows程序时需要VS2005一样 需要要Xcode为你写Mac ...

  8. 程序员2016年5月:走进VR开发世界

    时至今日,VR技术仍处在一个萌芽期,Oculus.Gear VR.PlayStation VR在经过长时间的精细打磨后才逐渐为大众所触知.在硬件升级的同时,对于以游戏为主的内容开发而言,核心即在于Un ...

  9. 《AR与VR开发实战》导读

    前 言 增强现实(Augmented Reality)简称AR,是一种实时计算摄像机捕捉到的现实影像的位置及角度并加上相应虚拟信息的技术.这种技术不仅能展现真实世界的信息,还能通过增加虚拟信息而对现实 ...

最新文章

  1. 2019年,自动化机器学习AutoML技术还火吗? | BDTC 2019
  2. 虚拟机做linux服务器,用 VirtualBox 的 linux 虚拟机做服务器
  3. c#将对象序列化为字符串和将字符串反序列化为对象
  4. 出入口控制系统工程设计规范_【理论冲刺】传说中的隐藏书目——《公园设计规范》...
  5. python subprocess阻塞
  6. VC++ .net 2005运行库解析
  7. python装饰器函数执行后日志_Python装饰器记录日志、异常处理、函数添加,python,处理函数,功能...
  8. (二)使用预定义模型 QStringListModel例子
  9. Activity not started, its current task has been brought to the front 。
  10. python画3d图-Python 竟能绘制如此酷炫的三维图
  11. 前端监控和前端埋点方案设计
  12. 服务器配置文件设计,IM配置服务器概要的设计文件.doc
  13. 翻译: 2.5. 自动微分 深入神经网络 pytorch
  14. iOS UITextView字数限制 拼音
  15. Python中机器学习模型的几种保存方式
  16. 手机扫描电脑百度网盘二维码,二维码无法刷新的解决办法
  17. Ubuntu在线安装NFS服务
  18. 【HTML粉色跳动爱心】效果展示+源代码
  19. Java JavaScript BOM和正则表达式
  20. Facebook:寻找出路的小巨人

热门文章

  1. matlab定积分积不出来,某些“积不出”函数的定积分近似计算方法及其原函数的近似曲线...
  2. 女生勿扰,只适合男孩子的python爬虫,男生记得偷偷爬哦!
  3. 华氏温度转化为摄氏度
  4. vtk教程第一章介绍
  5. 3个超好用的图片压缩软件,超高压缩比,保持图片清晰度
  6. 软件定义汽车下,大众“笨重”转型
  7. 做短视频时自己的声音不好听,有没有让声音好听的办法?
  8. iPhone 7-b
  9. 用VMware虚拟机安装Ubuntu时出现窗口显示不完全的解决方案
  10. ProcessDB实时/时序数据库——C/C++操作数据库对象