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() {
58 protected void onDestroy() {
60 if (m_AssetCopy != null) {
61 m_AssetCopy.cancel(true);
65 public void makeFullScreen() {
66 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
67 this.getWindow().getDecorView().setSystemUiVisibility(
68 View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
74 public void onWindowFocusChanged(boolean hasFocus) {
75 super.onWindowFocusChanged(hasFocus);
81 /* preserve asset copy background task to prevent restart of copying */
82 /* this way of doing it is not recommended for latest android version */
83 /* but the recommended way isn't available on android 2.x */
84 public Object onRetainNonConfigurationInstance() {
88 private static class copyAssetTask extends AsyncTask<String, Integer, String> {
89 boolean m_copy_started = false;
90 String m_Foldername = "media";
91 Vector<String> m_foldernames;
92 Vector<String> m_filenames;
93 Vector<String> m_tocopy;
94 Vector<String> m_asset_size_unknown;
96 private long getFullSize(String filename) {
99 InputStream src = getAssets().open(filename);
100 byte[] buf = new byte[4096];
103 while ((len = src.read(buf)) > 0) {
106 } catch (IOException e) {
113 protected String doInBackground(String... files) {
114 m_foldernames = new Vector<String>();
115 m_filenames = new Vector<String>();
116 m_tocopy = new Vector<String>();
117 m_asset_size_unknown = new Vector<String>();
119 Environment.getExternalStorageDirectory().getAbsolutePath()
123 // prepare temp folder
124 File TempFolder = new File(baseDir + "Minetest/tmp/");
126 if (!TempFolder.exists()) {
129 File[] todel = TempFolder.listFiles();
131 for (int i = 0; i < todel.length; i++) {
132 Log.v("MinetestAssetCopy", "deleting: " + todel[i].getAbsolutePath());
137 // add a .nomedia file
139 OutputStream dst = new FileOutputStream(baseDir + "Minetest/.nomedia");
141 } catch (IOException e) {
142 Log.e("MinetestAssetCopy", "Failed to create .nomedia file");
147 // build lists from prepared data
155 m_copy_started = true;
156 m_ProgressBar.setMax(m_tocopy.size());
158 for (int i = 0; i < m_tocopy.size(); i++) {
160 String filename = m_tocopy.get(i);
163 boolean asset_size_unknown = false;
166 if (m_asset_size_unknown.contains(filename)) {
167 File testme = new File(baseDir + "/" + filename);
169 if (testme.exists()) {
170 filesize = testme.length();
172 asset_size_unknown = true;
177 src = getAssets().open(filename);
178 } catch (IOException e) {
179 Log.e("MinetestAssetCopy", "Copying file: " + filename + " FAILED (not in assets)");
184 // Transfer bytes from in to out
185 byte[] buf = new byte[1024];
186 int len = src.read(buf, 0, 1024);
188 /* following handling is crazy but we need to deal with */
189 /* compressed assets.Flash chips limited livetime due to */
190 /* write operations, we can't allow large files to destroy */
192 if (asset_size_unknown) {
193 if ((len > 0) && (len < buf.length) && (len == filesize)) {
198 if (len == buf.length) {
200 long size = getFullSize(filename);
201 if (size == filesize) {
204 src = getAssets().open(filename);
205 len = src.read(buf, 0, 1024);
209 int total_filesize = 0;
212 dst = new FileOutputStream(baseDir + "/" + filename);
213 } catch (IOException e) {
214 Log.e("MinetestAssetCopy", "Copying file: " + baseDir +
215 "/" + filename + " FAILED (couldn't open output file)");
220 dst.write(buf, 0, len);
221 total_filesize += len;
223 while ((len = src.read(buf)) > 0) {
224 dst.write(buf, 0, len);
225 total_filesize += len;
229 Log.v("MinetestAssetCopy", "Copied file: " +
230 m_tocopy.get(i) + " (" + total_filesize +
232 } else if (len < 0) {
233 Log.e("MinetestAssetCopy", "Copying file: " +
234 m_tocopy.get(i) + " failed, size < 0");
237 } catch (IOException e) {
238 Log.e("MinetestAssetCopy", "Copying file: " +
239 m_tocopy.get(i) + " failed");
247 * update progress bar
249 protected void onProgressUpdate(Integer... progress) {
251 if (m_copy_started) {
252 boolean shortened = false;
253 String todisplay = m_tocopy.get(progress[0]);
254 m_ProgressBar.setProgress(progress[0]);
255 m_Filename.setText(todisplay);
257 boolean shortened = false;
258 String todisplay = m_Foldername;
259 String full_text = "scanning " + todisplay + " ...";
260 m_Filename.setText(full_text);
265 * check all files and folders in filelist
267 protected void ProcessFileList() {
268 String FlashBaseDir =
269 Environment.getExternalStorageDirectory().getAbsolutePath();
271 Iterator itr = m_filenames.iterator();
273 while (itr.hasNext()) {
274 String current_path = (String) itr.next();
275 String FlashPath = FlashBaseDir + "/" + current_path;
277 if (isAssetFolder(current_path)) {
278 /* store information and update gui */
279 m_Foldername = current_path;
282 /* open file in order to check if it's a folder */
283 File current_folder = new File(FlashPath);
284 if (!current_folder.exists()) {
285 if (!current_folder.mkdirs()) {
286 Log.e("MinetestAssetCopy", "\t failed create folder: " +
289 Log.v("MinetestAssetCopy", "\t created folder: " +
297 /* if it's not a folder it's most likely a file */
298 boolean refresh = true;
300 File testme = new File(FlashPath);
302 long asset_filesize = -1;
303 long stored_filesize = -1;
305 if (testme.exists()) {
307 AssetFileDescriptor fd = getAssets().openFd(current_path);
308 asset_filesize = fd.getLength();
310 } catch (IOException e) {
312 m_asset_size_unknown.add(current_path);
313 Log.e("MinetestAssetCopy", "Failed to open asset file \"" +
314 FlashPath + "\" for size check");
317 stored_filesize = testme.length();
319 if (asset_filesize == stored_filesize) {
326 m_tocopy.add(current_path);
332 * read list of folders prepared on package build
334 protected void BuildFolderList() {
336 InputStream is = getAssets().open("index.txt");
337 BufferedReader reader = new BufferedReader(new InputStreamReader(is));
339 String line = reader.readLine();
340 while (line != null) {
341 m_foldernames.add(line);
342 line = reader.readLine();
345 } catch (IOException e1) {
346 Log.e("MinetestAssetCopy", "Error on processing index.txt");
347 e1.printStackTrace();
352 * read list of asset files prepared on package build
354 protected void BuildFileList() {
357 InputStream is = getAssets().open("filelist.txt");
358 BufferedReader reader = new BufferedReader(new InputStreamReader(is));
360 String line = reader.readLine();
361 while (line != null) {
362 m_filenames.add(line);
363 line = reader.readLine();
367 } catch (IOException e1) {
368 Log.e("MinetestAssetCopy", "Error on processing filelist.txt");
369 e1.printStackTrace();
373 protected void onPostExecute(String result) {
377 protected boolean isAssetFolder(String path) {
378 return m_foldernames.contains(path);