android中Opengl的权限配置是什么呢 android中Opengl的权限配置是什么呢''
Android OpenGL详解一2012-05-15 ? ? ?0 个评论 ? ? ?收藏 ? ?我要投稿概述 Android通过OpenGL包含了对高性能2D和3D图形的支持.尤其支持OpenGLES API.OpenGL是一个跨平台的图形API,提供了软件操作3D图形硬件的接口.OpenGLES是一个专用于嵌入式设备的OpenGL规格.从android1.0开始支持OpenGLES 1.0和1.1API规格.从Android2.2 (API Level 8)开始,框架支持OpenGLES 2.0 API规格. 注:Android框架所提供的API与J2MEJSR239 OpenGL ES API非常相似,但并不是完全相同.如果你熟悉J2MEJSR239规格,请注意不同的地方.基础知识
Android的框架API和NDK都支持OpenGL.本主题面向Android框架接口.关于NDK的更多信息,请观NDK开发文档.
在Android框架中有两个基本的类使你可以通过OpenGLES API创建和操作图形系统:GLSurfaceView和GLSurfaceView.Renderer.如果你的目标是在你的Android应用中使用OpenGL,了解如何在一个activity中实现这些类是首要目标.GLSurfaceView 这个类是一个View,你可以用OpenGLAPI调用来绘制对象并管理它们.它与SurfaceView很相似.你可以创建一个GLSurfaceView的实例然后把你的绘制操作添加给它.然而,如果你想捕获触屏事件,你应扩展GLSurfaceView类来实现触屏事件监听器,就像在SDK的OpenGL例子ES1.0, ES 2.0和TouchRotateActivity中所示.GLSurfaceView.Renderer 此接口定义了在一个OpenGL GLSurfaceView上作画所需的方法们.你必须提供另一个类来实现这个接口然后把它附加到你的GLSurfaceView实例上,使用GLSurfaceView.setRenderer().GLSurfaceView.Renderer接口需要你实现以下方法们:onSurfaceCreated():当创建GLSurfaceView时被调用,只调用一次.在这个方法中执行只发生一次的动作,比如设置OpenGL环境参数或初始化OpenGL图形对象.onDrawFrame():系统在每次重绘GLSurfaceView时调用此方法.此方法是绘制图形对象的主要的执行点.onSurfaceChanged():当GLSurfaceView几何体改变时系统调用此方法,比如GLSurfaceView的大小改变或设备屏幕的方向改变.使用此方法来响应GLSurfaceView容器的变化.OpenGL包
一旦你使用GLSurfaceView和GLSurfaceView.Renderer为OpenGL建立起一个容器,你就可以开始用以下类来调用OpenGLAPIs:OpenGLES 1.0/1.1 API 包android.opengl- 这个包为OpenGLES 1.0/1.1 类提供了一个静态接口并且其性能好于javax.microedition.khronos包中的接口.GLES10GLES10ExtGLES11GLES10Extjavax.microedition.khronos.opengles- 这个包提供了OpenGLES 1.0/1.1 的标准实现.GL10GL10ExtGL11GL11ExtGL11ExtensionPackOpenGLES 2.0 API 类android.opengl.GLES20- 这个包提供了OpenGLES 2.0 的接口并且从Android2.2 (API Level 8)开始才能用. 如果你想正确创建支持OpenGL的应用,请看OpenGL ES 1.0或OpenGLES 2.0的指南.声明OpenGL的需求
如果你的应用使用的OpenGL特性不能被所有的设备支持,你必须在AndroidManifest.xml文件中包含你的OpenGL的需求.下面是最常见的OpenGLmanifest声明:OpenGLES 版本需求-如果你的应用只支持OpenGLES 2.0,你必须把以下设置添加到manifest中以声明这个需求:[html] ?
添加这个声明使得Android市场阻止你的应用被安装到不支持OpenGLES 2.0的设备上.纹理压缩需求-如果你的应用使用了纹理压缩格式,你必须在你的manifest文件中用来声明所用格式. 在你的manifest中声明纹理压缩格式需求使得使用不支持其中任何一种压缩格式的设备的用户看不到你的应用.为绘制对象映射坐标系
在Android设备中显示图形的一个基本问题是它们的屏幕的尺寸和形状可能不同.OpenGL假设一个正方形的,一致的坐标系统,并且,默认情况下,也乐于把这些坐标画到你的非正方形屏幕上,就像在正方形上一样. 图 1.默认OpenGL坐标系统(left)映射到典型的Android设备屏幕(right).
上面的插图,左图演示了一个OpenGL帧的一致的坐标系,以及如何映射到像右图这样的横向屏幕上.要解决这个问题,你可以设置OpenGL投影模式和相机视进行坐标变换使得你的图形对象在任何地方都具有正确的比例. 为了应用投影和视口,你要创建一个投影矩阵和一个视口矩阵然后把它们应用到OpenGL呈现管线中.投影矩阵重新计算你的图形的坐标于是它们可以正确地映射到Android设备屏幕上.视口矩追创建一个变换以从指定的眼睛位置呈现对象.OpenGLES 1.0中的投影和视口 www.2cto.com
在ES1.0 API中,你通过创建每个矩追并把它们添加到OpenGL环境中来应用投影和视口.投影矩阵-使用设备屏幕的几何体创建一个投影矩阵是为了重新计算对象坐标以使它们能按照正确的比例画出.下面的示例代码演示了如何实现GLSurfaceView.Renderer的onSurfaceChanged()方法来基于屏幕的纵横比创建一个投影矩阵然后把它应用到OpenGL呈现环境中.[java] public void onSurfaceChanged(GL10 gl, int width, int height) {
? ?gl.glViewport(0, 0, width, height);
? ?// make adjustments for screen ratio ?
? ?float ratio = (float) width / height;
? ?gl.glMatrixMode(GL10.GL_PROJECTION); ? ? ? ?// set matrix to projection mode ?
? ?gl.glLoadIdentity(); ? ? ? ? ? ? ? ? ? ? ? ?// reset the matrix to its default state ?
? ?gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7); ?// apply the projection matrix ?
}
?public void onSurfaceChanged(GL10 gl, int width, int height) {
? ? ?gl.glViewport(0, 0, width, height); ? ? ?// make adjustments for screen ratio
? ? ?float ratio = (float) width / height;
? ? ?gl.glMatrixMode(GL10.GL_PROJECTION); ? ? ? ?// set matrix to projection mode
? ? ?gl.glLoadIdentity(); ? ? ? ? ? ? ? ? ? ? ? ?// reset the matrix to its default state
? ? ?gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7); ?// apply the projection matrix
?}
视口变换矩阵-一旦你使用投影矩阵调整了坐标系统,你必须同时应用一个视口矩阵.下面的示例代码演示了如何实现GLSurfaceView.Renderer的onDrawFrame()方法来应用视图模型并且使用GLU.gluLookAt()来指定眼睛位置创建一个视口变换.[java] public void onDrawFrame(GL10 gl) {
? ?...
? ?// Set GL_MODELVIEW transformation mode ?
? ?gl.glMatrixMode(GL10.GL_MODELVIEW);
? ?gl.glLoadIdentity(); ? ? ? ? ? ? ? ? ? ? ?// reset the matrix to its default state ?
? ?// When using GL_MODELVIEW, you must set the camera view ?
? ?GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
? ?...
}
? ?public void onDrawFrame(GL10 gl) {
? ? ? ?...
? ? ? ?// Set GL_MODELVIEW transformation mode
? ? ? ?gl.glMatrixMode(GL10.GL_MODELVIEW);
? ? ? ?gl.glLoadIdentity(); ? ? ? ? ? ? ? ? ? ? ?// reset the matrix to its default state ? ? ? ?// When using GL_MODELVIEW, you must set the camera view
? ? ? ?GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
? ? ? ?...
? ?}OpenGLES 2.0中的投影和视口
在ES2.0API中,你首先要添加一个矩阵到顶点着色器才能应用投影和视口变换.通过添加这种矩阵成员,你就可以为你的对象产生并应用投影和视口变换.1添加矩阵到顶点着色器-为投影矩阵创建一个变量并把它作为着色器位置的乘积来包含.在下面的顶点着色器示例代码中,所包含的uMVPMatrix成员允许你应用投影和视口矩阵到使用这个着色器的对象的坐标上.[java] private final String vertexShaderCode =
? ?// 这个矩阵成员变量提供了一个勾子来操控 ?
? ?// 使用这个顶点着色器的对象的坐标 ?
? ?"uniform mat4 uMVPMatrix; ? \n" +
? ?"attribute vec4 vPosition; ?\n" +
? ?"void main(){ ? ? ? ? ? ? ? \n" +
? ?// the matrix must be included as part of gl_Position ?
? ?" gl_Position = uMVPMatrix * vPosition; \n" +
? ?"} ?\n";
? ?private final String vertexShaderCode = ? ? ? ?// 这个矩阵成员变量提供了一个勾子来操控
? ? ? ?// 使用这个顶点着色器的对象的坐标
? ? ? ?"uniform mat4 uMVPMatrix; ? \n" + ? ? ? ?"attribute vec4 vPosition; ?\n" +
? ? ? ?"void main(){ ? ? ? ? ? ? ? \n" + ? ? ? ?// the matrix must be included as part of gl_Position
? ? ? ?" gl_Position = uMVPMatrix * vPosition; \n" + ? ? ? ?"} ?\n";
注:上面的例子在顶点着色器中定义了一个单独的变换矩阵成员,在着色器中你应用了组合的投影矩阵和视口矩阵.跟据你的应用的需求,你可能想在你的顶点着色器中分别定义投影矩阵和视口矩阵成员,这样可以单独地改变它们.2操作顶点着色器-在你的顶点着色器中创建一个钩子来应用投影和视口后,你就可以操作这些变量来应用投影和视口矩阵.下面的代码演示了如何修改GLSurfaceView.Renderer的onSurfaceCreated()方法的实现来操作上面的定义在顶点着色器中的矩阵变量.[java] public void onSurfaceCreated(GL10 unused, EGLConfig config) {
? ?...
? ?muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
? ?...
}
? ?public void onSurfaceCreated(GL10 unused, EGLConfig config) {
? ? ? ?...
? ? ? ?muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
? ? ? ?...
? ?}3创建投影和视口矩阵 -生成要应用到图形对象的投影和视口矩阵.下面的示例代码演示了如何修改GLSurfaceView.Renderer的onSurfaceCreated()和 onSurfaceChanged()方法的实现来基于设备的屏幕的宽高比创建视口矩阵和投影矩阵.[java] public void onSurfaceCreated(GL10 unused, EGLConfig config) {
? ?...
? ?// 创建一个视口矩阵 ?
? ?Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
? ?GLES20.glViewport(0, 0, width, height);
? ?float ratio = (float) width / height;
? ?// 跟据设备屏幕的几何特征创建投影矩阵 ?
? ?Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
? ?public void onSurfaceCreated(GL10 unused, EGLConfig config) {
? ? ? ?...
? ? ? ?// 创建一个视口矩阵
? ? ? ?Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
? ?} ? ?public void onSurfaceChanged(GL10 unused, int width, int height) {
? ? ? ?GLES20.glViewport(0, 0, width, height); ? ? ? ?float ratio = (float) width / height; ? ? ? ?// 跟据设备屏幕的几何特征创建投影矩阵
? ? ? ?Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
? ?}
4应用投影和视口矩阵 -要应用投影和视口矩阵,需将矩阵们相乘然后把它们设置给顶点着色器.下面的示例代码演示了如何GLSurfaceView.Renderer的方法onDrawFrame()的实现来把上面代码所创建的投影和视口矩阵合并然后应应到图形对象上.[java] public void onDrawFrame(GL10 unused) {
? ?...
? ?// 合并投影和视口矩阵 ?
? ?Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
? ?// 应用合并后的投影和视口变换 ?
? ?GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
? ?// 绘制对象们 ?
? ?...
}
? ?public void onDrawFrame(GL10 unused) {
? ? ? ?...
? ? ? ?// 合并投影和视口矩阵
? ? ? ?Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0); ? ? ? ?// 应用合并后的投影和视口变换
? ? ? ?GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); ? ? ? ?// 绘制对象们
? ? ? ?...
? ?}
一)linux文件系统上的权限-rwxr-x--x system?? system?????? 4156 2012-06-30 16:12 test.apk.代表的是相应的用户/用户组及其他人对此文件的访问权限,与此文件运行起来具有的权限完全不相关比如上面的例子只能说明system用户拥有对此文件的读写执行权限;system组的用户对此文件拥有读、执行权限;其他人对此文件只具有执行权限。而test.apk运行起来后可以干哪些事情,跟这个就不相关了。千万不要看apk文件系统上属于system/system用户及用户组,或者root/root用户及用户组,就认为apk具有system或root权限。apk程序是运行在虚拟机上的,对应的是Android独特的权限机制,只有体现到文件系统上时才使用linux的权限设置。(二)Android的权限规则(1)Android中的apk必须签名这种签名不是基于权威证书的,不会决定某个应用允不允许安装,而是一种自签名证书。重要的是,android系统有的权限是基于签名的。比如:system等级的权限有专门对应的签名,签名不对,权限也就获取不到。默认生成的APK文件是debug签名的。获取system权限时用到的签名见后面描述(2)基于UserID的进程级别的安全机制进程有独立的地址空间,进程与进程间默认是不能互相访问的,Android通过为每一个apk分配唯一的linux userID来实现,名称为“app_“加一个数字,比如app_43不同的UserID,运行在不同的进程,所以apk之间默认便不能相互访问。Android提供了如下的一种机制,可以使两个apk打破前面讲的这种壁垒。在AndroidManifest.xml中利用sharedUserId属性给不同的package分配相同的userID,通过这样做,两个package可以被当做同一个程序,系统会分配给两个程序相同的UserID。当然,基于安全考虑,两个apk需要相同的签名,否则没有验证也就没有意义了。(3)默认apk生成的数据对外是不可见的实现方法是:Android会为程序存储的数据分配该程序的UserID。借助于Linux严格的文件系统访问权限,便实现了apk之间不能相互访问似有数据的机制。例:我的应用创建的一个文件,默认权限如下,可以看到只有UserID为app_21的程序才能读写该文件。-rw------- app_21?? app_21????? 87650 2000-01-01 09:48 test.txt如何对外开放?<1>?使用MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE标记。When creating a new file with getSharedPreferences(String, int), openFileOutput(String, int), or openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory), you can use the MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE flags to allow any other package to read/write the file. When setting these flags, the file is still owned by your application, but its global read and/or write permissions have been set appropriately so any other application can see it.(4)AndroidManifest.xml中的显式权限声明Android默认应用是没有任何权限去操作其他应用或系统相关特性的,应用在进行某些操作时都需要显式地去申请相应的权限。一般以下动作时都需要申请相应的权限:A particular permission may be enforced at a number of places during your program‘s operation:At the time of a call into the system, to prevent an application from executing certain functions.When starting an activity, to prevent applications from launching activities of other applications.Both sending and receiving broadcasts, to control who can receive your broadcast or who can send a broadcast to you.When accessing and operating on a content provider.Binding or starting a service.在应用安装的时候,package installer会检测该应用请求的权限,根据该应用的签名或者提示用户来分配相应的权限。在程序运行期间是不检测权限的。如果安装时权限获取失败,那执行就会出错,不会提示用户权限不够。大多数情况下,权限不足导致的失败会引发一个?SecurityException,会在系统log(system log)中有相关记录。(5)权限继承/UserID继承当我们遇到apk权限不足时,我们有时会考虑写一个linux程序,然后由apk调用它去完成某个它没有权限完成的事情,很遗憾,这种方法是行不通的。前面讲过,android权限是在进程层面的,也就是说一个apk应用启动的子进程的权限不可能超越其父进程的权限(即apk的权限),即使单独运行某个应用有权限做某事,但如果它是由一个apk调用的,那权限就会被限制。实际上,android是通过给子进程分配父进程的UserID实现这一机制的。