利用Android NDK以及OpenGLES开发动态壁纸


本文是一个Android动态壁纸的例子,利用android_ndk调用底层的C++代码,使用OpenGLES来绘制动态壁纸。仅作参考。

首先是定义我们自己的Renderer类,FireWallpaperRenderer实现了GLWallpaperService.Renderer接口(GLWallpaperService的代码在《Android利用OpenGLES开发动态壁纸用到的GLWallpaperService类》的那篇文章里):

 
  1. import java.io.IOException;  
  2. import java.io.InputStream;  
  3.   
  4. import javax.microedition.khronos.egl.EGLConfig;  
  5. import javax.microedition.khronos.opengles.GL10;  
  6. import android.content.Context;  
  7. import android.graphics.Bitmap;  
  8. import android.graphics.BitmapFactory;  
  9. import android.opengl.GLUtils;  
  10. import android.util.Log;  
  11.   
  12. public class FireWallpaperRenderer implements GLWallpaperService.Renderer {  
  13.     //用于纹理映射的绑定,并把绑定后的地址传递给C++代码,供其调用   
  14.     private int[] texture = new int[2];  
  15.     //用于加载Bitmap的context   
  16.     private Context mContext;  
  17.       
  18.     //FireWallpaperRenderer构造函数,用来初始化mContext   
  19.     public FireWallpaperRenderer(Context context){  
  20.         mContext = context;  
  21.     }  
  22.       
  23.     /** 
  24.      * 渲染场景的代码,这里我们是通过调用底层C++的代码来实现的, 
  25.      * 这样能得到更好地运行速度 
  26.      * */  
  27.     @Override  
  28.     public void onDrawFrame(GL10 gl) {  
  29.         //调用本地onDrawFrame方法   
  30.         FireNativeMethod.onDrawFrame(gl);  
  31.     }  
  32.       
  33.       
  34.     /** 
  35.      * 处理屏幕尺寸发生变化时的代码, 
  36.      * 用来重新设置场景的大小和其他一些属性, 
  37.      * 也是通过调用底层C++代码来实现 
  38.      * */  
  39.     @Override  
  40.     public void onSurfaceChanged(GL10 gl, int width, int height) {  
  41.         //调用本地onSurfaceChanged方法   
  42.         FireNativeMethod.onSurfaceChanged(gl, width, height);  
  43.     }  
  44.   
  45.     /** 
  46.      * 初始化OpenGL场景, 
  47.      * 用来设置场景的一些属性, 
  48.      * 也是通过调用底层C++代码来实现 
  49.      * */  
  50.     @Override  
  51.     public void onSurfaceCreated(GL10 gl, EGLConfig config) {  
  52.         //用来绑定Bitmap纹理   
  53.         bindTexture(gl, mContext);  
  54.         //调用本地setTexture方法,把纹理绑定的地址传递给C++代码,以供其调用   
  55.         FireNativeMethod.setTexture(texture);  
  56.         //调用本地onSurfaceCreated方法   
  57.         FireNativeMethod.onSurfaceCreated(gl, config);  
  58.   
  59.     }  
  60.       
  61.     /** 
  62.      * 用来绑定Bitmap纹理的代码, 
  63.      * 因为暂时没有找到在C++代码中绑定Bitmap纹理的方法, 
  64.      * 所以暂且在java层绑定Bitmap纹理 
  65.      * */  
  66.   
  67.     private void bindTexture(GL10 gl, Context context) {  
  68.         //生成纹理   
  69.         gl.glGenTextures(2, texture, 0);  
  70.         //加载Bitmap   
  71.         Bitmap bitmap = loadBitmap(context, R.drawable.floor);  
  72.         if (bitmap != null) {  
  73.             Log.i("firewallpaperrenderer""bind the floor texture");  
  74.             //如果bitmap加载成功,则生成此bitmap的纹理映射   
  75.             gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);  
  76.             //设置纹理映射的属性   
  77.             gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,  
  78.                     GL10.GL_NEAREST);  
  79.             gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,  
  80.                     GL10.GL_NEAREST);  
  81.             //生成纹理映射   
  82.             GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);  
  83.             //释放bitmap资源   
  84.             bitmap.recycle();  
  85.         }  
  86.         bitmap = loadBitmap(context, R.drawable.fire);  
  87.         if (bitmap != null) {  
  88.             //同上   
  89.             Log.i("firewallpaperrenderer""bind the fire texture");  
  90.             gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]);  
  91.             gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,  
  92.                     GL10.GL_NEAREST);  
  93.             gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,  
  94.                     GL10.GL_NEAREST);  
  95.             GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);  
  96.             bitmap.recycle();  
  97.         }  
  98.   
  99.     }  
  100.   
  101.     /** 
  102.      * 加载Bitmap的方法, 
  103.      * 用来从res中加载Bitmap资源 
  104.      * */  
  105.     private Bitmap loadBitmap(Context context, int resourceId) {  
  106.         InputStream is = context.getResources().openRawResource(resourceId);  
  107.         Bitmap bitmap = null;  
  108.         try {  
  109.   
  110.             // 利用BitmapFactory生成Bitmap   
  111.             bitmap = BitmapFactory.decodeStream(is);  
  112.         } finally {  
  113.             try {  
  114.   
  115.                 // 关闭流   
  116.                 is.close();  
  117.                 is = null;  
  118.             } catch (IOException e) {  
  119.                 e.printStackTrace();  
  120.             }  
  121.   
  122.         }  
  123.         return bitmap;  
  124.   
  125.     }  
  126.   
  127. }  

然后定义我们的WallpaperService,FireWallpaperService继承自GLWallpaperService:

 
  1. public class FireWallpaperService extends GLWallpaperService {  
  2.     //定义FireWallpaperRenderer实例   
  3.     private FireWallpaperRenderer mRenderer;  
  4.       
  5.       
  6.     public Engine onCreateEngine() {  
  7.         if (mRenderer == null) {  
  8.             mRenderer = new FireWallpaperRenderer(this);  
  9.         }  
  10.         return new FireWallpaperEngine();  
  11.     }  
  12.   
  13.     class FireWallpaperEngine extends GLWallpaperService.GLEngine {  
  14.   
  15.         public FireWallpaperEngine() {  
  16.             //设置Renderer和RendererMode   
  17.             setRenderer(mRenderer);  
  18.             setRenderMode(RENDERMODE_CONTINUOUSLY);  
  19.         }  
  20.   
  21.     }  
  22.   
  23. }  

完成后编辑Manifest.xml文件,如下:

 
  1. application android:icon="@drawable/icon" android:label="@string/app_name">  
  2.         <service android:name=".FireWallpaperService" android:label="@string/firewallpaper"  
  3.             android:permission="android.permission.BIND_WALLPAPER">  
  4.             <intent-filter>  
  5.                 <action android:name="android.service.wallpaper.WallpaperService" />  
  6.             </intent-filter>  
  7.             <meta-data android:name="android.service.wallpaper"  
  8.                 android:resource="@xml/wallpaper" />  
  9.         </service>  
  10.   
  11.     </application>  

Manifest.xml文件中,FireWallpaperService使用到的wallpaper文件

(<meta-dataandroid:name="android.service.wallpaper"android:resource="@xml/wallpaper" />)在res/xml目录下定义,内容如下:

 
  1. <span style="color:#000000;"><?xml version="1.0" encoding="utf-8"?>  
  2. <wallpaper xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:description="@string/description" android:thumbnail="@drawable/firelivewallpaper" /></span>  

然后是我们的本地方法类——FireNativeMethod:

 
  1. import javax.microedition.khronos.egl.EGLConfig;  
  2. import javax.microedition.khronos.opengles.GL10;  
  3.   
  4. public class FireNativeMethod {  
  5.     //加载本地库文件   
  6.     static{  
  7.         System.loadLibrary("fire_native_method");  
  8.     }  
  9.       
  10.     //渲染场景本地方法   
  11.     public static native void onDrawFrame(GL10 gl);  
  12.     //处理屏幕尺寸变化本地方法   
  13.     public static native void onSurfaceChanged(GL10 gl, int width, int height);  
  14.     //初始化OpenGL场景本地方法   
  15.     public static native void onSurfaceCreated(GL10 gl, EGLConfig config);  
  16.     //传递纹理映射地址本地方法   
  17.     public static native void setTexture(int [] textureString);  
  18.   
  19. }  

之后就是我们的本地C++代码部分了。

相关内容