最近在测试闹钟时,发现选择铃声时有重复选项,出现两个Cesium。追踪DeskClock至创建ringtone_picker的indent就没有具体的细节了,ringtone_picker是怎么生成的?在packages/app下调用的系统类,应该都去framework中查找。根据这一思路,grep -w Cesium framework/base,在framework/data下找到了我需要的东西。
音乐选择列表主要是由out\target\product\rk2928sdk\system\media\audio\alarms下的文件遍历生成,需要注意的地方:列表内容是根据音乐的Track title生成的。重名可能是因为文件名不相同,而track title相同。(Cesium.ogg和Alarm_Classic.ogg的Track title相同)
修改如下:
①根据frameworks\base\data\sounds\Allaudio.mk包括的mk,在这些mk中查找Alarm_Classic.ogg,将对应行删除掉。
②将out\target\product\rk2928sdk\system\media\audio\alarms\Alarm_Classic.ogg删除掉。
更多想法:
framework/data下有很多其它的目录,如:sounds,videos,fonts等。相关的mk文件主要起着复制到out目录中的作用,如果用户需要预先将某些音视频文件放在机器中,可以尝试放在此目录,并修改mk文件。
由于iOS6以上的UIKit不会在内存警告时自动释放视图,所以viewWillUnload和viewDidUnload将不再触发。
因此,在iOS6上,开发者需要负责内存警告时将不用到的视图释放。
WWDC2012的视频有提到,具体代码如下:
- (void)didReceiveMemoryWarning { if ([self.view window] == nil) { self.view = nil; self.otherSubView = nil; } }由于[self view]会引发视图的加载所以上述代码还是有潜在风险的,假如视图控制器在创建之后,在还没有加载视图时收到内存警告,那上面的代码就会触发视图的加载(调用了[self view]引起),反而加大了内存占用。所以应该先判断一下视图是否已被加载。
- (void)didReceiveMemoryWarning { if ([self isViewLoaded] && [self.view window] == nil) { self.view = nil; self.otherSubView = nil; } }Notification 的注册和反注册以及Delegate的设置和置空
如果注册的通知跟界面相关,可以考虑将注册放入viewWillAppear并在viewWillDisappear中反注册。
如果需要在视图加载时就注册,那就在viewDidLoad注册,dealloc和didReceiveMemoryWarning中根据视图是否加载过来进行反注册。
注意viewDidUnload和viewDidLoad不是成对调用的,所以即使是iOS5或者以下的版本也不能在viewDidUnload里面反注册。参见[iOS] ViewController的生命周期及其加载View的步骤。
综上所述,最佳实践的代码如下:
- (void)viewDidLoad { self.subView.delegate = self; [[NSNotificationCenter defaultCenter] addObserver:self]; self.viewCreatedByCode = [[UIView alloc] init]; } // 自定义函数viewUnloaded,其操作与viewDidLoad对称。 - (void)viewUnloaded { self.subView.delegate = nil; [[NSNotificationCenter defaultCenter] removeObserver:self]; self.viewCreatedByCode = nil; } - (void)didReceiveMemoryWarning { if ([self isViewLoaded] && [self.view window] == nil) { self.view = nil; // 需要开发者手动释放控制器的视图。 self.viewCreatedByNib = nil; // 在xib中创建的视图也要手动清空。 [self viewUnloaded]; // 视图已被卸载,调用viewDIdLoad的反操作。 } } - (void)dealloc { if ([self isViewLoaded]) { [self viewUnloaded]; // 如果视图已被加载,说明viewDidLoad被调用过,所以调用viewDIdLoad的反操作。 } }
openGL 灯光与材质例子. 顺带完成了一个颇复杂的平面分级算法, 修正版,列出了所有易错的地方:
1. 开启了 GL_XXX_ARRAY 后一定要使用对应的pointer, 否则就把 GL_XXX_ARRAY disable 掉.
2. 法线不一定要设置, openGL会自动为每一Vertex生成一个默认的, 自己设置当然可控性更好.
3. initLights() 等GL具体到场景内容的设置必须放在 GLUT 基本设置之后(一开始就死在这个弱智的问题).
4. 灯光的 GL_POSITION, 齐次坐标最后一位如果是 0, 则为平行光, 无需设置 GL_SPOT_DIRECTION 和 GL_SPOT_CUTOFF(这个值为照射角的一半). 如果是1, 则为聚光灯.
5. GL 环境光对所有面都会有影响.尝试变换灯光的颜色和环境光颜色的数组值,观察其变化.
6. 材质的 SHINESS 参数, 1 端接近橡胶与织物, 128 端接近金属与清漆.
7. 灯灯灯凳~ 最麻烦的还是平面分级算法, 理论上分级越细, 关照效果越细致, 代码如下:
#include <gl/GLUT.h> #include <stdio.h> static GLfloat LEVEL=12; static GLfloat LENGTH=2; static GLfloat START_PT=-1*(LENGTH/2); static GLfloat END_PT=1*(LENGTH/2); GLfloat angle=0; GLfloat *vertices; //GLfloat *colors; short *indices; GLfloat *normals; //GLfloat vertices[]={-1,-1,1, // -0.3333f,-1,1, // 0.3333f,-1,1, // 1,-1,1, // -1,-0.3333,1, // -0.3333f,-0.3333,1, // 0.3333f,-0.3333,1, // 1,-0.3333,1, // -1,0.3333,1, // -0.3333f,0.3333,1, // 0.3333f,0.3333,1, // 1,0.3333,1, // -1,1,1, // -0.3333f,1,1, // 0.3333f,1,1, // 1,1,1}; //short indices[]={0,1,4, 1,5,4, 1,2,5, 2,6,5, 2,3,6, 3,7,6, // 4,5,8, 5,9,8, 5,6,9, 6,10,9, 6,7,10, 7,11,10, // 8,9,12, 9,13,12, 9,10,13, 10,14,13, 10,11,14, 11,15,14}; //lights GLfloat lightPos[]={0,0,2.5f,1}; GLfloat lightColor[]={0.6f,0.3f,0.3f,1}; //red GLfloat lightDir[]={0,0,-1}; //ambient light GLfloat light_ambient[]={0.3f,0.3f,0.4f,1}; //light blue //materials GLfloat cubeColor[]={0.6f,0.6f,0.6f,1}; //gray color GLfloat cubeSpecular[]={1,1,1,1}; void setMaterial(){ glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,cubeColor); glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,cubeSpecular); //try to change the shiness from 1(rubber/frabic)-128(metal/clear painted) glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,20); } void drawPlane(){ glVertexPointer(3,GL_FLOAT,0,vertices); //glNormalPointer(GL_FLOAT,0,normals); //glColorPointer(4,GL_FLOAT,0,colors); glDrawElements(GL_TRIANGLES,(GLsizei)((LEVEL-1)*(LEVEL-1)*2*3),GL_UNSIGNED_SHORT,indices); } void drawCube(){ //set material setMaterial(); glPushMatrix(); drawPlane(); glPopMatrix(); glPushMatrix(); glRotatef(-90,1,0,0); drawPlane(); glPopMatrix(); glPushMatrix(); glRotatef(90,1,0,0); drawPlane(); glPopMatrix(); glPushMatrix(); glRotatef(180,1,0,0); drawPlane(); glPopMatrix(); glPushMatrix(); glRotatef(90,0,1,0); drawPlane(); glPopMatrix(); glPushMatrix(); glRotatef(-90,0,1,0); drawPlane(); glPopMatrix(); } void rendering(void){ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(angle,0,1,0); drawCube(); glPopMatrix(); glutSwapBuffers(); angle+=0.01; } void reshape(int w, int h){ if(h==0){ h=1; } GLfloat ratio=(GLfloat)(w/h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0,0,w,h); gluPerspective(45,ratio,0.1,1000); gluLookAt(0,5,10,0,0,0,0,1,0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void makeArrays(){ //build vertices array for one face GLfloat step=(GLfloat)(LENGTH/(LEVEL-1)); GLint total=LEVEL*LEVEL*3; GLint oneLine=LEVEL*3; //12 //printf("level: %f ", step); vertices=new GLfloat[total]; for(int i=0;i<LEVEL;i++){ //every point x,y,z for(int j=0;j<LEVEL*3;j+=3){ vertices[(i*oneLine)+j]=(GLfloat)(START_PT+(j*step/3)); vertices[(i*oneLine)+(j+1)]=(GLfloat)(START_PT+i*step); vertices[(i*oneLine)+(j+2)]=(GLfloat)(LENGTH/2); printf("pt : x: %f, y: %f, z: %f \n", vertices[(i*oneLine)+j], vertices[(i*oneLine)+j+1], vertices[(i*oneLine)+j+2]); } } //build colors array, normal white color; /*GLint totalColor=LEVEL*LEVEL*4; colors=new GLfloat[totalColor]; for(int r=0;r<totalColor;r+=4){ colors[r]=1; colors[r+1]=1; colors[r+2]=1; colors[r+3]=1; }*/ //build index array for one face //using TRIANGLES indices=new short[(LEVEL-1)*(LEVEL-1)*2*3]; //square of LEVEL-1, 2 triangles, 3 points; for(int m=0;m<LEVEL-1;m++){ for(int n=0;n<LEVEL-1;n++){ indices[m*((GLint)LEVEL-1)*6+n*6+0]=n+m*((GLint)LEVEL-1)+m+0; indices[m*((GLint)LEVEL-1)*6+n*6+1]=n+m*((GLint)LEVEL-1)+m+1; indices[m*((GLint)LEVEL-1)*6+n*6+2]=n+m*((GLint)LEVEL-1)+m+(LEVEL); indices[m*((GLint)LEVEL-1)*6+n*6+3]=n+m*((GLint)LEVEL-1)+m+1; indices[m*((GLint)LEVEL-1)*6+n*6+4]=n+m*((GLint)LEVEL-1)+m+(LEVEL)+1; indices[m*((GLint)LEVEL-1)*6+n*6+5]=n+m*((GLint)LEVEL-1)+m+(LEVEL); } } normals=new GLfloat[LEVEL*LEVEL*3]; for(int s=0;s<LEVEL*LEVEL*3;s+=3){ normals[s]=0; normals[s+1]=0; normals[s+2]=1; } } void initLights(){ glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); glLightfv(GL_LIGHT0,GL_AMBIENT,lightColor); glLightfv(GL_LIGHT0,GL_DIFFUSE,lightColor); glLightfv(GL_LIGHT0,GL_SPECULAR,lightColor); glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightDir); glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,45); // glLightModelfv(GL_LIGHT_MODEL_AMBIENT,light_ambient); } int main(int argc, char* args[]){ //make arrays makeArrays(); //basic init glutInit(&argc,args); glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); //window init glutInitWindowPosition(100,100); glutInitWindowSize(600,600); glutCreateWindow("light cube"); //functions init glutDisplayFunc(rendering); glutIdleFunc(rendering); glutReshapeFunc(reshape); //gl init glEnable(GL_DEPTH_TEST); glEnableClientState(GL_VERTEX_ARRAY); //glEnableClientState(GL_NORMAL_ARRAY); //glEnableClientState(GL_COLOR_ARRAY); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); //init lights initLights(); //run main loop, trigger all the funtions glutMainLoop(); return 0; }