b570fe61a1a4830c6ac8651f315f88fadf1e819b
[oweals/minetest.git] / build / android / src / main / java / net.minetest.minetest / MinetestAssetCopy.java
1 package net.minetest.minetest;
2
3 import android.app.Activity;
4 import android.content.res.AssetFileDescriptor;
5 import android.os.AsyncTask;
6 import android.os.Build;
7 import android.os.Bundle;
8 import android.os.Environment;
9 import android.util.Log;
10 import android.view.Display;
11 import android.view.View;
12 import android.widget.ProgressBar;
13 import android.widget.TextView;
14
15 import java.io.BufferedReader;
16 import java.io.File;
17 import java.io.FileOutputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.InputStreamReader;
21 import java.io.OutputStream;
22 import java.util.Iterator;
23 import java.util.Vector;
24
25 public class MinetestAssetCopy extends Activity {
26         ProgressBar m_ProgressBar;
27         TextView m_Filename;
28         copyAssetTask m_AssetCopy;
29
30         @Override
31         public void onCreate(Bundle savedInstanceState) {
32                 super.onCreate(savedInstanceState);
33                 setContentView(R.layout.assetcopy);
34                 m_ProgressBar = findViewById(R.id.progressBar1);
35                 m_Filename = findViewById(R.id.textView1);
36                 Display display = getWindowManager().getDefaultDisplay();
37                 m_ProgressBar.getLayoutParams().width = (int) (display.getWidth() * 0.8);
38                 m_ProgressBar.invalidate();
39
40                 /* check if there's already a copy in progress and reuse in case it is*/
41                 MinetestAssetCopy prevActivity =
42                                 (MinetestAssetCopy) getLastNonConfigurationInstance();
43                 if (prevActivity != null) {
44                         m_AssetCopy = prevActivity.m_AssetCopy;
45                 } else {
46                         m_AssetCopy = new copyAssetTask();
47                         m_AssetCopy.execute();
48                 }
49         }
50
51         @Override
52         protected void onResume() {
53                 super.onResume();
54                 makeFullScreen();
55         }
56
57         public void makeFullScreen() {
58                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
59                         this.getWindow().getDecorView().setSystemUiVisibility(
60                                         View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
61                         );
62                 }
63         }
64
65         @Override
66         public void onWindowFocusChanged(boolean hasFocus) {
67                 super.onWindowFocusChanged(hasFocus);
68                 if (hasFocus) {
69                         makeFullScreen();
70                 }
71         }
72
73         /* preserve asset copy background task to prevent restart of copying */
74         /* this way of doing it is not recommended for latest android version */
75         /* but the recommended way isn't available on android 2.x */
76         public Object onRetainNonConfigurationInstance() {
77                 return this;
78         }
79
80         private class copyAssetTask extends AsyncTask<String, Integer, String> {
81                 boolean m_copy_started = false;
82                 String m_Foldername = "media";
83                 Vector<String> m_foldernames;
84                 Vector<String> m_filenames;
85                 Vector<String> m_tocopy;
86                 Vector<String> m_asset_size_unknown;
87
88                 private long getFullSize(String filename) {
89                         long size = 0;
90                         try {
91                                 InputStream src = getAssets().open(filename);
92                                 byte[] buf = new byte[4096];
93
94                                 int len = 0;
95                                 while ((len = src.read(buf)) > 0) {
96                                         size += len;
97                                 }
98                         } catch (IOException e) {
99                                 e.printStackTrace();
100                         }
101                         return size;
102                 }
103
104                 @Override
105                 protected String doInBackground(String... files) {
106                         m_foldernames = new Vector<String>();
107                         m_filenames = new Vector<String>();
108                         m_tocopy = new Vector<String>();
109                         m_asset_size_unknown = new Vector<String>();
110                         String baseDir =
111                                         Environment.getExternalStorageDirectory().getAbsolutePath()
112                                                         + "/";
113
114
115                         // prepare temp folder
116                         File TempFolder = new File(baseDir + "Minetest/tmp/");
117
118                         if (!TempFolder.exists()) {
119                                 TempFolder.mkdir();
120                         } else {
121                                 File[] todel = TempFolder.listFiles();
122
123                                 for (int i = 0; i < todel.length; i++) {
124                                         Log.v("MinetestAssetCopy", "deleting: " + todel[i].getAbsolutePath());
125                                         todel[i].delete();
126                                 }
127                         }
128
129                         // add a .nomedia file
130                         try {
131                                 OutputStream dst = new FileOutputStream(baseDir + "Minetest/.nomedia");
132                                 dst.close();
133                         } catch (IOException e) {
134                                 Log.e("MinetestAssetCopy", "Failed to create .nomedia file");
135                                 e.printStackTrace();
136                         }
137
138
139                         // build lists from prepared data
140                         BuildFolderList();
141                         BuildFileList();
142
143                         // scan filelist
144                         ProcessFileList();
145
146                         // doing work
147                         m_copy_started = true;
148                         m_ProgressBar.setMax(m_tocopy.size());
149
150                         for (int i = 0; i < m_tocopy.size(); i++) {
151                                 try {
152                                         String filename = m_tocopy.get(i);
153                                         publishProgress(i);
154
155                                         boolean asset_size_unknown = false;
156                                         long filesize = -1;
157
158                                         if (m_asset_size_unknown.contains(filename)) {
159                                                 File testme = new File(baseDir + "/" + filename);
160
161                                                 if (testme.exists()) {
162                                                         filesize = testme.length();
163                                                 }
164                                                 asset_size_unknown = true;
165                                         }
166
167                                         InputStream src;
168                                         try {
169                                                 src = getAssets().open(filename);
170                                         } catch (IOException e) {
171                                                 Log.e("MinetestAssetCopy", "Copying file: " + filename + " FAILED (not in assets)");
172                                                 e.printStackTrace();
173                                                 continue;
174                                         }
175
176                                         // Transfer bytes from in to out
177                                         byte[] buf = new byte[1024];
178                                         int len = src.read(buf, 0, 1024);
179
180                                         /* following handling is crazy but we need to deal with    */
181                                         /* compressed assets.Flash chips limited livetime due to   */
182                                         /* write operations, we can't allow large files to destroy */
183                                         /* users flash.                                            */
184                                         if (asset_size_unknown) {
185                                                 if ((len > 0) && (len < buf.length) && (len == filesize)) {
186                                                         src.close();
187                                                         continue;
188                                                 }
189
190                                                 if (len == buf.length) {
191                                                         src.close();
192                                                         long size = getFullSize(filename);
193                                                         if (size == filesize) {
194                                                                 continue;
195                                                         }
196                                                         src = getAssets().open(filename);
197                                                         len = src.read(buf, 0, 1024);
198                                                 }
199                                         }
200                                         if (len > 0) {
201                                                 int total_filesize = 0;
202                                                 OutputStream dst;
203                                                 try {
204                                                         dst = new FileOutputStream(baseDir + "/" + filename);
205                                                 } catch (IOException e) {
206                                                         Log.e("MinetestAssetCopy", "Copying file: " + baseDir +
207                                                                         "/" + filename + " FAILED (couldn't open output file)");
208                                                         e.printStackTrace();
209                                                         src.close();
210                                                         continue;
211                                                 }
212                                                 dst.write(buf, 0, len);
213                                                 total_filesize += len;
214
215                                                 while ((len = src.read(buf)) > 0) {
216                                                         dst.write(buf, 0, len);
217                                                         total_filesize += len;
218                                                 }
219
220                                                 dst.close();
221                                                 Log.v("MinetestAssetCopy", "Copied file: " +
222                                                                 m_tocopy.get(i) + " (" + total_filesize +
223                                                                 " bytes)");
224                                         } else if (len < 0) {
225                                                 Log.e("MinetestAssetCopy", "Copying file: " +
226                                                                 m_tocopy.get(i) + " failed, size < 0");
227                                         }
228                                         src.close();
229                                 } catch (IOException e) {
230                                         Log.e("MinetestAssetCopy", "Copying file: " +
231                                                         m_tocopy.get(i) + " failed");
232                                         e.printStackTrace();
233                                 }
234                         }
235                         return "";
236                 }
237
238                 /**
239                  * update progress bar
240                  */
241                 protected void onProgressUpdate(Integer... progress) {
242
243                         if (m_copy_started) {
244                                 boolean shortened = false;
245                                 String todisplay = m_tocopy.get(progress[0]);
246                                 m_ProgressBar.setProgress(progress[0]);
247                                 m_Filename.setText(todisplay);
248                         } else {
249                                 boolean shortened = false;
250                                 String todisplay = m_Foldername;
251                                 String full_text = "scanning " + todisplay + " ...";
252                                 m_Filename.setText(full_text);
253                         }
254                 }
255
256                 /**
257                  * check all files and folders in filelist
258                  */
259                 protected void ProcessFileList() {
260                         String FlashBaseDir =
261                                         Environment.getExternalStorageDirectory().getAbsolutePath();
262
263                         Iterator itr = m_filenames.iterator();
264
265                         while (itr.hasNext()) {
266                                 String current_path = (String) itr.next();
267                                 String FlashPath = FlashBaseDir + "/" + current_path;
268
269                                 if (isAssetFolder(current_path)) {
270                                         /* store information and update gui */
271                                         m_Foldername = current_path;
272                                         publishProgress(0);
273
274                                         /* open file in order to check if it's a folder */
275                                         File current_folder = new File(FlashPath);
276                                         if (!current_folder.exists()) {
277                                                 if (!current_folder.mkdirs()) {
278                                                         Log.e("MinetestAssetCopy", "\t failed create folder: " +
279                                                                         FlashPath);
280                                                 } else {
281                                                         Log.v("MinetestAssetCopy", "\t created folder: " +
282                                                                         FlashPath);
283                                                 }
284                                         }
285
286                                         continue;
287                                 }
288
289                                 /* if it's not a folder it's most likely a file */
290                                 boolean refresh = true;
291
292                                 File testme = new File(FlashPath);
293
294                                 long asset_filesize = -1;
295                                 long stored_filesize = -1;
296
297                                 if (testme.exists()) {
298                                         try {
299                                                 AssetFileDescriptor fd = getAssets().openFd(current_path);
300                                                 asset_filesize = fd.getLength();
301                                                 fd.close();
302                                         } catch (IOException e) {
303                                                 refresh = true;
304                                                 m_asset_size_unknown.add(current_path);
305                                                 Log.e("MinetestAssetCopy", "Failed to open asset file \"" +
306                                                                 FlashPath + "\" for size check");
307                                         }
308
309                                         stored_filesize = testme.length();
310
311                                         if (asset_filesize == stored_filesize) {
312                                                 refresh = false;
313                                         }
314
315                                 }
316
317                                 if (refresh) {
318                                         m_tocopy.add(current_path);
319                                 }
320                         }
321                 }
322
323                 /**
324                  * read list of folders prepared on package build
325                  */
326                 protected void BuildFolderList() {
327                         try {
328                                 InputStream is = getAssets().open("index.txt");
329                                 BufferedReader reader = new BufferedReader(new InputStreamReader(is));
330
331                                 String line = reader.readLine();
332                                 while (line != null) {
333                                         m_foldernames.add(line);
334                                         line = reader.readLine();
335                                 }
336                                 is.close();
337                         } catch (IOException e1) {
338                                 Log.e("MinetestAssetCopy", "Error on processing index.txt");
339                                 e1.printStackTrace();
340                         }
341                 }
342
343                 /**
344                  * read list of asset files prepared on package build
345                  */
346                 protected void BuildFileList() {
347                         long entrycount = 0;
348                         try {
349                                 InputStream is = getAssets().open("filelist.txt");
350                                 BufferedReader reader = new BufferedReader(new InputStreamReader(is));
351
352                                 String line = reader.readLine();
353                                 while (line != null) {
354                                         m_filenames.add(line);
355                                         line = reader.readLine();
356                                         entrycount++;
357                                 }
358                                 is.close();
359                         } catch (IOException e1) {
360                                 Log.e("MinetestAssetCopy", "Error on processing filelist.txt");
361                                 e1.printStackTrace();
362                         }
363                 }
364
365                 protected void onPostExecute(String result) {
366                         finish();
367                 }
368
369                 protected boolean isAssetFolder(String path) {
370                         return m_foldernames.contains(path);
371                 }
372         }
373 }