基于android的增强现实应用开发基础

时间:2022-12-03 03:27:20

求从事移动应用开发以及基于移动终端的AR应用开发的朋友,一起做一些事!有兴趣可以给我私信,谢谢!

基于android的增强现实应用开发基础

1、  简单介绍android的平台架构及特性

2、  Android5大组件及他们之间的关系

3、  Android增强现实应用开发的所需要的主要的API

4、  GPS

5、  Camera

6、  Sensor

7、  Opengl es

谷歌于2007115日发布了android1.0版本。原意是机器人,现在所代表的主要意思是Google的基于Linux平台开源的手机操作系统。现在最新的版本是今年北京时间628日发布的4.1(Jelly Bean,果冻豆)Android 4.1新增三重影像缓冲技术,让所有的渲染感觉更顺畅。触摸延时不仅会遵循VSYNC计时,还会在触摸操作时做出预判提前渲染,此外在CPU闲置时会分配更多的处理能力来应对触摸事件,确保触摸没有延迟。

Android系统结构图有四个部分,分别是操作系统,中间件,用户界面,和应用软件。在图上可以看到五部分,应用程序层,应用程序框架,函数库,运行时,以及Linux内核层。

主要包括一些驱动程序,例如蓝牙,wifi,相机等等,使用的语言是c/c++

Android依赖linux内核2.6提供核心系统服务,例如,安全性管理,内存管理,进程管理,网络协议栈和驱动模型等。它扮演的是系统硬件和系统其他软件层次的抽象层的角色。需要注意的是,这个和标准的linux系统是有所不同的,在系统库,系统初始化和编程接口方面。

 

首先看Libraries,他的主要作用是为android的系统开发提供了丰富的库类支持,例如数据库,2D3D图形库,基于Linux底层系统的c库,媒体库等等。

再来看android运行时,这里面主要有两个部分,一个android核心库集,提供可Java语言核心库所能使用的绝大部分功能,一个Dalvik虚拟机,负责运行android程序。DalvikGoogle公司自己设计用于Android平台的Java虚拟机。不要和JVM混淆,JVM运行的是Java字节码(.class),Dalvic运行的是.dex,这个是专有的。Dalvik经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Dalvik应用作为一个独立的Linux 进程执行。这个就可以保证android系统下低资源消耗和没有应用相互干扰的多应用程序并行运行。

这部分为android开发提供了丰富的API,这个为android的应用程序开发提供了工具。

这一部分就是应用程序,用android手机的里面都有这些,不管是程序自带的还是后来装上去的。

1.      Activity:应用活动
            Activity几乎承接着用户对应用程序(Application)的所有操作,Activity应该有一个窗口(Window),这个窗口是可以通过不同的主题(Theme)改变样子的。Activity应该要注意它的生命周期(Lifecycle)、设备状态(Configuration)等改变时对应用程序的影响以及运行状态和数据的保存,这个在一个应用程序是否可靠和人性化上至关重要。Activity里还应该要申明一些许可(Permissions),以便使用Android的一些软硬件功能,这些申明可以由代码或者androidmanifest.xml给出。最后,每个Activity(的入口)一定要在Manifest当中申明。


       2. Service:后台服务
            Service是没有界面的程序,它是所谓的服务,也叫后台程序。应该要非常注意Service的启动(startService)和绑定(bindService)这两种开启Service的方法之间的关系以及Service对应的生命周期,两种开户Service的方法对Service的生命周期效果是不同的。还有就是申明许可以及申明Service,也是在代码内或者Manifest内申明。
        3. BroadcastReceiver:广播接收
             广播接收并不是通常所说的无线电广播,而是指由sendBroadcast()所发送出来的意图(Intent),即广播在这里的意思是意图,BroadcastReceiver在注册(Registe)之后可以自动监听符合预先给定的条件的意图,如果有则会通知此BroadcastReceiver的持有程序。
       4. ContentProvider:数据支持(外部数据)
            ContentProvider是作保存应用程序数据和建立维持数据库之用,以便程序重新启动时回到以前的状态或者保存信息。应该注意应用程序的使用权限以及SQL语言的使用,Android用的是一个轻量级的数据库系统SQLite
       5. Intent:意图(活动桥)
             IntentAndroid应用开发里很重要的一个元件,很多书上以直译来解释,不太好理解,我觉得可以译为活动桥,也就是连接两个活动(Activity)的桥梁(Bridge)。通过Intent可以从一个Activity来启动另一个任意的Activity,不管是自己定义的还是系统定义的。在ActivityGroupextends Activity)里面,Intentflag设置对于子Activity的启动方式至关重要。

另外我还想将一下ViewView一般都是在activity里面调用的,它是用户实实在在看到的部分,他就是所有UI控件和容器控件的基类。需要在Activity里面显示View的话,调用ActivitysetContentView()方法即可。

 

Android的成功的过程可以用8个字来概括,寻找,突破,信任,流行!关于信任,谷歌联合世界各大移动运营商,如中国三巨头,德国T-Mobile,意大利电信等等,半导体公司,手机和其他终端制造商,软件供应商,商业公司。

三:

增强现实技术大家都熟悉这里就不在多讲了,基于android的增强现实的开发主要用到的apicamerasensoropenGL ESGPS等,还有一些其他的不是androidAPI里面的,这里就不说了。

下面我通过几个简单的例子来分别介绍这几个API的用法。

Camera

需要注意的是在AndroidManifest.xml中申明一些权限和属性。

    <!-- 授予程序使用摄像头的权限 --> 

<uses-permissionandroid:name="android.permission.CAMERA"/>

<uses-feature     android:name="android.hardware.camera"/>

<uses-feature android:name="android.hardware.camera.autofocus"/>

The Camera class is used to set image capture settings, start/stoppreview, snap pictures, and retrieve frames for encoding for video. This classis a client for the Camera service, which manages the actual camera hardware.

1、 调用cameraopen()方法打开相机

2、 调用getParameters()获取拍照参数

3、   设置需要的parameters,再调用setParameters(Camera.Parameters),这个在2.3.3之后的版本中就不需要了。

4、   如果有需要的话,调用setDisplayOrientation(int)设置屏幕显示方向

5、   这个很重要,获取SurfaceView的SurfaceHolder接口,setPreviewDisplay(SurfaceHolder)如果没有这个,相机就不能开始预览。

6、 调用startPreview()开始预览。

7、 当程序结束是,要调用stopPreview()方法关闭预览,而且要调用release()来释放资源,否则其他程序要用到camera的时候就不会顺利。

 

  1. Obtain an instance of Camera fromopen(int).    
  2. Get existing (default) settings withgetParameters().
  3. If necessary, modify the returnedCamera.Parameters object and callsetParameters(Camera.Parameters).
  4. If desired, callsetDisplayOrientation(int).
  5. Important: Pass a fully initializedSurfaceHolder tosetPreviewDisplay(SurfaceHolder). Without a surface, the camera will be unable to start the preview.
  6. Important: CallstartPreview() to start updating the preview surface. Preview must be started     before you can take a picture.
  7. When you want, calltakePicture(Camera.ShutterCallback,     Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback) to capture a photo. Wait for the callbacks to provide the actual     image data.
  8. After taking a picture, preview display will have stopped. To take more photos, callstartPreview() again first.
  9. Call stopPreview() to stop updating the preview surface.
  10. Important: Callrelease() to release the camera for use by other applications. Applications should release the camera immediately inonPause() (and re-open() it inonResume()).

Sensor的应用

在Android2.3 gingerbread系统中,google提供了11种传感器供应用层使用。
#define SENSOR_TYPE_ACCELEROMETER //加速度

#defineSENSOR_TYPE_MAGNETIC_FIELD //磁力

#defineTYPE_RELATIVE_HUMIDITY3 //相对湿度

#defineSENSOR_TYPE_GYROSCOPE 4 //陀螺仪

#defineSENSOR_TYPE_LIGHT 5 //光线感应

#defineSENSOR_TYPE_PRESSURE 6 //压力

#defineSENSOR_TYPE_AMBIENT _TEMPERATURE 7 //环境温度

#defineSENSOR_TYPE_PROXIMITY 8 //接近

#defineSENSOR_TYPE_GRAVITY 9 //重力

#defineSENSOR_TYPE_LINEAR_ACCELERATION 10//线性加速度

#defineSENSOR_TYPE_ROTATION_VECTOR 11//旋转矢量

 

这些传感器为手机的应用提供很多的空间,方便了人们的生活。下面介绍一些常用的。

1 加速度传感器

加速度传感器又叫G-sensor,返回x、y、z三轴的加速度数值。

该数值包含地心引力的影响,单位是m/s^2。

将手机平放在桌面上,x轴默认为0,y轴默认0,z轴默认9.81。

将手机朝下放在桌面上,z轴为-9.81。

将手机向左倾斜,x轴为正值。

将手机向右倾斜,x轴为负值。

将手机向上倾斜,y轴为负值。

将手机向下倾斜,y轴为正值。

 

加速度传感器可能是最为成熟的一种mems产品,市场上的加速度传感器种类很多。

手机中常用的加速度传感器有BOSCH(博世)的BMA系列,AMK的897X系列,ST的LIS3X系列等。

这些传感器一般提供±2G至±16G的加速度测量范围,采用I2C或SPI接口和MCU相连,数据精度小于16bit。

 

2 磁力传感器

磁力传感器简称为M-sensor,返回x、y、z三轴的环境磁场数据。

该数值的单位是微特斯拉(micro-Tesla),用uT表示。

单位也可以是高斯(Gauss),1Tesla=10000Gauss。

硬件上一般没有独立的磁力传感器,磁力数据由电子罗盘传感器提供(E-compass)。

电子罗盘传感器同时提供下文的方向传感器数据。

 

3 方向传感器

方向传感器简称为O-sensor,返回三轴的角度数据,方向数据的单位是角度。

为了得到精确的角度数据,E-compass需要获取G-sensor的数据,

经过计算生产O-sensor数据,否则只能获取水平方向的角度。

方向传感器提供三个数据,分别为azimuth、pitch和roll。

azimuth:方位,返回水平时磁北极和Y轴的夹角,范围为0°至360°。

0°=北,90°=东,180°=南,270°=西。

pitch:x轴和水平面的夹角,范围为-180°至180°。

当z轴向y轴转动时,角度为正值。

roll:y轴和水平面的夹角,由于历史原因,范围为-90°至90°。

当x轴向z轴移动时,角度为正值。

 

电子罗盘在获取正确的数据前需要进行校准,通常可用8字校准法。

8字校准法要求用户使用需要校准的设备在空中做8字晃动,

原则上尽量多的让设备法线方向指向空间的所有8个象限。

 

手机中使用的电子罗盘芯片有AKM公司的897X系列,ST公司的LSM系列以及雅马哈公司等等。

由于需要读取G-sensor数据并计算出M-sensor和O-sensor数据,

因此厂商一般会提供一个后台daemon来完成工作,电子罗盘算法一般是公司私有产权。

 

4 陀螺仪传感器

陀螺仪传感器叫做Gyro-sensor,返回x、y、z三轴的角加速度数据。

角加速度的单位是radians/second。

根据Nexus S手机实测:

水平逆时针旋转,Z轴为正。

水平逆时针旋转,z轴为负。

向左旋转,y轴为负。

向右旋转,y轴为正。

向上旋转,x轴为负。

向下旋转,x轴为正。

 

ST的L3G系列的陀螺仪传感器比较流行,iphone4和google的nexuss中使用该种传感器。

 

5 光线感应传感器

光线感应传感器检测实时的光线强度,光强单位是lux,其物理意义是照射到单位面积上的光通量。

光线感应传感器主要用于Android系统的LCD自动亮度功能。

可以根据采样到的光强数值实时调整LCD的亮度。

 

6 压力传感器

压力传感器返回当前的压强,单位是百帕斯卡hectopascal(hPa)。

 

7 温度传感器

温度传感器返回当前的温度。

 

8 接近传感器

接近传感器检测物体与手机的距离,单位是厘米。

一些接近传感器只能返回远和近两个状态,

因此,接近传感器将最大距离返回远状态,小于最大距离返回近状态。

接近传感器可用于接听电话时自动关闭LCD屏幕以节省电量。

一些芯片集成了接近传感器和光线传感器两者功能。

 

 

下面三个传感器是Android2新提出的传感器类型,目前还不太清楚有哪些应用程序使用。

9 重力传感器

重力传感器简称GV-sensor,输出重力数据。

在地球上,重力数值为9.8,单位是m/s^2。

坐标系统与加速度传感器相同。

当设备复位时,重力传感器的输出与加速度传感器相同。

 

10 线性加速度传感器

线性加速度传感器简称LA-sensor。

线性加速度传感器是加速度传感器减去重力影响获取的数据。

单位是m/s^2,坐标系统与加速度传感器相同。

加速度传感器、重力传感器和线性加速度传感器的计算公式如下:

加速度 = 重力 + 线性加速度

 

11 旋转矢量传感器

旋转矢量传感器简称RV-sensor。

旋转矢量代表设备的方向,是一个将坐标轴和角度混合计算得到的数据。

RV-sensor输出三个数据:

x*sin(theta/2)

y*sin(theta/2)

z*sin(theta/2)

sin(theta/2)是RV的数量级。

RV的方向与轴旋转的方向相同。

RV的三个数值,与cos(theta/2)组成一个四元组。

RV的数据没有单位,使用的坐标系与加速度相同。

举例:

sensors_event_t.data[0] = x*sin(theta/2)

sensors_event_t.data[1] = y*sin(theta/2)

sensors_event_t.data[2] = z*sin(theta/2)

sensors_event_t.data[3] =   cos(theta/2)

 

GV、LA和RV的数值没有物理传感器可以直接给出,

需要G-sensor、O-sensor和Gyro-sensor经过算法计算后得出。

算法一般是传感器公司的私有产权。

 

我的主要有重力 光感 陀螺 距離 加速度。

 

 

GPS的应用

一般都是应用在定位和导航系统,在AR中的话,也不外乎这两个应用,可能还会包括测量距离的用法。

 

OpenGL的英文全称是OpenGraphics Library,OpenGL ES是openGL的一个子集,OpenGLfor Embedded System。

目前android的SDK已经支持了OpenGLES2.0的大部分功能,而且还专门提供了android.opengl包,在该包下提供了一些如GLSurfaceView,GLU,GLUtils等工具类,可以通过这些类来方便地在android系统下进行相关的开发。

通过Projection和CameraView in OpenGL ES1.0来解决图形与手机屏幕多样性的适应问题

图形失真

解决办法:

1.  public voidonSurfaceChanged(GL10 gl, int width, int height) {

2.        gl.glViewport(0, 0, width, height);

3.   

4.        // make adjustments for screen ratio

5.        float ratio = (float) width / height;

6.        gl.glMatrixMode(GL10.GL_PROJECTION);        // set matrix to projection mode

7.        gl.glLoadIdentity();                        // reset the matrix to itsdefault state

8.        gl.glFrustumf(-ratio, ratio, -1, 1, 3,7);  // apply the projection matrix

  }

camera view

1.  public voidonDrawFrame(GL10 gl) {

2.          ...

3.          // Set GL_MODELVIEW transformation mode

4.          gl.glMatrixMode(GL10.GL_MODELVIEW);

5.          gl.glLoadIdentity();                      // reset the matrix toits default state

6.   

7.          // When using GL_MODELVIEW, you mustset the camera view

8.          GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f,0f, 1.0f, 0.0f);

9.          ...

}

再介绍纹理贴图的一些知识。

下图是android平台下opengl纹理系统的坐标,左下角为0点。

这个坐标顺序很关键,不仅牵涉到贴图的时候会遇到纹理坐标数组,而且设计到opengl中正面和背面的区别,总之这个顺序很重要。如果弄错了给背面贴图的话,会什么都看不到的。

OPENGL中规定:如果多边形的顶点以逆时针顺序出现在屏幕上,则为正面。我们通过使用voidglFrontFace(GLenum mode) 函数可以交换图形的正反面。默认情况下,modeGL_CCW,即逆时针为正面;GL_CW顺时针为正面。为了丢弃一些被OPENGL认为是背面的多边形,应采用剔除。首先调用:glEnable(GL_CULL_FACE)启用剔除功能;然后调用glCullFace(GLenummode)mode参数为:GL_FRONT,GL_BACK,GL_FRONT_AND_BACK