1 package net.minetest.minetest;
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;
15 import java.io.BufferedReader;
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;
25 public class MinetestAssetCopy extends Activity {
26 ProgressBar m_ProgressBar;
28 copyAssetTask m_AssetCopy;
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();
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;
46 m_AssetCopy = new copyAssetTask();
47 m_AssetCopy.execute();
52 protected void onResume() {
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
66 public void onWindowFocusChanged(boolean hasFocus) {
67 super.onWindowFocusChanged(hasFocus);
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() {
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;
88 private long getFullSize(String filename) {
91 InputStream src = getAssets().open(filename);
92 byte[] buf = new byte[4096];
95 while ((len = src.read(buf)) > 0) {
98 } catch (IOException e) {
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>();
111 Environment.getExternalStorageDirectory().getAbsolutePath()
115 // prepare temp folder
116 File TempFolder = new File(baseDir + "Minetest/tmp/");
118 if (!TempFolder.exists()) {
121 File[] todel = TempFolder.listFiles();
123 for (int i = 0; i < todel.length; i++) {
124 Log.v("MinetestAssetCopy", "deleting: " + todel[i].getAbsolutePath());
129 // add a .nomedia file
131 OutputStream dst = new FileOutputStream(baseDir + "Minetest/.nomedia");
133 } catch (IOException e) {
134 Log.e("MinetestAssetCopy", "Failed to create .nomedia file");
139 // build lists from prepared data
147 m_copy_started = true;
148 m_ProgressBar.setMax(m_tocopy.size());
150 for (int i = 0; i < m_tocopy.size(); i++) {
152 String filename = m_tocopy.get(i);
155 boolean asset_size_unknown = false;
158 if (m_asset_size_unknown.contains(filename)) {
159 File testme = new File(baseDir + "/" + filename);
161 if (testme.exists()) {
162 filesize = testme.length();
164 asset_size_unknown = true;
169 src = getAssets().open(filename);
170 } catch (IOException e) {
171 Log.e("MinetestAssetCopy", "Copying file: " + filename + " FAILED (not in assets)");
176 // Transfer bytes from in to out
177 byte[] buf = new byte[1024];
178 int len = src.read(buf, 0, 1024);
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 */
184 if (asset_size_unknown) {
185 if ((len > 0) && (len < buf.length) && (len == filesize)) {
190 if (len == buf.length) {
192 long size = getFullSize(filename);
193 if (size == filesize) {
196 src = getAssets().open(filename);
197 len = src.read(buf, 0, 1024);
201 int total_filesize = 0;
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)");
212 dst.write(buf, 0, len);
213 total_filesize += len;
215 while ((len = src.read(buf)) > 0) {
216 dst.write(buf, 0, len);
217 total_filesize += len;
221 Log.v("MinetestAssetCopy", "Copied file: " +
222 m_tocopy.get(i) + " (" + total_filesize +
224 } else if (len < 0) {
225 Log.e("MinetestAssetCopy", "Copying file: " +
226 m_tocopy.get(i) + " failed, size < 0");
229 } catch (IOException e) {
230 Log.e("MinetestAssetCopy", "Copying file: " +
231 m_tocopy.get(i) + " failed");
239 * update progress bar
241 protected void onProgressUpdate(Integer... progress) {
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);
249 boolean shortened = false;
250 String todisplay = m_Foldername;
251 String full_text = "scanning " + todisplay + " ...";
252 m_Filename.setText(full_text);
257 * check all files and folders in filelist
259 protected void ProcessFileList() {
260 String FlashBaseDir =
261 Environment.getExternalStorageDirectory().getAbsolutePath();
263 Iterator itr = m_filenames.iterator();
265 while (itr.hasNext()) {
266 String current_path = (String) itr.next();
267 String FlashPath = FlashBaseDir + "/" + current_path;
269 if (isAssetFolder(current_path)) {
270 /* store information and update gui */
271 m_Foldername = current_path;
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: " +
281 Log.v("MinetestAssetCopy", "\t created folder: " +
289 /* if it's not a folder it's most likely a file */
290 boolean refresh = true;
292 File testme = new File(FlashPath);
294 long asset_filesize = -1;
295 long stored_filesize = -1;
297 if (testme.exists()) {
299 AssetFileDescriptor fd = getAssets().openFd(current_path);
300 asset_filesize = fd.getLength();
302 } catch (IOException e) {
304 m_asset_size_unknown.add(current_path);
305 Log.e("MinetestAssetCopy", "Failed to open asset file \"" +
306 FlashPath + "\" for size check");
309 stored_filesize = testme.length();
311 if (asset_filesize == stored_filesize) {
318 m_tocopy.add(current_path);
324 * read list of folders prepared on package build
326 protected void BuildFolderList() {
328 InputStream is = getAssets().open("index.txt");
329 BufferedReader reader = new BufferedReader(new InputStreamReader(is));
331 String line = reader.readLine();
332 while (line != null) {
333 m_foldernames.add(line);
334 line = reader.readLine();
337 } catch (IOException e1) {
338 Log.e("MinetestAssetCopy", "Error on processing index.txt");
339 e1.printStackTrace();
344 * read list of asset files prepared on package build
346 protected void BuildFileList() {
349 InputStream is = getAssets().open("filelist.txt");
350 BufferedReader reader = new BufferedReader(new InputStreamReader(is));
352 String line = reader.readLine();
353 while (line != null) {
354 m_filenames.add(line);
355 line = reader.readLine();
359 } catch (IOException e1) {
360 Log.e("MinetestAssetCopy", "Error on processing filelist.txt");
361 e1.printStackTrace();
365 protected void onPostExecute(String result) {
369 protected boolean isAssetFolder(String path) {
370 return m_foldernames.contains(path);