diff --git a/contrib/mobile/Android/res/layout/control_bar.xml b/contrib/mobile/Android/res/layout/control_bar.xml
new file mode 100644
index 0000000000000000000000000000000000000000..89bc5c543d55b4409f06ee9adb75cf918fa34c37
--- /dev/null
+++ b/contrib/mobile/Android/res/layout/control_bar.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal"
+    android:background="@android:color/black"
+    android:alpha=".50"
+    android:gravity="center" >
+
+    <ImageButton
+        android:id="@+id/controlPrev"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@android:drawable/ic_media_previous"
+        android:contentDescription="previous" />
+
+    <ImageButton
+        android:id="@+id/controlPlay"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@android:drawable/ic_media_play"
+        android:contentDescription="play" />
+
+    <ImageButton
+        android:id="@+id/controlNext"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@android:drawable/ic_media_next"
+        android:contentDescription="next" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/contrib/mobile/Android/src/org/geuz/onelab/Gmsh.java b/contrib/mobile/Android/src/org/geuz/onelab/Gmsh.java
index 9800649e93bc761756464fac07561511be1b70e4..00d4d8e66d6150ef1fb11a6380110279a0c9cf63 100644
--- a/contrib/mobile/Android/src/org/geuz/onelab/Gmsh.java
+++ b/contrib/mobile/Android/src/org/geuz/onelab/Gmsh.java
@@ -13,7 +13,6 @@ public class Gmsh implements Parcelable {
 		System.loadLibrary("Gmsh");
 		System.loadLibrary("GetDP");
 		System.loadLibrary("Onelab");
-        
     }
 	private native long init(String name); // Init Gmsh
 	private native void loadFile(long ptr, String name); // load a file(OpenProjet)
@@ -33,6 +32,7 @@ public class Gmsh implements Parcelable {
 	public native int onelabCB(String action); // Call onelab
 	
 	public native void animationNext();
+	public native void animationPrev();
 	
 	/** Java CLASS **/
 	private long ptr;
diff --git a/contrib/mobile/Android/src/org/geuz/onelab/MainActivity.java b/contrib/mobile/Android/src/org/geuz/onelab/MainActivity.java
index 89b384b594ff53d220acf617c2bf5f699a73651f..c49fe250625cb22821e44fb34b2fe34b7ee4b7fb 100644
--- a/contrib/mobile/Android/src/org/geuz/onelab/MainActivity.java
+++ b/contrib/mobile/Android/src/org/geuz/onelab/MainActivity.java
@@ -4,8 +4,6 @@ import java.io.File;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.Timer;
-import java.util.TimerTask;
 
 import android.app.ActionBar;
 import android.app.Activity;
@@ -40,7 +38,6 @@ public class MainActivity extends Activity{
 	private OptionsFragment _optionsFragment;
 	private ArrayList<String> _errors = new ArrayList<String>();
 	private Dialog _errorDialog;
-	private Timer _animation;
 
 	public MainActivity() {
 	}
@@ -87,6 +84,7 @@ public class MainActivity extends Activity{
 	
 	@Override
 	protected void onSaveInstanceState(Bundle outState) {
+		outState.putBoolean("Compute", _compute);
 		super.onSaveInstanceState(outState);
 	}
 	
@@ -101,11 +99,14 @@ public class MainActivity extends Activity{
     	_runStopMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
     	MenuItem shareMenuItem = menu.add(R.string.menu_share);
     	shareMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
-    	MenuItem playPauseMenuItem = menu.add("Play animation");
-    	playPauseMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
         return true;
     }
 	@Override
+	public boolean onMenuOpened(int featureId, Menu menu) {
+		_modelFragment.postDelay();
+		return super.onMenuOpened(featureId, menu);
+	}
+	@Override
     public boolean onMenuItemSelected(int featureId, MenuItem item) {
     	if (item.getTitle().equals(getString(R.string.menu_parameters))) {
     		Intent intent = new Intent(this, OptionsActivity.class);
@@ -115,6 +116,7 @@ public class MainActivity extends Activity{
 			_modelFragment.requestRender();
     	}
     	else if(item.getTitle().equals(getString(R.string.menu_run))){
+    		if(_modelFragment != null) _modelFragment.hideControlBar();
     		new Run().execute();
     	}
     	else if(item.getTitle().equals(getString(R.string.menu_stop))){
@@ -144,33 +146,6 @@ public class MainActivity extends Activity{
     			shareIntent.setType("image/jpeg");
     			startActivity(Intent.createChooser(shareIntent, getString(R.string.title_share)));
     		}
-    	}
-    	else if(item.getTitle().equals("Play animation")) {
-    		if(this._compute) {
-				AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
-    			_errorDialog = dialogBuilder.setTitle("Can't start animation")
-    			.setMessage("The computing have to be finished before you can play animation.")
-    			.setPositiveButton("OK", new DialogInterface.OnClickListener() {
-					
-					public void onClick(DialogInterface dialog, int which) {
-						dialog.dismiss();
-					}
-				})
-    			.show();
-    		}
-    		else {
-	    		item.setTitle("Stop animation");
-	    		_animation = new Timer();
-	    		_animation.schedule(new TimerTask() {
-	    			public void run()  {
-	    				_gmsh.animationNext();
-	    				_modelFragment.requestRender();
-	    			} }, 2000, 1);
-    		}
-    	}
-    	else if(item.getTitle().equals("Stop animation")) {
-    		item.setTitle("Play animation");
-    		_animation.cancel();
     	}
 		else if(item.getItemId() == android.R.id.home) {
 			if(this._compute) {
@@ -275,6 +250,7 @@ public class MainActivity extends Activity{
 	
 	@Override
 	public void onLowMemory() {
+		if(!_compute) return;
 		_gmsh.onelabCB("stop");
 		Toast.makeText(this, "Low memory !!! computing is going to stop", Toast.LENGTH_LONG).show();
 		super.onLowMemory();
@@ -282,9 +258,14 @@ public class MainActivity extends Activity{
 	
 	@Override
 	public void onTrimMemory(int level) {
+		if(!_compute) return;
 		if(level == Activity.TRIM_MEMORY_COMPLETE){
 			_gmsh.onelabCB("stop");
 			notifyInterruptComputing();
+			_notify = false;
+		}
+		else if(level == Activity.TRIM_MEMORY_COMPLETE) {
+			// TODO
 		}
 		super.onTrimMemory(level);
 	}
diff --git a/contrib/mobile/Android/src/org/geuz/onelab/ModelFragment.java b/contrib/mobile/Android/src/org/geuz/onelab/ModelFragment.java
index 77fe46fc31a7618febfc511555c5f3efb485b1f6..826ea9dbad6fd0accb43c0a8b37590247ca5a19d 100644
--- a/contrib/mobile/Android/src/org/geuz/onelab/ModelFragment.java
+++ b/contrib/mobile/Android/src/org/geuz/onelab/ModelFragment.java
@@ -3,15 +3,24 @@ package org.geuz.onelab;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
+import java.util.Timer;
+import java.util.TimerTask;
 
 import android.app.Fragment;
 import android.graphics.Bitmap;
 import android.opengl.GLSurfaceView;
 import android.os.Bundle;
+import android.os.Handler;
+import android.view.GestureDetector;
+import android.view.GestureDetector.OnGestureListener;
 import android.view.Gravity;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.ImageButton;
 import android.widget.LinearLayout;
 import android.widget.ProgressBar;
 import android.widget.RelativeLayout;
@@ -19,10 +28,16 @@ import android.widget.TextView;
 
 public class ModelFragment extends Fragment{
 
-	Gmsh _gmsh;
-	mGLSurfaceView _glView;
-	TextView _progress;
-	LinearLayout _progressLayout;
+	private Gmsh _gmsh;
+	private mGLSurfaceView _glView;
+	private TextView _progress;
+	private LinearLayout _progressLayout;
+	private LinearLayout _controlBarLayout;
+	private GestureDetector _gestureListener;
+	private Timer _animation;
+	private Handler _hideDelay;
+	
+	final Runnable hideControlsRunnable = new Runnable() {public void run() {hideControlBar();}};
 	
 	public static ModelFragment newInstance(Gmsh g) {
 		ModelFragment fragment = new ModelFragment();
@@ -52,6 +67,50 @@ public class ModelFragment extends Fragment{
 		_glView.setRenderer(renderer);
 		_glView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
 		_glView.requestRender();
+		_hideDelay = new Handler();
+		this.postDelay();
+		_gestureListener = new GestureDetector(getActivity(), new OnGestureListener() {
+			public boolean onSingleTapUp(MotionEvent e) {
+				if(View.VISIBLE == _controlBarLayout.getVisibility())
+					hideControlBar();
+				else
+					showControlBar();
+				return true;
+			}
+			
+			public void onShowPress(MotionEvent e) {
+				// TODO Auto-generated method stub
+				
+			}
+			
+			public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
+					float distanceY) {
+				// TODO Auto-generated method stub
+				return false;
+			}
+			
+			public void onLongPress(MotionEvent e) {
+				// TODO Auto-generated method stub
+				
+			}
+			
+			public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
+					float velocityY) {
+				// TODO Auto-generated method stub
+				return false;
+			}
+			
+			public boolean onDown(MotionEvent e) {
+				// TODO Auto-generated method stub
+				return false;
+			}
+		});
+		_glView.setOnTouchListener(new View.OnTouchListener() {
+			
+			public boolean onTouch(View v, MotionEvent event) {
+				return _gestureListener.onTouchEvent(event);
+			}
+		});
 		glViewLayout.addView(_glView);
 		_progressLayout = new LinearLayout(container.getContext());
 		ProgressBar bar = new ProgressBar(container.getContext());
@@ -70,8 +129,74 @@ public class ModelFragment extends Fragment{
 			    RelativeLayout.LayoutParams.WRAP_CONTENT);
 		layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
 		glViewLayout.addView(_progressLayout, layoutParams);
+		_controlBarLayout = (LinearLayout) getActivity().getLayoutInflater().inflate(R.layout.control_bar, null);
+		ImageButton playPauseButton = (ImageButton)_controlBarLayout.findViewById(R.id.controlPlay);
+		playPauseButton.setOnClickListener(new View.OnClickListener() {
+			public void onClick(View v) {
+				postDelay();
+				if(((ImageButton)v).getContentDescription().equals("play")) {
+					((ImageButton)v).setContentDescription("pause");
+					((ImageButton)v).setImageResource(android.R.drawable.ic_media_pause);
+		    		_animation = new Timer();
+		    		_animation.schedule(new TimerTask() {
+		    			public void run()  {
+		    				_gmsh.animationNext();
+		    				requestRender();
+		    			} }, 0, 500);
+				}
+				else {
+					((ImageButton)v).setContentDescription("play");
+					((ImageButton)v).setImageResource(android.R.drawable.ic_media_play);
+					_animation.cancel();
+				}
+			}
+		});
+		ImageButton nextButton = (ImageButton)_controlBarLayout.findViewById(R.id.controlNext);
+		nextButton.setOnClickListener(new View.OnClickListener() {
+			public void onClick(View v) {
+				postDelay();
+		    	_gmsh.animationNext();
+		    	requestRender();
+			}
+		});
+		ImageButton prevButton = (ImageButton)_controlBarLayout.findViewById(R.id.controlPrev);
+		prevButton.setOnClickListener(new View.OnClickListener() {
+			public void onClick(View v) {
+				postDelay();
+		    	_gmsh.animationPrev();
+		    	requestRender();
+			}
+		});
+		layoutParams = new RelativeLayout.LayoutParams(
+			    RelativeLayout.LayoutParams.MATCH_PARENT, 
+			    RelativeLayout.LayoutParams.WRAP_CONTENT);
+		layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+		glViewLayout.addView(_controlBarLayout, layoutParams);
 		return rootView;
 	}
+	public void postDelay(int delay) {
+		_hideDelay.removeCallbacks(hideControlsRunnable);
+		_hideDelay.postDelayed(hideControlsRunnable, delay);
+	}
+	public void postDelay() {
+		this.postDelay(6000);
+	}
+	public void showControlBar() {
+		if(getActivity() == null) return;
+		this.postDelay();
+		getActivity().getActionBar().show();
+		Animation bottomUp = AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in);
+		_controlBarLayout.setVisibility(View.VISIBLE);
+		_controlBarLayout.startAnimation(bottomUp);
+	}
+	public void hideControlBar() {
+		if(getActivity() == null) return;
+		_hideDelay.removeCallbacks(hideControlsRunnable);
+		getActivity().getActionBar().hide();
+		Animation bottomDown = AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out);
+		_controlBarLayout.startAnimation(bottomDown);
+		_controlBarLayout.setVisibility(View.INVISIBLE);
+	}
 	public void showProgress(String progress) {
 		_progressLayout.setAlpha(1);
 		_progress.setText(progress);
diff --git a/contrib/mobile/androidGModel.cpp b/contrib/mobile/androidGModel.cpp
index 2d8e3de46ab013644473d8e98e0ff71d689b623d..606626e84096eda1bb1b3bee54b9e5213b76efba 100644
--- a/contrib/mobile/androidGModel.cpp
+++ b/contrib/mobile/androidGModel.cpp
@@ -309,4 +309,9 @@ JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_animationNext
 {
 	animation_next();
 }
+JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_animationPrev
+  (JNIEnv *, jobject)
+{
+	animation_prev();
+}
 }
diff --git a/contrib/mobile/androidGModel.h b/contrib/mobile/androidGModel.h
index 7497acd9288d7b370f251d7ba85ca61f571acf8f..043816e97112d3ba65f6faf89cff61ac3df3108a 100644
--- a/contrib/mobile/androidGModel.h
+++ b/contrib/mobile/androidGModel.h
@@ -145,6 +145,14 @@ JNIEXPORT jint JNICALL Java_org_geuz_onelab_Gmsh_onelabCB
 JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_animationNext
   (JNIEnv *, jobject);
 
+/*
+ * Class:     org_geuz_onelab_Gmsh
+ * Method:    animationPrev
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_animationPrev
+  (JNIEnv *, jobject);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/contrib/mobile/drawContext.cpp b/contrib/mobile/drawContext.cpp
index a9e361165079da1ec4e1454ae4bce320c097c878..58eea35343783a6debbcf09732cb05f1c97e903c 100644
--- a/contrib/mobile/drawContext.cpp
+++ b/contrib/mobile/drawContext.cpp
@@ -693,7 +693,24 @@ void animation_next() {
 				if(step < 0) step = numSteps - 1;
 				if(step > numSteps - 1) step = 0;
 			}
-			Msg::Info("animation: step%d nextstep%d totalstep%d", p->getOptions()->timeStep, step, p->getData()->getNumTimeSteps());
+			p->getOptions()->timeStep = step;
+			p->setChanged(true);
+		}
+	}
+}
+void animation_prev() {
+	for(unsigned int i = 0; i < PView::list.size(); i++){
+		PView * p = PView::list[i];
+		if(p->getOptions()->visible){
+			// skip empty steps
+			int step = (int)p->getOptions()->timeStep - 1;
+			int numSteps = (int)p->getData()->getNumTimeSteps();
+			for(int j = 0; j < numSteps; j++){
+				if(p->getData()->hasTimeStep(step)) break;
+				else step -= 1;
+				if(step < 0) step = numSteps - 1;
+				if(step > numSteps - 1) step = 0;
+			}
 			p->getOptions()->timeStep = step;
 			p->setChanged(true);
 		}
diff --git a/contrib/mobile/drawContext.h b/contrib/mobile/drawContext.h
index befc96db43d4b67a365db7bf48d4bd8b59d5bcd8..e69035fb0a942a188334e752f726a6cea44c67fe 100644
--- a/contrib/mobile/drawContext.h
+++ b/contrib/mobile/drawContext.h
@@ -22,6 +22,7 @@
 void drawArray(VertexArray *va, int type, bool useColorArray=false, bool useNormalArray=false);
 int onelab_cb(std::string);
 void animation_next();
+void animation_prev();
 
 class drawContext{
 private: