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