NativeActivity.java revision 54a181b1a2b1517a9479b21fbf7705a688232faf
1package android.app; 2 3import dalvik.system.PathClassLoader; 4 5import android.content.pm.ActivityInfo; 6import android.content.pm.ApplicationInfo; 7import android.content.pm.PackageManager; 8import android.graphics.PixelFormat; 9import android.os.Bundle; 10import android.os.Looper; 11import android.os.MessageQueue; 12import android.view.InputChannel; 13import android.view.InputQueue; 14import android.view.KeyEvent; 15import android.view.Surface; 16import android.view.SurfaceHolder; 17import android.view.View; 18 19import java.io.File; 20 21/** 22 * Convenience for implementing an activity that will be implemented 23 * purely in native code. That is, a game (or game-like thing). 24 */ 25public class NativeActivity extends Activity implements SurfaceHolder.Callback, 26 InputQueue.Callback { 27 public static final String META_DATA_LIB_NAME = "android.app.lib_name"; 28 29 private int mNativeHandle; 30 31 private InputQueue mCurInputQueue; 32 private SurfaceHolder mCurSurfaceHolder; 33 34 private boolean mDestroyed; 35 36 private native int loadNativeCode(String path, MessageQueue queue); 37 private native void unloadNativeCode(int handle); 38 39 private native void onStartNative(int handle); 40 private native void onResumeNative(int handle); 41 private native void onSaveInstanceStateNative(int handle); 42 private native void onPauseNative(int handle); 43 private native void onStopNative(int handle); 44 private native void onLowMemoryNative(int handle); 45 private native void onWindowFocusChangedNative(int handle, boolean focused); 46 private native void onSurfaceCreatedNative(int handle, Surface surface); 47 private native void onSurfaceChangedNative(int handle, Surface surface, 48 int format, int width, int height); 49 private native void onSurfaceDestroyedNative(int handle); 50 private native void onInputChannelCreatedNative(int handle, InputChannel channel); 51 private native void onInputChannelDestroyedNative(int handle, InputChannel channel); 52 53 @Override 54 protected void onCreate(Bundle savedInstanceState) { 55 String libname = "main"; 56 ActivityInfo ai; 57 58 getWindow().takeSurface(this); 59 getWindow().takeInputQueue(this); 60 getWindow().setFormat(PixelFormat.RGB_565); 61 62 try { 63 ai = getPackageManager().getActivityInfo( 64 getIntent().getComponent(), PackageManager.GET_META_DATA); 65 if (ai.metaData != null) { 66 String ln = ai.metaData.getString(META_DATA_LIB_NAME); 67 if (ln != null) libname = ln; 68 } 69 } catch (PackageManager.NameNotFoundException e) { 70 throw new RuntimeException("Error getting activity info", e); 71 } 72 73 String path = null; 74 75 if ((ai.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) == 0) { 76 // If the application does not have (Java) code, then no ClassLoader 77 // has been set up for it. We will need to do our own search for 78 // the native code. 79 path = ai.applicationInfo.dataDir + "/lib/" + System.mapLibraryName(libname); 80 if (!(new File(path)).exists()) { 81 path = null; 82 } 83 } 84 85 if (path == null) { 86 path = ((PathClassLoader)getClassLoader()).findLibrary(libname); 87 } 88 89 if (path == null) { 90 throw new IllegalArgumentException("Unable to find native library: " + libname); 91 } 92 93 mNativeHandle = loadNativeCode(path, Looper.myQueue()); 94 if (mNativeHandle == 0) { 95 throw new IllegalArgumentException("Unable to load native library: " + path); 96 } 97 super.onCreate(savedInstanceState); 98 } 99 100 @Override 101 protected void onDestroy() { 102 mDestroyed = true; 103 if (mCurSurfaceHolder != null) { 104 onSurfaceDestroyedNative(mNativeHandle); 105 mCurSurfaceHolder = null; 106 } 107 if (mCurInputQueue != null) { 108 onInputChannelDestroyedNative(mNativeHandle, mCurInputQueue.getInputChannel()); 109 mCurInputQueue = null; 110 } 111 unloadNativeCode(mNativeHandle); 112 super.onDestroy(); 113 } 114 115 @Override 116 protected void onPause() { 117 super.onPause(); 118 onPauseNative(mNativeHandle); 119 } 120 121 @Override 122 protected void onResume() { 123 super.onResume(); 124 onResumeNative(mNativeHandle); 125 } 126 127 @Override 128 protected void onSaveInstanceState(Bundle outState) { 129 super.onSaveInstanceState(outState); 130 onSaveInstanceStateNative(mNativeHandle); 131 } 132 133 @Override 134 protected void onStart() { 135 super.onStart(); 136 onStartNative(mNativeHandle); 137 } 138 139 @Override 140 protected void onStop() { 141 super.onStop(); 142 onStopNative(mNativeHandle); 143 } 144 145 @Override 146 public void onLowMemory() { 147 super.onLowMemory(); 148 if (!mDestroyed) { 149 onLowMemoryNative(mNativeHandle); 150 } 151 } 152 153 @Override 154 public void onWindowFocusChanged(boolean hasFocus) { 155 super.onWindowFocusChanged(hasFocus); 156 if (!mDestroyed) { 157 onWindowFocusChangedNative(mNativeHandle, hasFocus); 158 } 159 } 160 161 public void surfaceCreated(SurfaceHolder holder) { 162 if (!mDestroyed) { 163 mCurSurfaceHolder = holder; 164 onSurfaceCreatedNative(mNativeHandle, holder.getSurface()); 165 } 166 } 167 168 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 169 if (!mDestroyed) { 170 mCurSurfaceHolder = holder; 171 onSurfaceChangedNative(mNativeHandle, holder.getSurface(), format, width, height); 172 } 173 } 174 175 public void surfaceDestroyed(SurfaceHolder holder) { 176 mCurSurfaceHolder = null; 177 if (!mDestroyed) { 178 onSurfaceDestroyedNative(mNativeHandle); 179 } 180 } 181 182 public void onInputQueueCreated(InputQueue queue) { 183 if (!mDestroyed) { 184 mCurInputQueue = queue; 185 onInputChannelCreatedNative(mNativeHandle, queue.getInputChannel()); 186 } 187 } 188 189 public void onInputQueueDestroyed(InputQueue queue) { 190 mCurInputQueue = null; 191 if (!mDestroyed) { 192 onInputChannelDestroyedNative(mNativeHandle, queue.getInputChannel()); 193 } 194 } 195 196 void dispatchUnhandledKeyEvent(KeyEvent event) { 197 View decor = getWindow().getDecorView(); 198 if (decor != null) { 199 decor.dispatchKeyEvent(event); 200 } 201 } 202 203 void setWindowFlags(int flags, int mask) { 204 getWindow().setFlags(flags, mask); 205 } 206 207 void setWindowFormat(int format) { 208 getWindow().setFormat(format); 209 } 210} 211