diff --git a/build/android/Makefile b/build/android/Makefile
index d3d38f9ea33172c28740f7c60d8085bab56b2fb4..d4760ee21d70323616c1ac70faeb0f5a4e4f799c 100644
--- a/build/android/Makefile
+++ b/build/android/Makefile
@@ -629,6 +629,7 @@ assets : $(ASSETS_TIMESTAMP)
 	find . -name "timestamp" -exec rm {} \; ;                                  \
 	find . -name "*.blend" -exec rm {} \; ;                                    \
 	ls -R | grep ":$$" | sed -e 's/:$$//' -e 's/\.//' -e 's/^\///' > "index.txt"; \
+	find Minetest >"filelist.txt";                                             \
 	cp ${ROOT}/${ASSETS_TIMESTAMP} ${ROOT}/${ASSETS_TIMESTAMP}.old;            \
 	else                                                                       \
 		echo "nothing to be done for assets";                                  \
diff --git a/build/android/src/org/minetest/minetest/MinetestAssetCopy.java b/build/android/src/org/minetest/minetest/MinetestAssetCopy.java
index 652a00831341e25d669f385710870ea079a9b9a9..f6b2e80130478879f4aaf4ce4d8ec675a6e29da1 100644
--- a/build/android/src/org/minetest/minetest/MinetestAssetCopy.java
+++ b/build/android/src/org/minetest/minetest/MinetestAssetCopy.java
@@ -8,6 +8,7 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.util.Vector;
+import java.util.Iterator;
 
 import android.app.Activity;
 import android.content.res.AssetFileDescriptor;
@@ -20,10 +21,11 @@ import android.view.Display;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
-public class MinetestAssetCopy extends Activity {
-	
+public class MinetestAssetCopy extends Activity
+{
 	@Override
-	public void onCreate(Bundle savedInstanceState) {
+	public void onCreate(Bundle savedInstanceState)
+	{
 		super.onCreate(savedInstanceState);
 		
 		setContentView(R.layout.assetcopy);
@@ -35,8 +37,24 @@ public class MinetestAssetCopy extends Activity {
 		m_ProgressBar.getLayoutParams().width = (int) (display.getWidth() * 0.8);
 		m_ProgressBar.invalidate();
 		
-		m_AssetCopy = new copyAssetTask();
-		m_AssetCopy.execute();
+		/* check if there's already a copy in progress and reuse in case it is*/
+		MinetestAssetCopy prevActivity = 
+				(MinetestAssetCopy) getLastNonConfigurationInstance();
+		if(prevActivity!= null) {
+			m_AssetCopy = prevActivity.m_AssetCopy;
+		}
+		else {
+			m_AssetCopy = new copyAssetTask();
+			m_AssetCopy.execute();
+		}
+	}
+	
+	/* preserve asset copy background task to prevent restart of copying */
+	/* this way of doing it is not recommended for latest android version */
+	/* but the recommended way isn't available on android 2.x */
+	public Object onRetainNonConfigurationInstance()
+	{
+		return this;
 	}
 	
 	ProgressBar m_ProgressBar;
@@ -44,109 +62,53 @@ public class MinetestAssetCopy extends Activity {
 	
 	copyAssetTask m_AssetCopy;
 	
-	private class copyAssetTask extends AsyncTask<String, Integer, String>{
-		
-		private void copyElement(String name, String path) {
-			String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
-			String full_path;
-			if (path != "") {
-				full_path = path + "/" + name;
-			}
-			else {
-				full_path = name;
-			}
-			//is a folder read asset list
-			if (m_foldernames.contains(full_path)) {
-				m_Foldername = full_path;
-				publishProgress(0);
-				File current_folder = new File(baseDir + "/" + full_path);
-				if (!current_folder.exists()) {
-					if (!current_folder.mkdirs()) {
-						Log.w("MinetestAssetCopy","\t failed create folder: " + baseDir + "/" + full_path);
-					}
-					else {
-						Log.w("MinetestAssetCopy","\t created folder: " + baseDir + "/" + full_path);
-					}
-				}
-				try {
-					String[] current_assets = getAssets().list(full_path);
-					for(int i=0; i < current_assets.length; i++) {
-						copyElement(current_assets[i],full_path);
-					}
-				} catch (IOException e) {
-					Log.w("MinetestAssetCopy","\t failed to read contents of folder");
-					// TODO Auto-generated catch block
-					e.printStackTrace();
-				}
-			}
-			//is a file just copy
-			else {
-				boolean refresh = true;
-				
-				File testme = new File(baseDir + "/" + full_path);
-				
-				long asset_filesize = -1;
-				long stored_filesize = -1;
-				
-				if (testme.exists()) {
-					try {
-						AssetFileDescriptor fd = getAssets().openFd(full_path);
-						asset_filesize = fd.getLength();
-						fd.close();
-					} catch (IOException e) {
-						refresh = true;
-						m_asset_size_unknown.add(full_path);
-					}
-					
-					stored_filesize = testme.length();
-					
-					if (asset_filesize == stored_filesize) {
-						refresh = false;
-					}
-					
-				}
-				
-				if (refresh) {
-					m_tocopy.add(full_path);
-				}
-			}
-		}
-		
-		private long getFullSize(String filename) {
+	private class copyAssetTask extends AsyncTask<String, Integer, String>
+	{
+		private long getFullSize(String filename)
+		{
 			long size = 0;
 			try {
-			InputStream src = getAssets().open(filename);
-			byte[] buf = new byte[1024];
-			
-			int len = 0;
-			while ((len = src.read(buf)) > 0) {
-				size += len;
-			}
+				InputStream src = getAssets().open(filename);
+				byte[] buf = new byte[4096];
+				
+				int len = 0;
+				while ((len = src.read(buf)) > 0)
+				{
+					size += len;
+				}
 			}
-			catch (IOException e) {
+			catch (IOException e)
+			{
 				e.printStackTrace();
 			}
 			return size;
 		}
 
 		@Override
-		protected String doInBackground(String... files) {
-			
+		protected String doInBackground(String... files)
+		{
 			m_foldernames  = new Vector<String>();
+			m_filenames    = new Vector<String>();
 			m_tocopy       = new Vector<String>();
 			m_asset_size_unknown = new Vector<String>();
-			String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/";
+			String baseDir = 
+					Environment.getExternalStorageDirectory().getAbsolutePath()
+					+ "/";
+			
 			
+			// prepare temp folder
 			File TempFolder = new File(baseDir + "Minetest/tmp/");
 			
-			if (!TempFolder.exists()) {
+			if (!TempFolder.exists())
+			{
 				TempFolder.mkdir();
 			}
 			else {
 				File[] todel = TempFolder.listFiles();
 				
-				for(int i=0; i < todel.length; i++) {
-					Log.w("MinetestAssetCopy","deleting: " + todel[i].getAbsolutePath());
+				for(int i=0; i < todel.length; i++)
+				{
+					Log.v("MinetestAssetCopy","deleting: " + todel[i].getAbsolutePath());
 					todel[i].delete();
 				}
 			}
@@ -156,52 +118,49 @@ public class MinetestAssetCopy extends Activity {
 				OutputStream dst = new FileOutputStream(baseDir + "Minetest/.nomedia");
 				dst.close();
 			} catch (IOException e) {
-				Log.w("MinetestAssetCopy","Failed to create .nomedia file");
+				Log.e("MinetestAssetCopy","Failed to create .nomedia file");
 				e.printStackTrace();
 			}
 			
-			try {
-				InputStream is = getAssets().open("index.txt");
-				BufferedReader reader = new BufferedReader(new InputStreamReader(is));
-		
-				String line = reader.readLine();
-				while(line != null){
-					m_foldernames.add(line);
-					line = reader.readLine();
-				}
-			} catch (IOException e1) {
-				// TODO Auto-generated catch block
-				e1.printStackTrace();
-			}
 			
-			copyElement("Minetest","");
+			// build lists from prepared data
+			BuildFolderList();
+			BuildFileList();
+			
+			// scan filelist
+			ProcessFileList();
 			
+			// doing work
 			m_copy_started = true;
 			m_ProgressBar.setMax(m_tocopy.size());
 			
-			for (int i = 0; i < m_tocopy.size(); i++) {
-				try {
+			for (int i = 0; i < m_tocopy.size(); i++)
+			{
+				try
+				{
 					String filename = m_tocopy.get(i);
 					publishProgress(i);
 					
 					boolean asset_size_unknown = false;
 					long filesize = -1;
 					
-					if (m_asset_size_unknown.contains(filename)) {
+					if (m_asset_size_unknown.contains(filename))
+					{
 						File testme = new File(baseDir + "/" + filename);
 						
-						if(testme.exists()) {
+						if(testme.exists())
+						{
 							filesize = testme.length();
 						}
 						asset_size_unknown = true;
 					}
 					
 					InputStream src;
-					try {
+					try
+					{
 						src = getAssets().open(filename);
 					} catch (IOException e) {
-						Log.w("MinetestAssetCopy","Copying file: " + filename + " FAILED (not in assets)");
-						// TODO Auto-generated catch block
+						Log.e("MinetestAssetCopy","Copying file: " + filename + " FAILED (not in assets)");
 						e.printStackTrace();
 						continue;
 					}
@@ -211,32 +170,38 @@ public class MinetestAssetCopy extends Activity {
 					int len = src.read(buf, 0, 1024);
 					
 					/* following handling is crazy but we need to deal with    */
-					/* compressed assets.Flash chips limited livetime sue to   */
+					/* compressed assets.Flash chips limited livetime due to   */
 					/* write operations, we can't allow large files to destroy */
 					/* users flash.                                            */
-					if (asset_size_unknown) {
-						if ( (len > 0) && (len < buf.length) && (len == filesize)) {
+					if (asset_size_unknown)
+					{
+						if ( (len > 0) && (len < buf.length) && (len == filesize))
+						{
 							src.close();
 							continue;
 						}
 						
-						if (len == buf.length) {
+						if (len == buf.length)
+						{
 							src.close();
 							long size = getFullSize(filename);
-							if ( size == filesize) {
+							if ( size == filesize)
+							{
 								continue;
 							}
 							src = getAssets().open(filename);
 							len = src.read(buf, 0, 1024);
 						}
 					}
-					if (len > 0) {
+					if (len > 0)
+					{
 						int total_filesize = 0;
 						OutputStream dst;
-						try {
+						try
+						{
 							dst = new FileOutputStream(baseDir + "/" + filename);
 						} catch (IOException e) {
-							Log.w("MinetestAssetCopy","Copying file: " + baseDir + 
+							Log.e("MinetestAssetCopy","Copying file: " + baseDir +
 							"/" + filename + " FAILED (couldn't open output file)");
 							e.printStackTrace();
 							src.close();
@@ -245,43 +210,196 @@ public class MinetestAssetCopy extends Activity {
 						dst.write(buf, 0, len);
 						total_filesize += len;
 						
-						while ((len = src.read(buf)) > 0) {
+						while ((len = src.read(buf)) > 0)
+						{
 							dst.write(buf, 0, len);
 							total_filesize += len;
 						}
 						
 						dst.close();
-						Log.w("MinetestAssetCopy","Copied file: " + m_tocopy.get(i) + " (" + total_filesize + " bytes)");
+						Log.v("MinetestAssetCopy","Copied file: " +
+									m_tocopy.get(i) + " (" + total_filesize +
+									" bytes)");
 					}
-					else if (len < 0) {
-						Log.w("MinetestAssetCopy","Copying file: " + m_tocopy.get(i) + " failed, size < 0");
+					else if (len < 0)
+					{
+						Log.e("MinetestAssetCopy","Copying file: " +
+								m_tocopy.get(i) + " failed, size < 0");
 					}
 					src.close();
-				} catch (IOException e) {
-					Log.w("MinetestAssetCopy","Copying file: " + m_tocopy.get(i) + " failed");
+				} 
+				catch (IOException e)
+				{
+					Log.e("MinetestAssetCopy","Copying file: " +
+							m_tocopy.get(i) + " failed");
 					e.printStackTrace();
 				}
 			}
-			
 			return "";
 		}
 		
-		protected void onProgressUpdate(Integer... progress) {
-			if (m_copy_started) {
+		
+		/**
+		 * update progress bar
+		 */
+		protected void onProgressUpdate(Integer... progress)
+		{
+			if (m_copy_started)
+			{
 				m_ProgressBar.setProgress(progress[0]);
 				m_Filename.setText(m_tocopy.get(progress[0]));
 			}
-			else {
+			else
+			{
 				m_Filename.setText("scanning " + m_Foldername + " ...");
 			}
 		}
 		
-		protected void onPostExecute (String result) {
+		/**
+		 * check al files and folders in filelist
+		 */
+		protected void ProcessFileList()
+		{
+			String FlashBaseDir = 
+					Environment.getExternalStorageDirectory().getAbsolutePath();
+			
+			Iterator itr = m_filenames.iterator();
+			
+			while (itr.hasNext())
+			{
+				String current_path = (String) itr.next();
+				String FlashPath = FlashBaseDir + "/" + current_path;
+				
+				if (isAssetFolder(current_path))
+				{
+					/* store information and update gui */
+					m_Foldername = current_path;
+					publishProgress(0);
+					
+					/* open file in order to check if it's a folder */
+					File current_folder = new File(FlashPath);
+					if (!current_folder.exists())
+					 {
+						if (!current_folder.mkdirs())
+						{
+							Log.e("MinetestAssetCopy","\t failed create folder: " +
+									FlashPath);
+						}
+						else
+						{
+							Log.v("MinetestAssetCopy","\t created folder: " +
+									FlashPath);
+						}
+					}
+					
+					continue;
+				}
+				
+				/* if it's not a folder it's most likely a file */
+				boolean refresh = true;
+				
+				File testme = new File(FlashPath);
+				
+				long asset_filesize = -1;
+				long stored_filesize = -1;
+				
+				if (testme.exists())
+				{
+					try
+					{
+						AssetFileDescriptor fd = getAssets().openFd(current_path);
+						asset_filesize         = fd.getLength();
+						fd.close();
+					} 
+					catch (IOException e)
+					{
+						refresh = true;
+						m_asset_size_unknown.add(current_path);
+						Log.e("MinetestAssetCopy","Failed to open asset file \"" +
+								FlashPath + "\" for size check");
+					}
+					
+					stored_filesize = testme.length();
+					
+					if (asset_filesize == stored_filesize)
+					{
+						refresh = false;
+					}
+					
+				}
+				
+				if (refresh)
+				{
+					m_tocopy.add(current_path);
+				}
+			}
+		}
+		
+		/**
+		 * read list of folders prepared on package build
+		 */
+		protected void BuildFolderList()
+		{
+			try
+			{
+				InputStream is = getAssets().open("index.txt");
+				BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+		
+				String line = reader.readLine();
+				while (line != null)
+				{
+					m_foldernames.add(line);
+					line = reader.readLine();
+				}
+				is.close();
+			} catch (IOException e1)
+			{
+				Log.e("MinetestAssetCopy","Error on processing index.txt");
+				e1.printStackTrace();
+			}
+		}
+		
+		/**
+		 * read list of asset files prepared on package build
+		 */
+		protected void BuildFileList()
+		{
+			long entrycount = 0;
+			try
+			{
+				InputStream is = getAssets().open("filelist.txt");
+				BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+		
+				String line = reader.readLine();
+				while (line != null)
+				{
+					m_filenames.add(line);
+					line = reader.readLine();
+					entrycount ++;
+				}
+				is.close();
+			}
+			catch (IOException e1)
+			{
+				Log.e("MinetestAssetCopy","Error on processing filelist.txt");
+				e1.printStackTrace();
+			}
+		}
+		
+		protected void onPostExecute (String result)
+		{
 			finish();
 		}
+		
+		protected boolean isAssetFolder(String path)
+		{
+			return m_foldernames.contains(path);
+		}
+		
 		boolean m_copy_started = false;
 		String m_Foldername = "media";
 		Vector<String> m_foldernames;
+		Vector<String> m_filenames;
 		Vector<String> m_tocopy;
 		Vector<String> m_asset_size_unknown;
 	}