Speedup initial android startup on some devices by factor 10 or more 1985/head
authorsapier <Sapier at GMX dot net>
Wed, 17 Dec 2014 23:23:36 +0000 (00:23 +0100)
committersapier <Sapier at GMX dot net>
Fri, 2 Jan 2015 16:20:55 +0000 (17:20 +0100)
build/android/Makefile
build/android/src/org/minetest/minetest/MinetestAssetCopy.java

index d3d38f9ea33172c28740f7c60d8085bab56b2fb4..d4760ee21d70323616c1ac70faeb0f5a4e4f799c 100644 (file)
@@ -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";                                  \
index 652a00831341e25d669f385710870ea079a9b9a9..f6b2e80130478879f4aaf4ce4d8ec675a6e29da1 100644 (file)
@@ -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;
        }