diff options
Diffstat (limited to 'build/android/src/main')
-rw-r--r-- | build/android/src/main/AndroidManifest.xml | 34 | ||||
-rw-r--r-- | build/android/src/main/java/net.minetest.minetest/MinetestAssetCopy.java | 416 | ||||
-rw-r--r-- | build/android/src/main/java/net.minetest.minetest/MinetestTextEntry.java | 91 | ||||
-rw-r--r-- | build/android/src/main/java/net.minetest.minetest/MtNativeActivity.java | 104 | ||||
-rw-r--r-- | build/android/src/main/res/drawable-hdpi/irr_icon.png | bin | 0 -> 5490 bytes | |||
-rw-r--r-- | build/android/src/main/res/drawable-ldpi/irr_icon.png | bin | 0 -> 2262 bytes | |||
-rw-r--r-- | build/android/src/main/res/drawable-mdpi/irr_icon.png | bin | 0 -> 3110 bytes | |||
-rw-r--r-- | build/android/src/main/res/drawable-xhdpi/irr_icon.png | bin | 0 -> 7610 bytes | |||
-rw-r--r-- | build/android/src/main/res/layout/assetcopy.xml | 24 | ||||
-rw-r--r-- | build/android/src/main/res/values/strings.xml | 5 | ||||
-rw-r--r-- | build/android/src/main/res/values/styles.xml | 11 |
11 files changed, 685 insertions, 0 deletions
diff --git a/build/android/src/main/AndroidManifest.xml b/build/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..df218fb33 --- /dev/null +++ b/build/android/src/main/AndroidManifest.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="net.minetest.minetest" + android:installLocation="auto"> + <uses-feature android:glEsVersion="0x00010000" android:required="true"/> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <application android:icon="@drawable/irr_icon" + android:label="${project}" + android:theme="@android:style/Theme.NoTitleBar.Fullscreen" + android:allowBackup="true"> + <activity android:name=".MtNativeActivity" + android:label="${project}" + android:launchMode="singleTask" + android:configChanges="orientation|keyboard|keyboardHidden|navigation" + android:screenOrientation="sensorLandscape" + android:clearTaskOnLaunch="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + <meta-data android:name="android.app.lib_name" android:value="minetest" /> + </activity> + <activity android:name=".MinetestTextEntry" + android:theme="@style/Theme.Transparent" + android:excludeFromRecents="true"> + </activity> + <activity android:name=".MinetestAssetCopy" + android:theme="@style/Theme.Transparent" + android:excludeFromRecents="true"> + </activity> + </application> +</manifest> diff --git a/build/android/src/main/java/net.minetest.minetest/MinetestAssetCopy.java b/build/android/src/main/java/net.minetest.minetest/MinetestAssetCopy.java new file mode 100644 index 000000000..eb92acb63 --- /dev/null +++ b/build/android/src/main/java/net.minetest.minetest/MinetestAssetCopy.java @@ -0,0 +1,416 @@ +package net.minetest.minetest; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.Vector; +import java.util.Iterator; +import java.lang.Object; + +import android.app.Activity; +import android.content.res.AssetFileDescriptor; + +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Environment; +import android.util.Log; +import android.view.Display; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.graphics.Rect; +import android.graphics.Paint; +import android.text.TextPaint; + +public class MinetestAssetCopy extends Activity +{ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + setContentView(R.layout.assetcopy); + + m_ProgressBar = (ProgressBar) findViewById(R.id.progressBar1); + m_Filename = (TextView) findViewById(R.id.textView1); + + Display display = getWindowManager().getDefaultDisplay(); + m_ProgressBar.getLayoutParams().width = (int) (display.getWidth() * 0.8); + m_ProgressBar.invalidate(); + + /* 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; + TextView m_Filename; + + copyAssetTask m_AssetCopy; + + 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[4096]; + + int len = 0; + while ((len = src.read(buf)) > 0) + { + size += len; + } + } + catch (IOException e) + { + e.printStackTrace(); + } + return size; + } + + @Override + 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() + + "/"; + + + // prepare temp folder + File TempFolder = new File(baseDir + "Minetest/tmp/"); + + if (!TempFolder.exists()) + { + TempFolder.mkdir(); + } + else { + File[] todel = TempFolder.listFiles(); + + for(int i=0; i < todel.length; i++) + { + Log.v("MinetestAssetCopy","deleting: " + todel[i].getAbsolutePath()); + todel[i].delete(); + } + } + + // add a .nomedia file + try { + OutputStream dst = new FileOutputStream(baseDir + "Minetest/.nomedia"); + dst.close(); + } catch (IOException e) { + Log.e("MinetestAssetCopy","Failed to create .nomedia file"); + e.printStackTrace(); + } + + + // 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 + { + String filename = m_tocopy.get(i); + publishProgress(i); + + boolean asset_size_unknown = false; + long filesize = -1; + + if (m_asset_size_unknown.contains(filename)) + { + File testme = new File(baseDir + "/" + filename); + + if(testme.exists()) + { + filesize = testme.length(); + } + asset_size_unknown = true; + } + + InputStream src; + try + { + src = getAssets().open(filename); + } catch (IOException e) { + Log.e("MinetestAssetCopy","Copying file: " + filename + " FAILED (not in assets)"); + e.printStackTrace(); + continue; + } + + // Transfer bytes from in to out + byte[] buf = new byte[1*1024]; + int len = src.read(buf, 0, 1024); + + /* following handling is crazy but we need to deal with */ + /* 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)) + { + src.close(); + continue; + } + + if (len == buf.length) + { + src.close(); + long size = getFullSize(filename); + if ( size == filesize) + { + continue; + } + src = getAssets().open(filename); + len = src.read(buf, 0, 1024); + } + } + if (len > 0) + { + int total_filesize = 0; + OutputStream dst; + try + { + dst = new FileOutputStream(baseDir + "/" + filename); + } catch (IOException e) { + Log.e("MinetestAssetCopy","Copying file: " + baseDir + + "/" + filename + " FAILED (couldn't open output file)"); + e.printStackTrace(); + src.close(); + continue; + } + dst.write(buf, 0, len); + total_filesize += len; + + while ((len = src.read(buf)) > 0) + { + dst.write(buf, 0, len); + total_filesize += len; + } + + dst.close(); + Log.v("MinetestAssetCopy","Copied file: " + + m_tocopy.get(i) + " (" + total_filesize + + " bytes)"); + } + else if (len < 0) + { + Log.e("MinetestAssetCopy","Copying file: " + + m_tocopy.get(i) + " failed, size < 0"); + } + src.close(); + } + catch (IOException e) + { + Log.e("MinetestAssetCopy","Copying file: " + + m_tocopy.get(i) + " failed"); + e.printStackTrace(); + } + } + return ""; + } + + + /** + * update progress bar + */ + protected void onProgressUpdate(Integer... progress) + { + + if (m_copy_started) + { + boolean shortened = false; + String todisplay = m_tocopy.get(progress[0]); + m_ProgressBar.setProgress(progress[0]); + m_Filename.setText(todisplay); + } + else + { + boolean shortened = false; + String todisplay = m_Foldername; + String full_text = "scanning " + todisplay + " ..."; + m_Filename.setText(full_text); + } + } + + /** + * 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; + } +} diff --git a/build/android/src/main/java/net.minetest.minetest/MinetestTextEntry.java b/build/android/src/main/java/net.minetest.minetest/MinetestTextEntry.java new file mode 100644 index 000000000..68dc73274 --- /dev/null +++ b/build/android/src/main/java/net.minetest.minetest/MinetestTextEntry.java @@ -0,0 +1,91 @@ +package net.minetest.minetest; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.text.InputType; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnKeyListener; +import android.widget.EditText; + +public class MinetestTextEntry extends Activity { + public AlertDialog mTextInputDialog; + public EditText mTextInputWidget; + + private final int MultiLineTextInput = 1; + private final int SingleLineTextInput = 2; + private final int SingleLinePasswordInput = 3; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Bundle b = getIntent().getExtras(); + String acceptButton = b.getString("EnterButton"); + String hint = b.getString("hint"); + String current = b.getString("current"); + int editType = b.getInt("editType"); + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + mTextInputWidget = new EditText(this); + mTextInputWidget.setHint(hint); + mTextInputWidget.setText(current); + mTextInputWidget.setMinWidth(300); + if (editType == SingleLinePasswordInput) { + mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT | + InputType.TYPE_TEXT_VARIATION_PASSWORD); + } + else { + mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT); + } + + + builder.setView(mTextInputWidget); + + if (editType == MultiLineTextInput) { + builder.setPositiveButton(acceptButton, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) + { pushResult(mTextInputWidget.getText().toString()); } + }); + } + + builder.setOnCancelListener(new DialogInterface.OnCancelListener() { + public void onCancel(DialogInterface dialog) { + cancelDialog(); + } + }); + + mTextInputWidget.setOnKeyListener(new OnKeyListener() { + @Override + public boolean onKey(View view, int KeyCode, KeyEvent event) { + if ( KeyCode == KeyEvent.KEYCODE_ENTER){ + + pushResult(mTextInputWidget.getText().toString()); + return true; + } + return false; + } + }); + + mTextInputDialog = builder.create(); + mTextInputDialog.show(); + } + + public void pushResult(String text) { + Intent resultData = new Intent(); + resultData.putExtra("text", text); + setResult(Activity.RESULT_OK,resultData); + mTextInputDialog.dismiss(); + finish(); + } + + public void cancelDialog() { + setResult(Activity.RESULT_CANCELED); + mTextInputDialog.dismiss(); + finish(); + } +} diff --git a/build/android/src/main/java/net.minetest.minetest/MtNativeActivity.java b/build/android/src/main/java/net.minetest.minetest/MtNativeActivity.java new file mode 100644 index 000000000..3173a71f4 --- /dev/null +++ b/build/android/src/main/java/net.minetest.minetest/MtNativeActivity.java @@ -0,0 +1,104 @@ +package net.minetest.minetest; + +import android.app.NativeActivity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.WindowManager; + +public class MtNativeActivity extends NativeActivity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + m_MessagReturnCode = -1; + m_MessageReturnValue = ""; + + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public void onBackPressed() { + } + + + public void copyAssets() { + Intent intent = new Intent(this, MinetestAssetCopy.class); + startActivity(intent); + } + + public void showDialog(String acceptButton, String hint, String current, + int editType) { + + Intent intent = new Intent(this, MinetestTextEntry.class); + Bundle params = new Bundle(); + params.putString("acceptButton", acceptButton); + params.putString("hint", hint); + params.putString("current", current); + params.putInt("editType", editType); + intent.putExtras(params); + startActivityForResult(intent, 101); + m_MessageReturnValue = ""; + m_MessagReturnCode = -1; + } + + public static native void putMessageBoxResult(String text); + + /* ugly code to workaround putMessageBoxResult not beeing found */ + public int getDialogState() { + return m_MessagReturnCode; + } + + public String getDialogValue() { + m_MessagReturnCode = -1; + return m_MessageReturnValue; + } + + public float getDensity() { + return getResources().getDisplayMetrics().density; + } + + public int getDisplayWidth() { + return getResources().getDisplayMetrics().widthPixels; + } + + public int getDisplayHeight() { + return getResources().getDisplayMetrics().heightPixels; + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, + Intent data) { + if (requestCode == 101) { + if (resultCode == RESULT_OK) { + String text = data.getStringExtra("text"); + m_MessagReturnCode = 0; + m_MessageReturnValue = text; + } + else { + m_MessagReturnCode = 1; + } + } + } + + static { + System.loadLibrary("openal"); + System.loadLibrary("ogg"); + System.loadLibrary("vorbis"); + System.loadLibrary("ssl"); + System.loadLibrary("crypto"); + System.loadLibrary("gmp"); + System.loadLibrary("iconv"); + + // We don't have to load libminetest.so ourselves, + // but if we do, we get nicer logcat errors when + // loading fails. + System.loadLibrary("minetest"); + } + + private int m_MessagReturnCode; + private String m_MessageReturnValue; +} diff --git a/build/android/src/main/res/drawable-hdpi/irr_icon.png b/build/android/src/main/res/drawable-hdpi/irr_icon.png Binary files differnew file mode 100644 index 000000000..0b6861a0d --- /dev/null +++ b/build/android/src/main/res/drawable-hdpi/irr_icon.png diff --git a/build/android/src/main/res/drawable-ldpi/irr_icon.png b/build/android/src/main/res/drawable-ldpi/irr_icon.png Binary files differnew file mode 100644 index 000000000..b8c5d0177 --- /dev/null +++ b/build/android/src/main/res/drawable-ldpi/irr_icon.png diff --git a/build/android/src/main/res/drawable-mdpi/irr_icon.png b/build/android/src/main/res/drawable-mdpi/irr_icon.png Binary files differnew file mode 100644 index 000000000..951a7f8c1 --- /dev/null +++ b/build/android/src/main/res/drawable-mdpi/irr_icon.png diff --git a/build/android/src/main/res/drawable-xhdpi/irr_icon.png b/build/android/src/main/res/drawable-xhdpi/irr_icon.png Binary files differnew file mode 100644 index 000000000..2ec528ef7 --- /dev/null +++ b/build/android/src/main/res/drawable-xhdpi/irr_icon.png diff --git a/build/android/src/main/res/layout/assetcopy.xml b/build/android/src/main/res/layout/assetcopy.xml new file mode 100644 index 000000000..1fcfffd65 --- /dev/null +++ b/build/android/src/main/res/layout/assetcopy.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" > + + <ProgressBar + android:id="@+id/progressBar1" + style="?android:attr/progressBarStyleHorizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" /> + + <TextView + android:id="@+id/textView1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="middle" + android:singleLine="true" + android:layout_gravity="center_horizontal" + android:text="@string/preparing_media" + android:textAppearance="?android:attr/textAppearanceSmall" /> + +</LinearLayout> diff --git a/build/android/src/main/res/values/strings.xml b/build/android/src/main/res/values/strings.xml new file mode 100644 index 000000000..b407a77c6 --- /dev/null +++ b/build/android/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="preparing_media">Preparing media...</string> +</resources> + diff --git a/build/android/src/main/res/values/styles.xml b/build/android/src/main/res/values/styles.xml new file mode 100644 index 000000000..25b8df5a3 --- /dev/null +++ b/build/android/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <style name="Theme.Transparent" parent="android:Theme"> + <item name="android:windowIsTranslucent">true</item> + <item name="android:windowBackground">@android:color/transparent</item> + <item name="android:windowContentOverlay">@null</item> + <item name="android:windowNoTitle">true</item> + <item name="android:windowIsFloating">true</item> + <item name="android:backgroundDimEnabled">false</item> + </style> +</resources>
\ No newline at end of file |