Google VR全景图片与视频功能开发详解

1. VR开发概述

时下关于“谷歌、Android与VR”的各种言论纷飞。VR群里有人在争论Android VR是不是一体机,是不是类似Android Wear、为VR打造的全新平台,是不是改良后的Android N。

随着vr设备的流行开来,各大招聘平台上也发布了不少关于andorid vr开发相关的Android工程师岗位,从这点来说掌握vr在项目中的实际应用要点,有助于大家为自己的开发经验上增加前沿技术的积累。

经过研发市面上的主流vr app 的功能,抽取并整合项目中的vr开发知识点,希望大家掌握后,在企业相关vr app游刃有余。

1.1 下载google vr sdk 并搭建开发环境

  1. 带大家去github上搜索并下载google vr sdk
  2. 介绍sdk的组成部分与应用范围
  3. 搭建一个基本android vr app的开发环境

1.2 CardBorad应用核心功能

  1. 带大家查找本地vr 全景图片资源
  2. 介绍vr全景图与普通图片的不同点
  3. 使用rv列表进行展示
  4. 使用VrPanoramaView控件进行本地全景图片的展示

1.3 UtoVR应用核心功能

  1. 带大家通过网络请求获取vr视频的json数据
  2. 使用 Gson解析得到javaBean数据
  3. 使用VrVideoView控件进行网络全景视图的展示

以上这些功能是现流行的在线vr视频,vr图片相关app的核心功能。例如.vr管家应用,3d播播,discovery VR ,看房 vr等等热门应用。

1.4 知识点

  1. http网络请求技术
  2. Gson解析技术与gsonformat插件
  3. RecyclerView与cardView
  4. Glider流行图片加载框架
  5. VrPanoramaView
  6. VrVideoView

1.5 好玩好用的VR

成本其实很便宜!教你用手机体验VR魅力

  • 17块钱!把手机改造为VR眼镜
  • 好玩好用的VR APP推荐

2. 全景图片显示

2.1 搭建vr全景图片的开发环境

VR开发需要gvr-android-sdk,GitHub下载地址

VR开发Google官方技术文档

2.1.1 导入全景图相关的三个开发库

common,commonwidget,panowidget

2.1.2 依赖该库

compile project(‘:common‘)
compile project(‘:commonwidget‘)
compile project(‘:panowidget‘)
//google的一套序列化数据结构开发库
compile ‘com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7‘

2.1.3 准备全景图片测试资源

放在assets目录 例:assets/a.jpg(全景图与普通图片的不同 大,立体)

2.1.4 功能清单配置

android:largeHeap=”true” 全景图片比较耗资源

<application
    android:largeHeap="true">
</application>

2.2 布局全景控件显示加载后的全景图片

<com.google.vr.sdk.widgets.pano.VrPanoramaView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/vr_pv" />
public class MainActivity extends AppCompatActivity {

    private VrPanoramaView vrPanoramaView;
    private ImageTask imageTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //全景图片的浏览功能
        //步骤一。下载github上google开源 vr-sdk
        //1.1.导入到我们的工作空间 common,commonwidget  panowidget
        //1.2.依赖到我们的项目中
        //1.3.依赖sdk中找不到的api
        //1.4.准备一些测试素材 放置在assets目录下面 例:assets/a.jpg
        //1.5.开启内存设置  android:largeHeap="true"尽可能使应用使用最大内存

2.2.1 布局查找控件

//步骤二。布局全景控件显示加载后的全景图片
//2.1.布局查找控件
vrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_pv);

2.2.2 设置初始化参数

//2.2.设置初始化参数
vrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_STEREO);
//删除不需要连接,信息图标
vrPanoramaView.setInfoButtonEnabled(false);
//隐藏全屏按钮
vrPanoramaView.setFullscreenButtonEnabled(false);

2.2.3 创建异步任务加载图片

Bitmap是图片在内存中的表示对象,全景图也可加载成bitmap

    //2.3.创建异步任务加载图片 Bitmap是图片在内存中的表示对象,全景图也可加载成bitmap
    imageTask = new ImageTask();
    imageTask.execute();

}
private class ImageTask extends AsyncTask<Void, Void, Bitmap> {
    @Override
    protected Bitmap doInBackground(Void... params) {
        //2.4.从资产目录打开一个流
        try {
            InputStream inputStream = getAssets().open("a.jpg");
            //2.5.使用BitmapFactory转换成Bitmap
            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
            return bitmap;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    //2.6任务执行完后,可获取Bitmap图片
    @Override
    protected void onPostExecute(Bitmap bitmap) {
        super.onPostExecute(bitmap);
        if (bitmap != null) {
            //loadImageFromBitmap加载bitmap到显示控件 参1.bitmap 参2 显示参数的封装
            VrPanoramaView.Options options = new VrPanoramaView.Options();
            //加载立体图片,上部分显示在左眼,下部分显示在右眼
            options.inputType = VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER;
            if (listener == null) {
                listener = new VrPanoramaEventListener() {
                    @Override
                    public void onLoadError(String errorMessage) {
                        super.onLoadError(errorMessage);
                        //处理加载失败的情况
                        Toast.makeText(MainActivity.this, "错误消息:" + errorMessage, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onLoadSuccess() {
                        super.onLoadSuccess();
                        //成功的情况提示下现在要进行全景图片的展示
                        Toast.makeText(MainActivity.this, "进入vr:", Toast.LENGTH_SHORT).show();
                    }
                };
                // 增加加载出错的业务逻辑处理
                vrPanoramaView.setEventListener(listener);
            }
            //2.7.让控件加载bitmap对象
            vrPanoramaView.loadImageFromBitmap(bitmap, options);
            //2.8.如果loadImageFromBitmap加载失败需要提示用户相关信息则需要添加事件监听器listener
        }
    }
}
private VrPanoramaEventListener listener;

2.3 VrPanoramaView控件退到后台,回到屏幕,销毁处理细节

    //步骤三。VrPanoramaView控件退到后台,回到屏幕,销毁处理细节
    //3.1.退到后台.暂停显示
    @Override
    protected void onPause() {
        super.onPause();
        if (vrPanoramaView != null) {
            vrPanoramaView.pauseRendering();
        }
    }
    //3.2.回到屏幕,恢复显示
    @Override
    protected void onResume() {
        super.onResume();
        if (vrPanoramaView != null) {
            vrPanoramaView.resumeRendering();
        }
    }
    //3.3.退出界面停止显示
    @Override
    protected void onDestroy() {
        if (vrPanoramaView != null) {
            vrPanoramaView.shutdown();
        }
        if (imageTask != null && !imageTask.isCancelled()) {//销毁任务
            imageTask.cancel(true);
            imageTask = null;
        }
        super.onDestroy();
    }
}
package com.itheima.demovrimagevideo2;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

import com.google.vr.sdk.widgets.common.VrWidgetView;
import com.google.vr.sdk.widgets.pano.VrPanoramaEventListener;
import com.google.vr.sdk.widgets.pano.VrPanoramaView;

import java.io.IOException;
import java.io.InputStream;

public class MainActivity extends AppCompatActivity {

    private VrPanoramaView vrPanoramaView;
    private ImageTask imageTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //全景图片的浏览功能
        //步骤一。下载github上google开源 vr-sdk
        //1.1.导入到我们的工作空间 common,commonwidget  panowidget
        //1.2.依赖到我们的项目中
        //1.3.依赖sdk中找不到的api
        //1.4.准备一些测试素材 放置在assets目录下面 例:assets/a.jpg
        //1.5.开启内存设置  android:largeHeap="true"尽可能使应用使用最大内存
        //步骤二。将全景图片加载到内存中,再显示在控件
        //2.1.布局全景图片显示控件
        vrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_pano);
        //删除不需要连接
        vrPanoramaView.setInfoButtonEnabled(false);
        //隐藏全屏按钮
        vrPanoramaView.setFullscreenButtonEnabled(false);
        //2.2.所有的图片在内存表示成Bitmap
        imageTask = new ImageTask();
        imageTask.execute();
        //vrPanoramaView.loadImageFromBitmap(bitmap);
    }

    //2.3.AsyncTask异步加载
    private class ImageTask extends AsyncTask<Void, Void, Bitmap> {
        @Override
        protected Bitmap doInBackground(Void... params) {
            try {
                InputStream inputStream = getAssets().open("a.jpg");
                //2.4.使用BitmapFactory 可以sd ,byte[] inputstream-->Bitmap
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                return bitmap;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            if (bitmap != null) {
                //loadImageFromBitmap加载bitmap到显示控件 参1.bitmap 参2 显示参数的封装
                VrPanoramaView.Options option = new VrPanoramaView.Options();
                //立体图片:上半张显示在左眼,下半张显示在右眼
                option.inputType = VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER;
                VrPanoramaEventListener listener=new VrPanoramaEventListener(){
                    @Override
                    public void onLoadSuccess() {
                        super.onLoadSuccess();
                        //成功的情况提示下现在要进行全景图片的展示
                        Toast.makeText(MainActivity.this, "进入vr图片", Toast.LENGTH_SHORT).show();
                    }
                    @Override
                    public void onLoadError(String errorMessage) {
                        super.onLoadError(errorMessage);
                        //处理加载失败的情况
                        Toast.makeText(MainActivity.this, "E:"+errorMessage, Toast.LENGTH_SHORT).show();
                    }
                };
                //2.5.增加加载出错的业务逻辑处理
                vrPanoramaView.setEventListener(listener);
                //2.6.全屏展示
                vrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_MONO);
                //2.4.加载bitmap到控件上显示
                vrPanoramaView.loadImageFromBitmap(bitmap, option);
            }
        }
    }
    //步骤三。优化程序细节 ,页面退到后台,暂停显示 ,页面显示在屏幕 恢复显示。销毁页面,释放全景图片

    //3.1 页面退到后台,暂停显示
    @Override
    protected void onPause() {
        super.onPause();
        if(vrPanoramaView!=null)
        {
            vrPanoramaView.pauseRendering();
        }
    }
    //3.2 页面显示在屏幕 恢复显示
    @Override
    protected void onResume() {
        super.onResume();
        if(vrPanoramaView!=null)
        {
            vrPanoramaView.resumeRendering();
        }
    }
    //3.3.销毁页面,释放全景图片
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (vrPanoramaView != null) {
            vrPanoramaView.shutdown();
        }
        if (imageTask != null && !imageTask.isCancelled()) {
            imageTask.cancel(true);
            imageTask = null;
        }
    }
}

3. 全景视频显示开发

3.1 vr视频环境搭建

  • 导入需要的三个库 common,comonwidget.videowiget
  • 依赖这三个库
  • 准备显示使用到全景视频 assets目录下面 例:assets/b.mp4
  • 配置大内存选项 android:largeHeap=”true” 可以使用最大内存

3.1.1 导入vr sdk 中的相关库

common,commonwidget,videowidget

3.1.2 依赖以上三个库

compile project(‘:common‘)
compile project(‘:commonwidget‘)
compile project(‘:videowidget‘)
// 出现类未定义错误的缺少库
compile ‘com.google.android.exoplayer:exoplayer:r1.5.10‘
compile ‘com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7‘

3.1.3 打开内存设置 android:largeHeap=”true”

<application
        android:largeHeap="true">
</application>

3.1.4 准备测试使用的全景视频

放置在assets目录 例:assets/congo_2048.mp4

3.2 布局视频控件,并加载视频内容

public class MainActivity extends AppCompatActivity {

    private VrVideoView vrVideoView;
    private VideoTask videoTask;
    private SeekBar seekBar;
    private TextView text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //步骤一。搭建vr全景视频的开发环境
        //1.1.导入需要的三个库 common,comonwidget.videowiget
        //1.2.依赖这三个库
        //1.3.准备显示使用到全景视频 assets目录下面 例:assets/b.mp4
        //1.4.配置大内存选项   android:largeHeap="true" 可以使用最大内存
        //步骤二。布局视频控件,并加载视频内容
        //2.1布局控件
        //2.2查找控件
        vrVideoView = (VrVideoView) findViewById(R.id.vr_vv);
        //2.3加载视频数据
        videoTask = new VideoTask();
        videoTask.execute("congo_2048.mp4");
    }
    // 创建异步任务防止占用主线程
    private class VideoTask extends AsyncTask<String, Void, Void> {
        @Override
        protected Void doInBackground(String... params) {
           // 把文件名取出来进行加载  视频资源来自asssets
            VrVideoView.Options options = new VrVideoView.Options();
            //2.4.输入模式
            //立体模式
            options.inputType = VrVideoView.Options.TYPE_STEREO_OVER_UNDER;
            //2.5.设置视频来源
            //处理视频加载的格式(sd卡或者assets)
            //options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT;
            //FORMAT_DEFAULT 视频资源来自assetss/sd
            //FORMAT_HLS 视频来自网络流媒 直播
            //处理视频加载的格式 流媒体直播格式
            options.inputFormat=VrVideoView.Options.FORMAT_HLS;
            try {
                //2.8 如果资源有问题,不能正常播放需要处理下界面提示
                if (listener == null) {
                    listener = new VrVideoEventListener() {
                        @Override
                        public void onLoadSuccess() {
                            super.onLoadSuccess();
                            //获取当前总时长
                            long max=vrVideoView.getDuration();
                            seekBar.setMax((int) max);
                            seekBar.setProgress(0);
                            Toast.makeText(MainActivity.this, "准备播放vr", Toast.LENGTH_SHORT).show();

                        }
                        @Override
                        public void onNewFrame() {
                            super.onNewFrame();
                            //获取当前播放位置
                            long currentPosition = vrVideoView.getCurrentPosition();
                            //设置当前进度
                            seekBar.setProgress((int) currentPosition);
                            //时间值
                            String total=String.format("%.2f",vrVideoView.getDuration()/1000f);
                            String curr=String.format("%.2f",vrVideoView.getCurrentPosition()/1000f);
                            text.setText("播放进度"+curr+":"+total);
                        }
                        private boolean isPause=true;
                        @Override
                        public void onCompletion() {
                            super.onCompletion();
                            seekBar.setProgress(0);
                            vrVideoView.seekTo(0);//重回0位置
                            vrVideoView.pauseVideo();//暂停播放
                            isPause=true;//保存暂停状态
                        }

                        @Override
                        public void onClick() {
                            super.onClick();
                            if (isPause) {//播放
                                vrVideoView.playVideo();
                                isPause=false;
                            } else {
                                vrVideoView.pauseVideo();
                                isPause=true;
                            }
                        }

                        @Override
                        public void onLoadError(String errorMessage) {
                            super.onLoadError(errorMessage);
                            Toast.makeText(MainActivity.this, "加载失败", Toast.LENGTH_SHORT).show();
                        }
                    };
                    vrVideoView.setEventListener(listener);
                }
                //2.7加载视频资源
                //vrVideoView.loadVideoFromAsset(params[0], options);
                String url="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";
                vrVideoView.loadVideo(Uri.parse(url),options);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    private VrVideoEventListener listener;

3.3 处理页面退到后台,回到屏幕,页面销毁

    //步骤三。处理页面退到后台,回到屏幕,页面销毁。

    //3.1.页面退到后台暂停视频
    @Override
    protected void onPause() {
        super.onPause();
        if (vrVideoView != null) {
            vrVideoView.pauseRendering();
        }
    }

    //3.2.页面回到屏幕继续播放
    @Override
    protected void onResume() {
        super.onResume();
        if (vrVideoView != null) {
            vrVideoView.resumeRendering();
        }
    }

    //3.3.页面销毁
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (vrVideoView != null) {
            vrVideoView.shutdown();
        }
        if (videoTask != null && !videoTask.isCancelled()) {
            videoTask.cancel(false);
            videoTask = null;
        }
    }
}

3.4 添加进度条相关事件

3.4.1布局查找出控件

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <SeekBar
        android:id="@+id/seek_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/text"
        android:background="#AEAEAE"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textColor="#FFFFFF"
        android:textSize="22sp"
        android:text="00:00" />
</LinearLayout>
seekBar = (SeekBar) findViewById(R.id.seek_bar);
text = (TextView) findViewById(R.id.text);

3.4.2.加载成功设置最大值

在VrVideoEventListener中的onLoadSuccess处理

3.4.3.在播放过程中不断更新

进度值 onNewFrame 每播放一个画面就调用该方法一次

3.4.4.同步理新文本时间值

在VrVideoEventListener中的onNewFrame处理

3.4.5.播放完成重新播放

在VrVideoEventListener中的onCompletion处理

package com.itheima.appvideo;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.google.vr.sdk.widgets.common.VrWidgetView;
import com.google.vr.sdk.widgets.video.VrVideoEventListener;
import com.google.vr.sdk.widgets.video.VrVideoView;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {

    private VrVideoView vrVideoView;
    private VideoTask task;
    private SeekBar seekBar;
    private TextView timeText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //步骤一。搭建vr全景视频的开发环境
        //1.1.导入需要的三个库 common,comonwidget.videowiget
        //1.2.依赖这三个库
        //1.3.准备显示使用到全景视频 assets目录下面 例:assets/b.mp4
        //1.4.配置大内存选项   android:largeHeap="true" 可以使用最大内存
        //步骤二。加载视频到内存中,再使用控件显示
        //2.1 布局全景视频控件
        vrVideoView = (VrVideoView) findViewById(R.id.vr_video_view);
        //2.2加载全景视频
        task = new VideoTask();
        task.execute("b.mp4");
        seekBar = (SeekBar) findViewById(R.id.seekbar);
        timeText = (TextView) findViewById(R.id.time);
    }

    //2.2.1创建异步任务防止占用主线程
    private class VideoTask extends AsyncTask<String, Void, Void> {
        @Override
        protected Void doInBackground(String... params) {
            //2.2.2.把文件名取出来进行加载  视频资源来自asssets
            VrVideoView.Options options = new VrVideoView.Options();
            //立体的视频资源:上半画面显示在左眼,下半画面显示右眼
            options.inputType = VrVideoView.Options.TYPE_STEREO_OVER_UNDER;
            //FORMAT_DEFAULT 视频资源来自assetss/sd
            //FORMAT_HLS 视频来自网络流媒 直播
            options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT;
            try {
                //步骤四.编写进度显示 业务逻辑
                VrVideoEventListener listener = new VrVideoEventListener() {
                    //4.1.加载成功
                    @Override
                    public void onLoadSuccess() {
                        super.onLoadSuccess();
                        Toast.makeText(MainActivity.this, "准备放3d视频", Toast.LENGTH_SHORT).show();
                        upProgress();
                    }

                    //4.2加载失败的提示
                    @Override
                    public void onLoadError(String errorMessage) {
                        super.onLoadError(errorMessage);
                        Toast.makeText(MainActivity.this, "视频加载失败" + errorMessage, Toast.LENGTH_SHORT).show();
                    }

                    //4.3.显示播放时长与播放进度
                    //4.3.1.布局显示控件SeekBar 与TextView
                    //4.3.2.查找出来
                    //4.3.3.在onLoadSuccess里面获取视频时长 视频播放位置
                    //4.3.4.在onNewFrame  不断获取最新的进度值来更新界面
                    @Override//播放了一个画面,onNewFrame就被调用次
                    public void onNewFrame() {
                        super.onNewFrame();
                        upProgress();
                    }

                    private boolean isPause = false;

                    //4.4.处理播放完成
                    @Override
                    public void onCompletion() {
                        super.onCompletion();
                        vrVideoView.seekTo(0);
                        vrVideoView.pauseVideo();
                        isPause = true;
                        upProgress();
                    }

                    //4.5.点击业务
                    @Override
                    public void onClick() {
                        super.onClick();
                        if (isPause) {
                            isPause = false;
                            vrVideoView.playVideo();
                        } else {
                            isPause = true;
                            vrVideoView.pauseVideo();
                        }
                    }
                };
                vrVideoView.setEventListener(listener);
                vrVideoView.loadVideoFromAsset(params[0], options);//参1文件名 参2 设置参数
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        private void upProgress() {
            long max = vrVideoView.getDuration();
            long currPosition = vrVideoView.getCurrentPosition();
            seekBar.setMax((int) max);
            seekBar.setProgress((int) currPosition);
            timeText.setText(String.format("%.2f", currPosition / 1000f) + "/" + String.format("%.2f", max / 1000f));
        }
    }
    //步骤三。程序优化 页面退到后台,暂停  页面回到屏幕继续播放  页面销毁 关闭

    //3.1. 页面退到后台,暂停
    @Override
    protected void onPause() {
        super.onPause();
        if (vrVideoView != null) {
            vrVideoView.pauseRendering();
        }
    }

    //3.2 页面回到屏幕继续播放
    @Override
    protected void onResume() {
        super.onResume();
        if (vrVideoView != null) {
            vrVideoView.resumeRendering();
        }
    }

    //3.3. 页面销毁 关闭销毁
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (vrVideoView != null) {
            vrVideoView.shutdown();
        }
        if (task != null && !task.isCancelled()) {
            task.cancel(true);
            task = null;
        }
    }
}
时间: 2024-09-30 10:51:42

Google VR全景图片与视频功能开发详解的相关文章

小程序-微信聊天功能开发详解

需求:聊天功能(效果参照微信聊天) 直接先放效果图吧! 框架: wepy (vue) 主要思路: 1.布局只编写一个消息组件,包括头像和内容两部分!flex布局(左到右row),对方发来的消息正常显示,我方发出去的消息右到左布局(flex-direction: row-reverse;),这样增加了消息组件的复用!如图消息组件: 2.消息数据全部存储在一个Array中,demo如图:text为消息内容.isMine判断该消息来自于对方还是我自己,从而动态消息item的CSS布局(左到右或右到左)

下载Zookeeper从入门到精通(开发详解,案例实战,Web界面监控)

ZooKeeper是Hadoop的开源子项目(Google Chubby的开源实现),它是一个针对大型分布式系统的可靠协调系统,提供的功能包括:配置维护.命名服务.分布式同步.组服务等. Zookeeper的Fast Fail 和 Leader选举特性大大增强了分布式集群的稳定和健壮性,并且解决了Master/Slave模式的单点故障重大隐患,这是越来越多的分布式产品如HBase.Storm(流计算).S4(流计算)等强依赖Zookeeper的原因. Zookeeper从入门到精通(开发详解,案

Android相机开发详解(一)

Android相机开发详解(一) 请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的csdn博客) Android相机开发能够实现打开相机,前后摄像头切换,摄像预览,保存图片,浏览已拍照图片等相机功能. Android相机开发详解(一)主要实现打开相机,摄像预览,前后置摄像头切换,保存图片等四个功能. Android相机开发详解(二)主要实现翻页浏览相片,触控缩放浏览图片,删除图片,发送图片等四个功能. Andro

【转】【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料

转载请注明出处:http://blog.csdn.net/yangyu20121224/article/details/9057257 由于公司项目的需要,要实现在项目中使用第三方授权登录以及分享文字和图片等这样的效果,几经波折,查阅了一番资料,做了一个Demo.实现起来的效果还是不错的,不敢独享,决定写一个总结的教程,供大家互相交流.学习和参考,博主只求能和大家共同进步.希望能多多支持! 这篇文章中,我们使用到了Share SDK,它是为iOS.Android.WP8的APP提供社会化功能的一

基于H5的微信支付开发详解

这次总结一下用户在微信内打开网页时,可以调用微信支付完成下单功能的模块开发,也就是在微信内的H5页面通过jsApi接口实现支付功能.当然了,微信官网上的微信支付开发文档也讲解的很详细,并且有实现代码可供参考,有的朋友直接看文档就可以自己实现此支付接口的开发了. 一.前言 为何我还写一篇微信支付接口的博文呢?第一,我们必须知道,所谓的工作经验很多都是靠总结出来的,你只有总结了更多知识,积累了更多经验,你才能在该行业中脱颖而出,我个人觉得如今的招聘,很多都需要工作经验(1年.3年.5年....),其

opencart 模块开发详解

opencart 模块开发详解 由 xiekanxiyang » 2013年 7月 11日 10:17 pm opencart 将页面分成若干模块, 每个模块可以有多个实例(可能这样说不是很恰当) 每个实例可以指定它出现在哪个页面 这样更好的实现了代码的可重用性,可以达到更好的页面布局的可调节性. Opencar内置了几个模块,但实际应用中我们经常要根据需要开发自己模块,现在我给大家介绍下opencart的模块开发的细节 开发步骤:首先:模块代码也分前台,后台. 后台功能是模块的安装,编辑,模块

Apple Watch 开发详解

Apple Watch  开发详解 Apple Watch 开发详解 Apple Watch现在对于第三方开发者来说更多的还是一块额外的屏幕.暂时WatchKit没有能给出足够的接口.现在Watch App的主要运算逻辑需要依赖iPhone,Apple也承诺会有原生的手表App,可能要等到Apple Watch和WatchKit的完全版面世的时候. 1.两种屏幕分辨率 屏幕尺寸 38mm 42mm 分辨率 272 x 340 312 x 390 宽高比 4:5 4:5 2.三种屏幕模式 主屏模式

****基于H5的微信支付开发详解[转]

这次总结一下用户在微信内打开网页时,可以调用微信支付完成下单功能的模块开发,也就是在微信内的H5页面通过jsApi接口实现支付功能.当然了,微信官网上的微信支付开发文档也讲解的很详细,并且有实现代码可供参考,有的朋友直接看文档就可以自己实现此支付接口的开发了. 一.前言 为何我还写一篇微信支付接口的博文呢?第一,我们必须知道,所谓的工作经验很多都是靠总结出来的,你只有总结了更多知识,积累了更多经验,你才能在该行业中脱颖而出,我个人觉得如今的招聘,很多都需要工作经验(1年.3年.5年....),其

《Linux设备驱动开发详解(第3版)》海量更新总结

本博实时更新<Linux设备驱动开发详解(第3版)>的最新进展. 2015.2.26 几乎完成初稿. [F]是修正或升级:[N]是新增知识点:[D]是删除的内容 第1章 <Linux设备驱动概述及开发环境构建>[D]删除关于LDD6410开发板的介绍[F]更新新的Ubuntu虚拟机[N]添加关于QEMU模拟vexpress板的描述 第2章 <驱动设计的硬件基础> [N]增加关于SoC的介绍:[N]增加关于eFuse的内容:[D]删除ISA总线的内容了:[N]增加关于SP