1 // This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount
2 package org.warmux;
3 
4 import android.app.Activity;
5 import android.content.Context;
6 import android.os.Bundle;
7 import android.view.MotionEvent;
8 import android.view.KeyEvent;
9 import android.view.Window;
10 import android.view.WindowManager;
11 import android.view.View;
12 import android.view.ViewGroup;
13 import android.widget.TextView;
14 import android.widget.EditText;
15 import android.text.Editable;
16 import android.widget.Button;
17 import android.widget.ImageView;
18 import android.widget.LinearLayout;
19 import android.widget.FrameLayout;
20 import android.content.res.Configuration;
21 import android.app.Notification;
22 import android.app.NotificationManager;
23 import android.app.PendingIntent;
24 import android.content.Intent;
25 import android.view.View.OnKeyListener;
26 import android.text.method.TextKeyListener;
27 import java.util.LinkedList;
28 import java.io.SequenceInputStream;
29 import java.io.BufferedInputStream;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.OutputStream;
33 import java.io.FileOutputStream;
34 import java.io.File;
35 import java.util.zip.ZipEntry;
36 import java.util.zip.ZipInputStream;
37 import android.text.SpannedString;
38 
39 
40 public class MainActivity extends Activity {
41 	@Override
onCreate(Bundle savedInstanceState)42 	protected void onCreate(Bundle savedInstanceState) {
43 		super.onCreate(savedInstanceState);
44 
45 		// fullscreen mode
46 		requestWindowFeature(Window.FEATURE_NO_TITLE);
47 		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
48 				WindowManager.LayoutParams.FLAG_FULLSCREEN);
49 		if(Globals.InhibitSuspend)
50 			getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
51 					WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
52 
53 		System.out.println("libSDL: Creating startup screen");
54 		_layout = new LinearLayout(this);
55 		_layout.setOrientation(LinearLayout.VERTICAL);
56 		_layout.setLayoutParams(new LinearLayout.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
57 		_layout2 = new LinearLayout(this);
58 		_layout2.setLayoutParams(new LinearLayout.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
59 
60 		_btn = new Button(this);
61 		_btn.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
62 		_btn.setText(getResources().getString(R.string.device_change_cfg));
63 		class onClickListener implements View.OnClickListener
64 		{
65 				public MainActivity p;
66 				onClickListener( MainActivity _p ) { p = _p; }
67 				public void onClick(View v)
68 				{
69 					setUpStatusLabel();
70 					System.out.println("libSDL: User clicked change phone config button");
71 					Settings.showConfig(p);
72 				}
73 		};
74 		_btn.setOnClickListener(new onClickListener(this));
75 
76 		_layout2.addView(_btn);
77 
78 		_layout.addView(_layout2);
79 
80 		ImageView img = new ImageView(this);
81 
82 		img.setScaleType(ImageView.ScaleType.FIT_CENTER /* FIT_XY */ );
83 		img.setImageResource(R.drawable.publisherlogo);
84 		img.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
85 		_layout.addView(img);
86 
87 		_videoLayout = new FrameLayout(this);
88 		_videoLayout.addView(_layout);
89 
90 		setContentView(_videoLayout);
91 
92 		if(mAudioThread == null) // Starting from background (should not happen)
93 		{
94 			System.out.println("libSDL: Loading libraries");
95 			LoadLibraries();
96 			mAudioThread = new AudioThread(this);
97 			System.out.println("libSDL: Loading settings");
98 			Settings.Load(this);
99 		}
100 
101 		if( !Settings.settingsChanged )
102 		{
103 			System.out.println("libSDL: 3-second timeout in startup screen");
104 			class Callback implements Runnable
105 			{
106 				MainActivity p;
107 				Callback( MainActivity _p ) { p = _p; }
108 				public void run()
109 				{
110 					try {
111 						Thread.sleep(3000);
112 					} catch( InterruptedException e ) {};
113 					if( Settings.settingsChanged )
114 						return;
115 					System.out.println("libSDL: Timeout reached in startup screen, process with downloader");
116 					p.startDownloader();
117 				}
118 			};
119 			Thread changeConfigAlertThread = null;
120 			changeConfigAlertThread = new Thread(new Callback(this));
121 			changeConfigAlertThread.start();
122 		}
123 	}
124 
setUpStatusLabel()125 	public void setUpStatusLabel()
126 	{
127 		MainActivity Parent = this; // Too lazy to rename
128 		if( Parent._btn != null )
129 		{
130 			Parent._layout2.removeView(Parent._btn);
131 			Parent._btn = null;
132 		}
133 		if( Parent._tv == null )
134 		{
135 			Parent._tv = new TextView(Parent);
136 			Parent._tv.setMaxLines(1);
137 			Parent._tv.setText(R.string.init);
138 			Parent._layout2.addView(Parent._tv);
139 		}
140 	}
141 
startDownloader()142 	public void startDownloader()
143 	{
144 		System.out.println("libSDL: Starting data downloader");
145 		class Callback implements Runnable
146 		{
147 			public MainActivity Parent;
148 			public void run()
149 			{
150 				setUpStatusLabel();
151 				System.out.println("libSDL: Starting downloader");
152 				if( Parent.downloader == null )
153 					Parent.downloader = new DataDownloader(Parent, Parent._tv);
154 			}
155 		}
156 		Callback cb = new Callback();
157 		cb.Parent = this;
158 		this.runOnUiThread(cb);
159 	}
160 
initSDL()161 	public void initSDL()
162 	{
163 		if(sdlInited)
164 			return;
165 		System.out.println("libSDL: Initializing video and SDL application");
166 		sdlInited = true;
167 		if(Globals.UseAccelerometerAsArrowKeys)
168 			getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
169 					WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
170 		_videoLayout.removeView(_layout);
171 		_layout = null;
172 		_layout2 = null;
173 		_btn = null;
174 		_tv = null;
175 		_videoLayout = new FrameLayout(this);
176 		setContentView(_videoLayout);
177 		mGLView = new DemoGLSurfaceView(this);
178 		_videoLayout.addView(mGLView);
179 		// Receive keyboard events
180 		mGLView.setFocusableInTouchMode(true);
181 		mGLView.setFocusable(true);
182 		mGLView.requestFocus();
183 	}
184 
185 	@Override
onPause()186 	protected void onPause() {
187 		if( downloader != null ) {
188 			synchronized( downloader ) {
189 				downloader.setStatusField(null);
190 			}
191 		}
192 		_isPaused = true;
193 		if( mGLView != null )
194 			mGLView.onPause();
195 		super.onPause();
196 	}
197 
198 	@Override
onResume()199 	protected void onResume() {
200 		super.onResume();
201 		if( mGLView != null )
202 			mGLView.onResume();
203 		else
204 		if( downloader != null ) {
205 			synchronized( downloader ) {
206 				downloader.setStatusField(_tv);
207 				if( downloader.DownloadComplete )
208 					initSDL();
209 			}
210 		}
211 		_isPaused = false;
212 	}
213 
isPaused()214 	public boolean isPaused()
215 	{
216 		return _isPaused;
217 	}
218 
219 	@Override
onDestroy()220 	protected void onDestroy()
221 	{
222 		if( downloader != null ) {
223 			synchronized( downloader ) {
224 				downloader.setStatusField(null);
225 			}
226 		}
227 		if( mGLView != null )
228 			mGLView.exitApp();
229 		super.onDestroy();
230 		System.exit(0);
231 	}
232 
hideScreenKeyboard()233 	public void hideScreenKeyboard()
234 	{
235 		if(_screenKeyboard == null)
236 			return;
237 
238 		synchronized(textInput)
239 		{
240 			String text = _screenKeyboard.getText().toString();
241 			for(int i = 0; i < text.length(); i++)
242 			{
243 				DemoRenderer.nativeTextInput( (int)text.charAt(i), (int)text.codePointAt(i) );
244 			}
245 		}
246 		DemoRenderer.nativeTextInputFinished();
247 		_videoLayout.removeView(_screenKeyboard);
248 		_screenKeyboard = null;
249 		mGLView.setFocusableInTouchMode(true);
250 		mGLView.setFocusable(true);
251 		mGLView.requestFocus();
252 	};
253 
showScreenKeyboard(final String oldText, boolean sendBackspace)254 	public void showScreenKeyboard(final String oldText, boolean sendBackspace)
255 	{
256 		if(_screenKeyboard != null)
257 			return;
258 		class myKeyListener implements OnKeyListener
259 		{
260 			MainActivity _parent;
261 			boolean sendBackspace;
262 			myKeyListener(MainActivity parent, boolean sendBackspace) { _parent = parent; this.sendBackspace = sendBackspace; };
263 			public boolean onKey(View v, int keyCode, KeyEvent event)
264 			{
265 				if ((event.getAction() == KeyEvent.ACTION_UP) && ((keyCode == KeyEvent.KEYCODE_ENTER) || (keyCode == KeyEvent.KEYCODE_BACK)))
266 				{
267 					_parent.hideScreenKeyboard();
268 					return true;
269 				}
270 				if ((sendBackspace && event.getAction() == KeyEvent.ACTION_UP) && (keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_CLEAR))
271 				{
272 					synchronized(textInput) {
273 						DemoRenderer.nativeTextInput( 8, 0 ); // Send backspace to native code
274 					}
275 					return false; // and proceed to delete text in keyboard input field
276 				}
277 				return false;
278 			}
279 		};
280 		_screenKeyboard = new EditText(this);
281 		_videoLayout.addView(_screenKeyboard);
282 		_screenKeyboard.setOnKeyListener(new myKeyListener(this, sendBackspace));
283 		_screenKeyboard.setHint(R.string.text_edit_click_here);
284 		_screenKeyboard.setText(oldText);
285 		final Window window = getWindow();
286 		_screenKeyboard.setOnFocusChangeListener(new View.OnFocusChangeListener() {
287 			public void onFocusChange(View v, boolean hasFocus)
288 			{
289 				if (hasFocus)
290 					window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
291 			}
292 		});
293 		_screenKeyboard.setKeyListener(new TextKeyListener(TextKeyListener.Capitalize.NONE, false));
294 		_screenKeyboard.setFocusableInTouchMode(true);
295 		_screenKeyboard.setFocusable(true);
296 		_screenKeyboard.requestFocus();
297 	};
298 
299 	@Override
onKeyDown(int keyCode, final KeyEvent event)300 	public boolean onKeyDown(int keyCode, final KeyEvent event) {
301 		// Overrides Back key to use in our app
302 		if(_screenKeyboard != null)
303 			_screenKeyboard.onKeyDown(keyCode, event);
304 		else
305 		if( mGLView != null )
306 			 mGLView.nativeKey( keyCode, 1 );
307 		else
308 		if( keyCode == KeyEvent.KEYCODE_BACK && downloader != null )
309 		{
310 			if( downloader.DownloadFailed )
311 				System.exit(1);
312 			if( !downloader.DownloadComplete )
313 			 onStop();
314 		}
315 		else
316 		if( keyListener != null )
317 		{
318 			keyListener.onKeyEvent(keyCode);
319 		}
320 		return true;
321 	}
322 
323 	@Override
onKeyUp(int keyCode, final KeyEvent event)324 	public boolean onKeyUp(int keyCode, final KeyEvent event) {
325 		if(_screenKeyboard != null)
326 			_screenKeyboard.onKeyUp(keyCode, event);
327 		else
328 		if( mGLView != null )
329 			mGLView.nativeKey( keyCode, 0 );
330 		return true;
331 	}
332 
333 	@Override
dispatchTouchEvent(final MotionEvent ev)334 	public boolean dispatchTouchEvent(final MotionEvent ev) {
335 		if(_screenKeyboard != null)
336 			_screenKeyboard.dispatchTouchEvent(ev);
337 		else
338 		if(mGLView != null)
339 			mGLView.onTouchEvent(ev);
340 		else
341 		if( _btn != null )
342 			return _btn.dispatchTouchEvent(ev);
343 		else
344 		if( touchListener != null )
345 			touchListener.onTouchEvent(ev);
346 		return true;
347 	}
348 
349 	@Override
onConfigurationChanged(Configuration newConfig)350 	public void onConfigurationChanged(Configuration newConfig) {
351 		super.onConfigurationChanged(newConfig);
352 		// Do nothing here
353 	}
354 
setText(final String t)355 	public void setText(final String t)
356 	{
357 		class Callback implements Runnable
358 		{
359 			MainActivity Parent;
360 			public SpannedString text;
361 			public void run()
362 			{
363 				Parent.setUpStatusLabel();
364 				if(Parent._tv != null)
365 					Parent._tv.setText(text);
366 			}
367 		}
368 		Callback cb = new Callback();
369 		cb.text = new SpannedString(t);
370 		cb.Parent = this;
371 		this.runOnUiThread(cb);
372 	}
373 
showTaskbarNotification()374 	public void showTaskbarNotification()
375 	{
376 		showTaskbarNotification("SDL application paused", "SDL application", "Application is paused, click to activate");
377 	}
378 
379 	// Stolen from SDL port by Mamaich
showTaskbarNotification(String text0, String text1, String text2)380 	public void showTaskbarNotification(String text0, String text1, String text2)
381 	{
382 		NotificationManager NotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
383 		Intent intent = new Intent(this, MainActivity.class);
384 		PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
385 		Notification n = new Notification(R.drawable.icon, text0, System.currentTimeMillis());
386 		n.setLatestEventInfo(this, text1, text2, pendingIntent);
387 		NotificationManager.notify(NOTIFY_ID, n);
388 	}
389 
hideTaskbarNotification()390 	public void hideTaskbarNotification()
391 	{
392 		NotificationManager NotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
393 		NotificationManager.cancel(NOTIFY_ID);
394 	}
395 
LoadLibraries()396 	public void LoadLibraries()
397 	{
398 		try
399 		{
400 			for(String l : Globals.AppLibraries)
401 			{
402         try
403         {
404           String libname = System.mapLibraryName(l);
405           File libpath = new File(getFilesDir().getAbsolutePath() + "/../lib/" + libname);
406           System.out.println("libSDL: loading lib " + libpath.getAbsolutePath());
407           System.load(libpath.getPath());
408         }
409         catch( UnsatisfiedLinkError e )
410         {
411           System.loadLibrary(l);
412         }
413 			}
414 		}
415 		catch ( UnsatisfiedLinkError e )
416 		{
417 			try {
418 				System.out.println("libSDL: Extracting APP2SD-ed libs");
419 
420 				InputStream in = null;
421 				try
422 				{
423 					for( int i = 0; ; i++ )
424 					{
425 						InputStream in2 = getAssets().open("bindata" + String.valueOf(i));
426 						if( in == null )
427 							in = in2;
428 						else
429 							in = new SequenceInputStream( in, in2 );
430 					}
431 				}
432 				catch( IOException ee ) { }
433 
434 				if( in == null )
435 					throw new RuntimeException("libSDL: Extracting APP2SD-ed libs failed, the .apk file packaged incorrectly");
436 
437 				ZipInputStream zip = new ZipInputStream(in);
438 
439 				File cacheDir = getCacheDir();
440 				try {
441 					cacheDir.mkdirs();
442 				} catch( SecurityException ee ) { };
443 
444 				byte[] buf = new byte[16384];
445 				while(true)
446 				{
447 					ZipEntry entry = null;
448 					entry = zip.getNextEntry();
449 					/*
450 					if( entry != null )
451 						System.out.println("Extracting lib " + entry.getName());
452 					*/
453 					if( entry == null )
454 					{
455 						System.out.println("Extracting libs finished");
456 						break;
457 					}
458 					if( entry.isDirectory() )
459 					{
460 						System.out.println("Warning '" + entry.getName() + "' is a directory");
461 						continue;
462 					}
463 
464 					OutputStream out = null;
465 					String path = cacheDir.getAbsolutePath() + "/" + entry.getName();
466 
467 					System.out.println("Saving to file '" + path + "'");
468 
469 					out = new FileOutputStream( path );
470 					int len = zip.read(buf);
471 					while (len >= 0)
472 					{
473 						if(len > 0)
474 							out.write(buf, 0, len);
475 						len = zip.read(buf);
476 					}
477 
478 					out.flush();
479 					out.close();
480 				}
481 
482 				for(String l : Globals.AppLibraries)
483 				{
484 					String libname = System.mapLibraryName(l);
485 					File libpath = new File(cacheDir, libname);
486 					System.out.println("libSDL: loading lib " + libpath.getPath());
487 					System.load(libpath.getPath());
488 					libpath.delete();
489 				}
490 			}
491 			catch ( Exception ee )
492 			{
493 				System.out.println("libSDL: Error: " + e.toString());
494 			}
495 		}
496 	};
497 
getVideoLayout()498 	public FrameLayout getVideoLayout() { return _videoLayout; }
499 
500 	static int NOTIFY_ID = 12367098; // Random ID
501 
502 	private static DemoGLSurfaceView mGLView = null;
503 	private static AudioThread mAudioThread = null;
504 	private static DataDownloader downloader = null;
505 
506 	private TextView _tv = null;
507 	private Button _btn = null;
508 	private LinearLayout _layout = null;
509 	private LinearLayout _layout2 = null;
510 
511 	private FrameLayout _videoLayout = null;
512 	private EditText _screenKeyboard = null;
513 	private boolean sdlInited = false;
514 	public Settings.TouchEventsListener touchListener = null;
515 	public Settings.KeyEventsListener keyListener = null;
516 	boolean _isPaused = false;
517 
518 	public LinkedList<Integer> textInput = new LinkedList<Integer> ();
519 
520 }
521