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