diff --git a/CMakeLists.txt b/CMakeLists.txt index ea8fe9a6a..8dfca113d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,15 +14,14 @@ set(CMAKE_CXX_STANDARD 11) # Also remember to set PROTOCOL_VERSION in network/networkprotocol.h when releasing set(VERSION_MAJOR 1) -set(VERSION_MINOR 1) -set(VERSION_PATCH 10) -set(VERSION_TWEAK 0) +set(VERSION_MINOR 2) +set(VERSION_PATCH 0) set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string") # Change to false for releases set(DEVELOPMENT_BUILD FALSE) -set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_TWEAK}") +set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") if(VERSION_EXTRA) set(VERSION_STRING ${VERSION_STRING}-${VERSION_EXTRA}) elseif(DEVELOPMENT_BUILD) diff --git a/build/android/Makefile b/build/android/Makefile index d9ddd2db2..991a3c5ba 100644 --- a/build/android/Makefile +++ b/build/android/Makefile @@ -70,14 +70,14 @@ VORBIS_TIMESTAMP = $(VORBIS_DIR)/timestamp VORBIS_TIMESTAMP_INT = $(ANDR_ROOT)/deps/vorbis_timestamp VORBIS_URL_GIT = https://github.com/MoNTE48/libvorbis-android -IRRLICHT_COMMIT = 990d475fbbb2653c95b992937906eb49960d02fb +IRRLICHT_COMMIT = 237eb07bf4b6957f2e103adcaf835e6a2afe3486 IRRLICHT_DIR = $(ANDR_ROOT)/deps/irrlicht IRRLICHT_LIB = $(IRRLICHT_DIR)/lib/Android/libIrrlicht.a IRRLICHT_TIMESTAMP = $(IRRLICHT_DIR)/timestamp IRRLICHT_TIMESTAMP_INT = $(ANDR_ROOT)/deps/irrlicht_timestamp IRRLICHT_URL_HTTP = https://github.com/zaki/irrlicht/archive/$(IRRLICHT_COMMIT).zip -CURL_VERSION = 7.64.0 +CURL_VERSION = 7.64.1 CURL_DIR = $(ANDR_ROOT)/deps/curl CURL_LIB = $(CURL_DIR)/lib/.libs/libcurl.a CURL_TIMESTAMP = $(CURL_DIR)/timestamp @@ -89,10 +89,9 @@ FREETYPE_DIR = $(ANDR_ROOT)/deps/freetype FREETYPE_LIB = $(FREETYPE_DIR)/objs/.libs/libfreetype.a FREETYPE_TIMESTAMP = $(FREETYPE_DIR)/timestamp FREETYPE_TIMESTAMP_INT = $(ANDR_ROOT)/deps/freetype_timestamp -FREETYPE_URL_HTTP = https://sourceforge.net/projects/freetype/files/freetype2/2.10.0/freetype-$(FREETYPE_VERSION).tar.bz2 +FREETYPE_URL_HTTP = https://sourceforge.net/projects/freetype/files/freetype2/$(FREETYPE_VERSION)/freetype-$(FREETYPE_VERSION).tar.bz2 - -ICONV_VERSION = 1.15 +ICONV_VERSION = 1.16 ICONV_DIR = $(ANDR_ROOT)/deps/libiconv ICONV_URL_HTTP = https://ftp.gnu.org/pub/gnu/libiconv/libiconv-$(ICONV_VERSION).tar.gz diff --git a/build/android/build.gradle b/build/android/build.gradle index 2d0f8e194..7bf66c533 100644 --- a/build/android/build.gradle +++ b/build/android/build.gradle @@ -1,18 +1,19 @@ buildscript { - repositories { - maven { url 'https://maven.google.com' } - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.3.1' - } + repositories { + maven { url 'https://maven.google.com' } + jcenter() + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.4.0' + } } allprojects { - repositories { - maven { url 'https://maven.google.com' } - jcenter() - } + repositories { + maven { url 'https://maven.google.com' } + jcenter() + } } apply plugin: 'com.android.application' @@ -20,12 +21,12 @@ android { compileSdkVersion 28 buildToolsVersion "28.0.3" - defaultConfig { - applicationId 'mobi.MultiCraft' - minSdkVersion 16 - targetSdkVersion 28 - versionCode 114 - } + defaultConfig { + applicationId 'com.multicraft.game' + minSdkVersion 16 + targetSdkVersion 28 + versionCode 1 + } Properties props = new Properties() props.load(new FileInputStream(file("local.properties"))) @@ -39,23 +40,23 @@ android { } } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' signingConfig signingConfigs.release } } } // for multiple APKs - splits { - abi { - enable true - reset() - include "armeabi-v7a", "x86" - //include 'armeabi-v7a', 'arm64-v8a', 'x86' - } - } + splits { + abi { + enable true + reset() + include "armeabi-v7a", "x86" + //include 'armeabi-v7a', 'arm64-v8a', 'x86' + } + } } // build multiple APKs for all ABI @@ -64,16 +65,21 @@ ext.abiCodes = ['armeabi-v7a': 0, 'x86': 1] import com.android.build.OutputFile android.applicationVariants.all { variant -> - variant.outputs.each { output -> - def baseAbiVersionCode = - project.ext.abiCodes.get(output.getFilter(OutputFile.ABI)) - if (baseAbiVersionCode != null) { - output.versionCodeOverride = - baseAbiVersionCode + variant.versionCode - } - } + variant.outputs.each { output -> + def baseAbiVersionCode = + project.ext.abiCodes.get(output.getFilter(OutputFile.ABI)) + if (baseAbiVersionCode != null) { + output.versionCodeOverride = + baseAbiVersionCode + variant.versionCode + } + } } dependencies { - implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.crashlytics.sdk.android:crashlytics:2.10.0' + // Third-party libraries + implementation 'com.itlgl:iosdialog:1.0.0' + implementation 'gun0912.ted:tedpermission:2.2.2' + implementation 'org.apache.commons:commons-io:1.3.2' } diff --git a/build/android/gradle/wrapper/gradle-wrapper.properties b/build/android/gradle/wrapper/gradle-wrapper.properties index 3746a29b7..718635d43 100644 --- a/build/android/gradle/wrapper/gradle-wrapper.properties +++ b/build/android/gradle/wrapper/gradle-wrapper.properties @@ -1,2 +1,2 @@ -#Fri Feb 22 20:02:06 CET 2019 -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip +#Mon Apr 22 16:21:42 CEST 2019 +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip diff --git a/build/android/src/main/AndroidManifest.xml b/build/android/src/main/AndroidManifest.xml index e77a820f3..f4d7ac3c9 100644 --- a/build/android/src/main/AndroidManifest.xml +++ b/build/android/src/main/AndroidManifest.xml @@ -1,22 +1,43 @@ - + + + + + + + android:label="@string/app_name" + android:networkSecurityConfig="@xml/network_security_config" + android:resizeableActivity="false" + tools:ignore="GoogleAppIndexingWarning"> + + + + @@ -26,7 +47,7 @@ - + \ No newline at end of file diff --git a/build/android/src/main/java/com/multicraft/game/AlertDialogHelper.java b/build/android/src/main/java/com/multicraft/game/AlertDialogHelper.java new file mode 100644 index 000000000..1e6f58a9b --- /dev/null +++ b/build/android/src/main/java/com/multicraft/game/AlertDialogHelper.java @@ -0,0 +1,109 @@ +package com.multicraft.game; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.graphics.drawable.Drawable; +import android.view.ContextThemeWrapper; + + +public class AlertDialogHelper { + private DialogsCallback sCallback = null; + private Drawable icon = null; + private String title = null; + private CharSequence message = null; + private String buttonPositive = null; + private String buttonNegative = null; + private String buttonNeutral = null; + private Activity activity; + + AlertDialogHelper(Activity activity) { + this.activity = activity; + } + + private Drawable getIcon() { + return icon; + } + + public void setIcon(Drawable icon) { + this.icon = icon; + } + + private String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + private CharSequence getMessage() { + return message; + } + + void setMessage(CharSequence message) { + this.message = message; + } + + private String getButtonPositive() { + return buttonPositive; + } + + void setButtonPositive(String buttonPositive) { + this.buttonPositive = buttonPositive; + } + + private String getButtonNegative() { + return buttonNegative; + } + + void setButtonNegative(String buttonNegative) { + this.buttonNegative = buttonNegative; + } + + private String getButtonNeutral() { + return buttonNeutral; + } + + void setButtonNeutral(String buttonNeutral) { + this.buttonNeutral = buttonNeutral; + } + + void setListener(DialogsCallback callback) { + sCallback = callback; + } + + void showAlert(final String source) { + ContextThemeWrapper ctw = new ContextThemeWrapper(activity, R.style.CustomLollipopDialogStyle); + AlertDialog.Builder builder = new AlertDialog.Builder(ctw); + if (getIcon() != null) builder.setIcon(getIcon()); + if (getTitle() != null) builder.setTitle(getTitle()); + if (getMessage() != null) builder.setMessage(getMessage()); + if (getButtonPositive() != null) + builder.setPositiveButton(getButtonPositive(), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + sCallback.onPositive(source); + } + }); + if (getButtonNegative() != null) + builder.setNegativeButton(getButtonNegative(), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + sCallback.onNegative(source); + } + }); + if (getButtonNeutral() != null) + builder.setNeutralButton(getButtonNeutral(), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + sCallback.onNeutral(source); + } + }); + builder.setCancelable(false); + final AlertDialog dialog = builder.create(); + if (!activity.isFinishing()) { + dialog.show(); + } + } +} diff --git a/build/android/src/main/java/mobi/MultiCraft/CallBackListener.java b/build/android/src/main/java/com/multicraft/game/CallBackListener.java similarity index 84% rename from build/android/src/main/java/mobi/MultiCraft/CallBackListener.java rename to build/android/src/main/java/com/multicraft/game/CallBackListener.java index 9cbd67dad..85f199021 100644 --- a/build/android/src/main/java/mobi/MultiCraft/CallBackListener.java +++ b/build/android/src/main/java/com/multicraft/game/CallBackListener.java @@ -1,5 +1,4 @@ -package mobi.MultiCraft; - +package com.multicraft.game; public interface CallBackListener { void updateViews(int text, int textVisibility, int progressVisibility); diff --git a/build/android/src/main/java/mobi/MultiCraft/CheckConnectionTask.java b/build/android/src/main/java/com/multicraft/game/CheckConnectionTask.java similarity index 87% rename from build/android/src/main/java/mobi/MultiCraft/CheckConnectionTask.java rename to build/android/src/main/java/com/multicraft/game/CheckConnectionTask.java index c0ec0bf57..5a0b1684d 100644 --- a/build/android/src/main/java/mobi/MultiCraft/CheckConnectionTask.java +++ b/build/android/src/main/java/com/multicraft/game/CheckConnectionTask.java @@ -1,8 +1,9 @@ -package mobi.MultiCraft; +package com.multicraft.game; import android.content.Context; import android.os.AsyncTask; -import android.util.Log; + +import com.crashlytics.android.Crashlytics; import java.io.IOException; import java.lang.ref.WeakReference; @@ -42,9 +43,9 @@ public class CheckConnectionTask extends AsyncTask { urlc.setRequestProperty("Connection", "close"); urlc.setConnectTimeout(timeout); urlc.connect(); - return urlc.getResponseCode() == 204 && urlc.getContentLength() == 0; + return urlc.getResponseCode() == HttpURLConnection.HTTP_NO_CONTENT && urlc.getContentLength() == 0; } catch (IOException e) { - Log.e("WTF", "IOException " + e.getMessage()); + Crashlytics.logException(e); } return false; } @@ -54,4 +55,3 @@ public class CheckConnectionTask extends AsyncTask { isGoogleAvailable("http://g.cn/generate_204", 1000); } } - diff --git a/build/android/src/main/java/com/multicraft/game/CopyZipTask.java b/build/android/src/main/java/com/multicraft/game/CopyZipTask.java new file mode 100644 index 000000000..6381376a3 --- /dev/null +++ b/build/android/src/main/java/com/multicraft/game/CopyZipTask.java @@ -0,0 +1,139 @@ +package com.multicraft.game; + +import android.app.Activity; +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.AsyncTask; +import android.view.View; + +import com.crashlytics.android.Crashlytics; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.ref.WeakReference; + +import static com.multicraft.game.MainActivity.unzipLocation; + +public class CopyZipTask extends AsyncTask implements DialogsCallback { + + private WeakReference contextRef; + private CallBackListener listener; + private boolean isCancel = false; + + CopyZipTask(Context context) { + contextRef = new WeakReference<>(context); + } + + protected String[] doInBackground(String... params) { + while (!isCancel) { + copyAssets(params); + } + return params; + } + + @Override + protected void onPostExecute(String[] result) { + listener.updateViews(R.string.loading, View.VISIBLE, View.GONE); + startUnzipService(result); + + } + + private void copyAsset(String zipName) throws IOException { + String filename = zipName.substring(zipName.lastIndexOf("/") + 1); + InputStream in; + OutputStream out; + in = contextRef.get().getAssets().open(filename); + out = new FileOutputStream(zipName); + copyFile(in, out); + in.close(); + out.flush(); + out.close(); + } + + private void copyAssets(String[] zips) { + try { + for (String zipName : zips) { + copyAsset(zipName); + } + isCancel = true; + } catch (IOException e) { + Crashlytics.logException(e); + isCancel = true; + cancel(true); + if (e.getMessage().contains("ENOSPC")) { + showRestartDialog("ENOSPC"); + } else { + showRestartDialog("UKNWN"); + } + } + } + + private void copyFile(InputStream in, OutputStream out) throws IOException { + byte[] buffer = new byte[1024]; + int read; + while ((read = in.read(buffer)) != -1) { + out.write(buffer, 0, read); + } + } + + private void showRestartDialog(final String source) { + String message; + if ("ENOSPC".equals(source)) { + message = contextRef.get().getString(R.string.no_space); + } else { + message = contextRef.get().getString(R.string.restart); + } + final AlertDialogHelper dialogHelper = new AlertDialogHelper((Activity) contextRef.get()); + dialogHelper.setListener(this); + dialogHelper.setMessage(message); + dialogHelper.setButtonPositive(contextRef.get().getString(android.R.string.ok)); + ((Activity) contextRef.get()).runOnUiThread(new Runnable() { + @Override + public void run() { + dialogHelper.showAlert(source); + } + }); + } + + private void startUnzipService(String[] file) { + // Start MyIntentService + Intent intentMyIntentService = new Intent(contextRef.get(), UnzipService.class); + intentMyIntentService.putExtra(UnzipService.EXTRA_KEY_IN_FILE, file); + intentMyIntentService.putExtra(UnzipService.EXTRA_KEY_IN_LOCATION, unzipLocation); + contextRef.get().startService(intentMyIntentService); + + } + + private void restartApp() { + Context context = contextRef.get().getApplicationContext(); + Intent intent = new Intent(context, MainActivity.class); + int mPendingIntentId = 1337; + PendingIntent mPendingIntent = PendingIntent.getActivity(context, mPendingIntentId, intent, PendingIntent.FLAG_CANCEL_CURRENT); + AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + mgr.set(AlarmManager.RTC, System.currentTimeMillis(), mPendingIntent); + System.exit(0); + } + + void setListener(CallBackListener listener) { + this.listener = listener; + } + + @Override + public void onPositive(String source) { + restartApp(); + } + + @Override + public void onNegative(String source) { + + } + + @Override + public void onNeutral(String source) { + + } +} \ No newline at end of file diff --git a/build/android/src/main/java/mobi/MultiCraft/DeleteTask.java b/build/android/src/main/java/com/multicraft/game/DeleteTask.java similarity index 78% rename from build/android/src/main/java/mobi/MultiCraft/DeleteTask.java rename to build/android/src/main/java/com/multicraft/game/DeleteTask.java index 383d35c55..eca4c8992 100644 --- a/build/android/src/main/java/mobi/MultiCraft/DeleteTask.java +++ b/build/android/src/main/java/com/multicraft/game/DeleteTask.java @@ -1,9 +1,12 @@ -package mobi.MultiCraft; +package com.multicraft.game; import android.os.AsyncTask; -import android.util.Log; import android.view.View; +import com.crashlytics.android.Crashlytics; + +import org.apache.commons.io.FileUtils; + import java.io.File; import java.io.IOException; @@ -37,12 +40,10 @@ public class DeleteTask extends AsyncTask { private void deleteFiles(String path) { File file = new File(path); if (file.exists()) { - String deleteCmd = "rm -r " + path; - Runtime runtime = Runtime.getRuntime(); try { - runtime.exec(deleteCmd); + FileUtils.deleteDirectory(file); } catch (IOException e) { - Log.e("WTF", "delete files failed: " + e.getLocalizedMessage()); + Crashlytics.logException(e); } } } diff --git a/build/android/src/main/java/mobi/MultiCraft/DialogsCallback.java b/build/android/src/main/java/com/multicraft/game/DialogsCallback.java similarity index 63% rename from build/android/src/main/java/mobi/MultiCraft/DialogsCallback.java rename to build/android/src/main/java/com/multicraft/game/DialogsCallback.java index 16a7a9fd4..cc68ecb50 100644 --- a/build/android/src/main/java/mobi/MultiCraft/DialogsCallback.java +++ b/build/android/src/main/java/com/multicraft/game/DialogsCallback.java @@ -1,9 +1,9 @@ -package mobi.MultiCraft; +package com.multicraft.game; public interface DialogsCallback { void onPositive(String source); void onNegative(String source); - void onCancelled(String source); + void onNeutral(String source); } diff --git a/build/android/src/main/java/mobi/MultiCraft/GameActivity.java b/build/android/src/main/java/com/multicraft/game/GameActivity.java similarity index 65% rename from build/android/src/main/java/mobi/MultiCraft/GameActivity.java rename to build/android/src/main/java/com/multicraft/game/GameActivity.java index 5f6ea9150..d1b9e62b5 100644 --- a/build/android/src/main/java/mobi/MultiCraft/GameActivity.java +++ b/build/android/src/main/java/com/multicraft/game/GameActivity.java @@ -1,20 +1,33 @@ -package mobi.MultiCraft; +package com.multicraft.game; +import android.annotation.SuppressLint; +import android.app.ActivityManager; import android.app.NativeActivity; +import android.content.Context; import android.content.Intent; +import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.view.View; import android.view.WindowManager; +import com.crashlytics.android.Crashlytics; + +/*import static com.multicraft.game.AdManager.initAd; +import static com.multicraft.game.AdManager.setAdsCallback; +import static com.multicraft.game.AdManager.startAd; +import static com.multicraft.game.AdManager.stopAd;*/ + public class GameActivity extends NativeActivity { static { System.loadLibrary("MultiCraft"); + //System.loadLibrary("c++_shared"); } private int messageReturnCode; private String messageReturnValue; private int height, width; + private boolean consent; public static native void putMessageBoxResult(String text); @@ -24,14 +37,13 @@ public class GameActivity extends NativeActivity { Bundle bundle = getIntent().getExtras(); height = bundle != null ? bundle.getInt("height", 0) : getResources().getDisplayMetrics().heightPixels; width = bundle != null ? bundle.getInt("width", 0) : getResources().getDisplayMetrics().widthPixels; - // pf = PreferencesHelper.getInstance(this); - // if (pf.isAdsEnabled()) setAdsCallbacks(this); + consent = bundle == null || bundle.getBoolean("consent", true); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); messageReturnCode = -1; messageReturnValue = ""; + new AdInitTask().execute(); } - public void makeFullScreen() { if (Build.VERSION.SDK_INT >= 19) { this.getWindow().getDecorView().setSystemUiVisibility( @@ -51,10 +63,8 @@ public class GameActivity extends NativeActivity { @Override protected void onRestart() { super.onRestart(); - /*if (pf.isAdsEnabled()) { - stopAd(); - startAd(this, false); - }*/ + /*stopAd(); + startAd(this, false);*/ } @Override @@ -66,8 +76,7 @@ public class GameActivity extends NativeActivity { @Override protected void onStop() { super.onStop(); - /*if (pf.isAdsEnabled()) - stopAd();*/ + /*stopAd();*/ } @Override @@ -123,4 +132,42 @@ public class GameActivity extends NativeActivity { return width; } -} \ No newline at end of file + public int getMemoryMax() { + ActivityManager actManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); + ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo(); + if (actManager != null) { + actManager.getMemoryInfo(memInfo); + return (int) Math.floor(memInfo.totalMem / 1024 * 1024 * 1024 * 1.0); + } else { + Crashlytics.log(1, "RAM", "Cannot get RAM"); + return 1; + } + + } + + public void notifyServerConnect(boolean isMultiplayer) { + } + + public void notifyAbortLoading() { + + } + + public void notifyExitGame() { + } + + @SuppressLint("StaticFieldLeak") + class AdInitTask extends AsyncTask { + + @Override + protected Void doInBackground(Void... voids) { + /*initAd(GameActivity.this, consent);*/ + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + /*setAdsCallback(GameActivity.this);*/ + } + } + +} diff --git a/build/android/src/main/java/mobi/MultiCraft/InputDialogActivity.java b/build/android/src/main/java/com/multicraft/game/InputDialogActivity.java similarity index 99% rename from build/android/src/main/java/mobi/MultiCraft/InputDialogActivity.java rename to build/android/src/main/java/com/multicraft/game/InputDialogActivity.java index 67c64fba9..5c3e3b6ab 100644 --- a/build/android/src/main/java/mobi/MultiCraft/InputDialogActivity.java +++ b/build/android/src/main/java/com/multicraft/game/InputDialogActivity.java @@ -1,4 +1,4 @@ -package mobi.MultiCraft; +package com.multicraft.game; import android.annotation.SuppressLint; import android.app.Activity; @@ -16,6 +16,7 @@ import android.view.View.OnKeyListener; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; + public class InputDialogActivity extends Activity { private AlertDialog alertDialog; @@ -81,4 +82,4 @@ public class InputDialogActivity extends Activity { ); } } -} \ No newline at end of file +} diff --git a/build/android/src/main/java/mobi/MultiCraft/MainActivity.java b/build/android/src/main/java/com/multicraft/game/MainActivity.java similarity index 60% rename from build/android/src/main/java/mobi/MultiCraft/MainActivity.java rename to build/android/src/main/java/com/multicraft/game/MainActivity.java index e4d44f5b3..be2f71e4f 100644 --- a/build/android/src/main/java/mobi/MultiCraft/MainActivity.java +++ b/build/android/src/main/java/com/multicraft/game/MainActivity.java @@ -1,6 +1,6 @@ -package mobi.MultiCraft; +package com.multicraft.game; -import android.Manifest; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; @@ -15,15 +15,14 @@ import android.graphics.Bitmap; import android.graphics.Point; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.os.Handler; import android.provider.Settings; -import android.support.annotation.NonNull; -import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.text.method.LinkMovementMethod; -import android.util.Log; import android.view.ContextThemeWrapper; import android.view.Display; import android.view.LayoutInflater; @@ -35,37 +34,43 @@ import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; +import com.crashlytics.android.Crashlytics; +import com.gun0912.tedpermission.PermissionListener; +import com.gun0912.tedpermission.TedPermission; + +import org.apache.commons.io.FileUtils; + import java.io.File; import java.io.IOException; import java.util.Arrays; +import java.util.List; +import static android.Manifest.permission.ACCESS_COARSE_LOCATION; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; - -import static mobi.MultiCraft.PreferencesHelper.TAG_BUILD_NUMBER; -import static mobi.MultiCraft.PreferencesHelper.TAG_CONSENT_ASKED; -import static mobi.MultiCraft.PreferencesHelper.TAG_LAUNCH_TIMES; -import static mobi.MultiCraft.PreferencesHelper.TAG_SHORTCUT_CREATED; +import static com.multicraft.game.PreferencesHelper.TAG_BUILD_NUMBER; +import static com.multicraft.game.PreferencesHelper.TAG_CONSENT_ASKED; +import static com.multicraft.game.PreferencesHelper.TAG_COPY_WORLDS; +import static com.multicraft.game.PreferencesHelper.TAG_LAUNCH_TIMES; +import static com.multicraft.game.PreferencesHelper.TAG_SHORTCUT_CREATED; public class MainActivity extends Activity implements WVersionManager.ActivityListener, CallBackListener, DialogsCallback { public final static int REQUEST_CODE = 104; - private final static String TAG = "Error"; private final static String CREATE_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT"; - private final static String FILES = Environment.getExternalStorageDirectory() + "/Files.zip"; - private final static String WORLDS = Environment.getExternalStorageDirectory() + "/worlds.zip"; - private final static String GAMES = Environment.getExternalStorageDirectory() + "/games.zip"; + private final static String EXTERNAL_STORAGE = Environment.getExternalStorageDirectory().toString(); + private final static String FILES = EXTERNAL_STORAGE + "/Files.zip"; + private final static String WORLDS = EXTERNAL_STORAGE + "/worlds.zip"; + private final static String GAMES = EXTERNAL_STORAGE + "/games.zip"; private final static String NOMEDIA = ".nomedia"; - private final static int COARSE_LOCATION_RESULT = 100; - private final static int WRITE_EXTERNAL_RESULT = 101; - private final static int ALL_PERMISSIONS_RESULT = 102; - private static final String UPDATE_LINK = "https://raw.githubusercontent.com/MoNTE48/MultiCraft-links/master/ver.txt"; + private static final String UPDATE_LINK = "https://raw.githubusercontent.com/ubulem/coronahtml5/master/ver.txt"; private static final String[] EU_COUNTRIES = new String[]{ "AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "GB", "IS", "LI", "NO"}; - private static String dataFolder = "/Android/data/mobi.MultiCraft/files/"; - public static String unzipLocation = Environment.getExternalStorageDirectory() + dataFolder; + private static String dataFolder = "/Android/data/com.multicraft.game/files/"; + public static String unzipLocation = EXTERNAL_STORAGE + dataFolder; + private static String worldPath = EXTERNAL_STORAGE + "/Android/data/mobi.MultiCraft/files/worlds"; private int height, width; private boolean consent; private ProgressBar mProgressBar; @@ -73,8 +78,6 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi private TextView mLoading; private ImageView iv; private WVersionManager versionManager = null; - private ConnectionDialogListener connListener; - private PermissionManager pm = null; private PreferencesHelper pf; private BroadcastReceiver myReceiver = new BroadcastReceiver() { @Override @@ -84,10 +87,15 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi progress = intent.getIntExtra(UnzipService.ACTION_PROGRESS, 0); } if (progress >= 0) { - mProgressBar.setVisibility(View.VISIBLE); - mProgressBar.setProgress(progress); + if (mProgressBar != null) { + mProgressBar.setVisibility(View.VISIBLE); + mProgressBar.setProgress(progress); + } } else { createNomedia(); + File folder = new File(worldPath); + if (folder.exists() && !pf.isWorldsCopied()) + copyWorldsToNewFolder(); runGame(); } } @@ -107,7 +115,7 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi return; } addLaunchTimes(); - getPermissions(); + askStoragePermissions(); } @Override @@ -123,6 +131,17 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi } //helpful utilities + private void copyWorldsToNewFolder() { + File source = new File(worldPath); + File dest = new File(unzipLocation + "worlds"); + try { + FileUtils.copyDirectory(source, dest); + pf.saveSettings(TAG_COPY_WORLDS, true); + } catch (IOException e) { + Crashlytics.logException(e); + } + } + private void addLaunchTimes() { int i = pf.getLaunchTimes(); i++; @@ -149,7 +168,7 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi try { myFile.createNewFile(); } catch (IOException e) { - Log.e(TAG, "nomedia has not been created: " + e.getMessage()); + Crashlytics.logException(e); } } @@ -179,7 +198,7 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi addIntent.setAction(CREATE_SHORTCUT); getApplicationContext().sendBroadcast(addIntent); } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Shortcut cannot be created"); + Crashlytics.logException(e); } } @@ -231,7 +250,7 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi } private void askGdpr() { - if (pf.isAskConsent() && isGdprSubject() && pf.isAdsEnabled()) + if (pf.isAskConsent() && isGdprSubject()) showGdprDialog(); else { consent = true; @@ -240,74 +259,149 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi } private void init() { - RateMe.onStart(this); - if (pf.isCreateShortcut() && Build.VERSION.SDK_INT < 26) - addShortcut(); mProgressBar = findViewById(R.id.PB1); mProgressBarIndeterminate = findViewById(R.id.PB2); mLoading = findViewById(R.id.tv_progress_circle); Drawable draw = ContextCompat.getDrawable(this, R.drawable.custom_progress_bar); mProgressBar.setProgressDrawable(draw); - connListener = new ConnectionDialogListener(); + RateMe.onStart(this); + if (pf.isCreateShortcut() && Build.VERSION.SDK_INT < 26) + addShortcut(); createDataFolder(); checkAppVersion(); } //permission block - private void getPermissions() { - pm = new PermissionManager(this); - String[] permList = pm.requestPermissions(); - if (permList.length > 0) { - ActivityCompat.requestPermissions(this, permList, ALL_PERMISSIONS_RESULT); - } else { - askGdpr(); - } + private void askStoragePermissions() { + PermissionListener permissionlistener = new PermissionListener() { + @Override + public void onPermissionGranted() { + if (pf.getLaunchTimes() % 3 == 1) { + askLocationPermissions(); + } else askGdpr(); + } + + @Override + public void onPermissionDenied(List deniedPermissions) { + if (TedPermission.canRequestPermission(MainActivity.this, WRITE_EXTERNAL_STORAGE)) + askStorageRationalePermissions(); + else askStorageWhenDoNotShow(); + } + }; + TedPermission.with(this) + .setPermissionListener(permissionlistener) + .setPermissions(WRITE_EXTERNAL_STORAGE) + .check(); } - private void requestPermissionAfterExplain() { - Toast.makeText(this, R.string.explain, Toast.LENGTH_LONG).show(); - ActivityCompat.requestPermissions(MainActivity.this, - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_RESULT); + //storage permissions block + private void askStorageRationalePermissions() { + PermissionListener permissionlistener = new PermissionListener() { + @Override + public void onPermissionGranted() { + if (pf.getLaunchTimes() % 3 == 1) { + askLocationPermissions(); + } else askGdpr(); + } + + @Override + public void onPermissionDenied(List deniedPermissions) { + finish(); + } + }; + TedPermission.with(this) + .setPermissionListener(permissionlistener) + .setPermissions(WRITE_EXTERNAL_STORAGE) + .setRationaleMessage(R.string.explain) + .setDeniedMessage(R.string.denied) + .setDeniedCloseButtonText(R.string.close_game) + .setGotoSettingButtonText(R.string.settings) + .check(); } - private void requestStoragePermission() { - if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - requestPermissionAfterExplain(); - } else { - ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - WRITE_EXTERNAL_RESULT); - } + private void askStorageWhenDoNotShow() { + PermissionListener permissionlistener = new PermissionListener() { + @Override + public void onPermissionGranted() { + if (pf.getLaunchTimes() % 3 == 1) { + askLocationPermissions(); + } else askGdpr(); + } + + @Override + public void onPermissionDenied(List deniedPermissions) { + finish(); + } + }; + TedPermission.with(this) + .setPermissionListener(permissionlistener) + .setPermissions(WRITE_EXTERNAL_STORAGE) + .setDeniedMessage(R.string.denied) + .setDeniedCloseButtonText(R.string.close_game) + .setGotoSettingButtonText(R.string.settings) + .check(); } - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, - @NonNull int[] grantResults) { - switch (requestCode) { - case WRITE_EXTERNAL_RESULT: - if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - askGdpr(); - } else { - requestStoragePermission(); - } - break; - case COARSE_LOCATION_RESULT: - break; - case ALL_PERMISSIONS_RESULT: - for (String perms : PermissionManager.permissionsToRequest) { - if (!pm.hasPermission(perms)) { - PermissionManager.permissionsRejected.add(perms); - } - } - if (PermissionManager.permissionsRejected.size() == 0) { - askGdpr(); - } else if (!Arrays.asList(PermissionManager.permissionsRejected.toArray()).contains(WRITE_EXTERNAL_STORAGE)) { - Toast.makeText(this, R.string.location, Toast.LENGTH_SHORT).show(); - askGdpr(); - } else { - requestStoragePermission(); - } - break; - } + //location permissions block + private void askLocationPermissions() { + PermissionListener permissionlistener = new PermissionListener() { + @Override + public void onPermissionGranted() { + askGdpr(); + } + + @Override + public void onPermissionDenied(List deniedPermissions) { + if (TedPermission.canRequestPermission(MainActivity.this, ACCESS_COARSE_LOCATION)) + askLocationRationalePermissions(); + else askLocationWhenDoNotShow(); + } + }; + TedPermission.with(this) + .setPermissionListener(permissionlistener) + .setPermissions(ACCESS_COARSE_LOCATION) + .check(); + } + + private void askLocationRationalePermissions() { + PermissionListener permissionlistener = new PermissionListener() { + @Override + public void onPermissionGranted() { + askGdpr(); + } + + @Override + public void onPermissionDenied(List deniedPermissions) { + askGdpr(); + } + }; + TedPermission.with(this) + .setPermissionListener(permissionlistener) + .setPermissions(ACCESS_COARSE_LOCATION) + .setRationaleMessage(R.string.location) + .check(); + } + + private void askLocationWhenDoNotShow() { + PermissionListener permissionlistener = new PermissionListener() { + @Override + public void onPermissionGranted() { + if (pf.getLaunchTimes() % 3 == 1) { + askLocationPermissions(); + } else askGdpr(); + } + + @Override + public void onPermissionDenied(List deniedPermissions) { + askGdpr(); + } + }; + TedPermission.with(this) + .setPermissionListener(permissionlistener) + .setPermissions(ACCESS_COARSE_LOCATION) + .setDeniedMessage(R.string.location) + .setGotoSettingButtonText(R.string.settings) + .check(); } //game logic @@ -317,8 +411,7 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi RateMe.showRateDialog(); RateMe.setListener(this); } else { - // startBillingActivity(); - startNative(); + getNativeResolutionAndStart(); } } @@ -339,26 +432,34 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi } + private void getNativeResolutionAndStart() { + getDefaultResolution(); + startNative(); + } + private void runGame() { deleteZip(FILES, WORLDS, GAMES); pf.saveSettings(TAG_BUILD_NUMBER, getString(R.string.ver)); - CheckConnectionTask cct = new CheckConnectionTask(this); + final CheckConnectionTask cct = new CheckConnectionTask(this); cct.setListener(this); cct.execute(); + Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + if (cct.getStatus() == AsyncTask.Status.RUNNING) { + cct.cancel(true); + onEvent("CheckConnectionTask", "false"); + } + } + }, 2500); } - /*private void startBillingActivity() { - Intent intent = new Intent(this, BillingActivity.class); - startActivityForResult(intent, REQUEST_CODE); - }*/ - private void startNative() { - /*if (pf.isAdsEnabled()) { - initAd(MainActivity.this, consent); - }*/ Intent intent = new Intent(this, GameActivity.class); intent.putExtra("height", height); intent.putExtra("width", width); + intent.putExtra("consent", consent); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); } @@ -375,8 +476,7 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - getDefaultResolution(); - startNative(); + getNativeResolutionAndStart(); } private void prepareToRun(boolean isAll) { @@ -385,12 +485,12 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi if (isAll) { dt.execute(unzipLocation); } else { - dt.execute(unzipLocation + "builtin", unzipLocation + "games", unzipLocation + "textures", unzipLocation + "debug.txt"); + dt.execute(unzipLocation + "builtin", unzipLocation + "games", unzipLocation + "textures"/*, unzipLocation + "debug.txt"*/); } } private void checkAppVersion() { - if (!pf.isRestored() && pf.getBuildNumber().equals(getString(R.string.ver))) { + if (pf.getBuildNumber().equals(getString(R.string.ver))) { addImageView(1); runGame(); } else if (pf.getBuildNumber().equals("0")) { @@ -433,7 +533,7 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi ContextThemeWrapper ctw = new ContextThemeWrapper(this, R.style.CustomLollipopDialogStyle); AlertDialog.Builder builder = new AlertDialog.Builder(ctw); LayoutInflater inflater = getLayoutInflater(); - View dialogView = inflater.inflate(R.layout.gdpr_dialog, null); + @SuppressLint("InflateParams") View dialogView = inflater.inflate(R.layout.gdpr_dialog, null); builder.setView(dialogView) .setPositiveButton(R.string.gdpr_agree, new DialogInterface.OnClickListener() { @Override @@ -463,26 +563,21 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi } void showConnectionDialog() { - ContextThemeWrapper ctw = new ContextThemeWrapper(this, R.style.CustomLollipopDialogStyle); - AlertDialog.Builder builder = new AlertDialog.Builder(ctw); - builder.setMessage(getString(R.string.conn_message)); - - builder.setPositiveButton(getString(R.string.conn_wifi), connListener); - builder.setNegativeButton(getString(R.string.conn_mobile), connListener); - builder.setNeutralButton(getString(R.string.ignore), connListener); - - builder.setCancelable(false); - - AlertDialog dialog = builder.create(); - if (!isFinishing()) { - dialog.show(); - } + AlertDialogHelper dialogHelper = new AlertDialogHelper(this); + dialogHelper.setListener(this); + dialogHelper.setMessage(getString(R.string.conn_message)); + dialogHelper.setButtonPositive(getString(R.string.conn_wifi)); + dialogHelper.setButtonNegative(getString(R.string.conn_mobile)); + dialogHelper.setButtonNeutral(getString(R.string.ignore)); + dialogHelper.showAlert("ConnectionDialog"); } @Override public void onPositive(String source) { if ("RateMe".equals(source)) { finish(); + } else if ("ConnectionDialog".equals(source)) { + startActivityForResult(new Intent(Settings.ACTION_WIFI_SETTINGS), REQUEST_CODE); } else { versionManager.updateNow(versionManager.getUpdateUrl()); finish(); @@ -493,8 +588,9 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi public void onNegative(String source) { if ("RateMe".equals(source)) { Toast.makeText(MainActivity.this, R.string.sad, Toast.LENGTH_LONG).show(); - // startBillingActivity(); - startNative(); + getNativeResolutionAndStart(); + } else if ("ConnectionDialog".equals(source)) { + startActivityForResult(new Intent(Settings.ACTION_WIRELESS_SETTINGS), REQUEST_CODE); } else { versionManager.ignoreThisVersion(); checkRateDialog(); @@ -502,32 +598,15 @@ public class MainActivity extends Activity implements WVersionManager.ActivityLi } @Override - public void onCancelled(String source) { + public void onNeutral(String source) { if ("RateMe".equals(source)) { - // startBillingActivity(); - startNative(); + getNativeResolutionAndStart(); + } else if ("ConnectionDialog".equals(source)) { + getNativeResolutionAndStart(); } else { versionManager.remindMeLater(versionManager.getReminderTimer()); checkRateDialog(); } } - private class ConnectionDialogListener implements DialogInterface.OnClickListener { - - @Override - public void onClick(DialogInterface dialog, int which) { - switch (which) { - case AlertDialog.BUTTON_POSITIVE: - startActivityForResult(new Intent(Settings.ACTION_WIFI_SETTINGS), REQUEST_CODE); - break; - case AlertDialog.BUTTON_NEUTRAL: - getDefaultResolution(); - startNative(); - break; - case AlertDialog.BUTTON_NEGATIVE: - startActivityForResult(new Intent(Settings.ACTION_WIRELESS_SETTINGS), REQUEST_CODE); - break; - } - } - } -} \ No newline at end of file +} diff --git a/build/android/src/main/java/mobi/MultiCraft/PreferencesHelper.java b/build/android/src/main/java/com/multicraft/game/PreferencesHelper.java similarity index 81% rename from build/android/src/main/java/mobi/MultiCraft/PreferencesHelper.java rename to build/android/src/main/java/com/multicraft/game/PreferencesHelper.java index 129e8ee1f..4c2ca74cb 100644 --- a/build/android/src/main/java/mobi/MultiCraft/PreferencesHelper.java +++ b/build/android/src/main/java/com/multicraft/game/PreferencesHelper.java @@ -1,4 +1,4 @@ -package mobi.MultiCraft; +package com.multicraft.game; import android.content.Context; import android.content.SharedPreferences; @@ -8,11 +8,12 @@ class PreferencesHelper { static final String TAG_BUILD_NUMBER = "buildNumber"; static final String TAG_LAUNCH_TIMES = "launchTimes"; static final String TAG_CONSENT_ASKED = "consentAsked"; - static final String TAG_RESTORE_BACKUP = "restoredFromBackup"; + static final String TAG_COPY_WORLDS = "copyWorlds"; static final String IS_LOADED = "interstitialLoaded"; static final String RV_LOADED = "rewardedVideoLoaded"; + static final String ADS_DELAY = "adsDelay"; + static final String ADS_REPEAT = "adsRepeat"; private static final String SETTINGS = "MultiCraftSettings"; - private static final String TAG_DISABLED_ADS = "disabledADS"; private static PreferencesHelper instance; private static SharedPreferences sharedPreferences; @@ -49,26 +50,26 @@ class PreferencesHelper { return sharedPreferences.getBoolean(TAG_CONSENT_ASKED, true); } - boolean isRestored() { - return sharedPreferences.getBoolean(TAG_RESTORE_BACKUP, false); - } - - boolean isAdsEnabled() { - return !sharedPreferences.getBoolean(TAG_DISABLED_ADS, false); + boolean isWorldsCopied() { + return sharedPreferences.getBoolean(TAG_COPY_WORLDS, true); } String getBuildNumber() { return sharedPreferences.getString(TAG_BUILD_NUMBER, "0"); } - void savePurchase(boolean v) { - sharedPreferences.edit().putBoolean(TAG_DISABLED_ADS, v).apply(); - } - int getLaunchTimes() { return sharedPreferences.getInt(TAG_LAUNCH_TIMES, 0); } + int getAdsDelay() { + return sharedPreferences.getInt(ADS_DELAY, 10); + } + + int getAdsRepeat() { + return sharedPreferences.getInt(ADS_REPEAT, 300); + } + void saveSettings(String tag, boolean bool) { sharedPreferences.edit().putBoolean(tag, bool).apply(); } @@ -81,4 +82,4 @@ class PreferencesHelper { sharedPreferences.edit().putInt(tag, value).apply(); } -} \ No newline at end of file +} diff --git a/build/android/src/main/java/mobi/MultiCraft/RateMe.java b/build/android/src/main/java/com/multicraft/game/RateMe.java similarity index 97% rename from build/android/src/main/java/mobi/MultiCraft/RateMe.java rename to build/android/src/main/java/com/multicraft/game/RateMe.java index 54c16a700..8952f1d3e 100644 --- a/build/android/src/main/java/mobi/MultiCraft/RateMe.java +++ b/build/android/src/main/java/com/multicraft/game/RateMe.java @@ -1,4 +1,4 @@ -package mobi.MultiCraft; +package com.multicraft.game; import android.app.Activity; import android.app.Dialog; @@ -20,7 +20,7 @@ import java.util.Date; class RateMe { - private static final int INSTALL_DAYS = 2; + private static final int INSTALL_DAYS = 3; private static final int LAUNCH_TIMES = 3; private static final boolean DEBUG = false; private static final String TAG = RateMe.class.getSimpleName(); @@ -91,7 +91,7 @@ class RateMe { ratingBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() { @Override public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) { - if (rating >= 3) { + if (rating >= 4) { if (sCallback != null) { sCallback.onPositive("RateMe"); } @@ -113,7 +113,7 @@ class RateMe { @Override public void onCancel(DialogInterface dialog) { if (sCallback != null) { - sCallback.onCancelled("RateMe"); + sCallback.onNeutral("RateMe"); } clearSharedPreferences(activity); } @@ -169,4 +169,4 @@ class RateMe { } } -} \ No newline at end of file +} diff --git a/build/android/src/main/java/mobi/MultiCraft/Transliteration.java b/build/android/src/main/java/com/multicraft/game/Transliteration.java similarity index 97% rename from build/android/src/main/java/mobi/MultiCraft/Transliteration.java rename to build/android/src/main/java/com/multicraft/game/Transliteration.java index 8b5ad1b5b..a1173c73b 100644 --- a/build/android/src/main/java/mobi/MultiCraft/Transliteration.java +++ b/build/android/src/main/java/com/multicraft/game/Transliteration.java @@ -1,4 +1,4 @@ -package mobi.MultiCraft; +package com.multicraft.game; class Transliteration { @@ -56,7 +56,7 @@ class Transliteration { * Не русские символы останутся прежними. */ static String toLatin(String text) { - char charBuffer[] = text.toCharArray(); + char[] charBuffer = text.toCharArray(); StringBuilder sb = new StringBuilder(text.length()); for (char symbol : charBuffer) { int i = symbol - START_CHAR; diff --git a/build/android/src/main/java/mobi/MultiCraft/UnzipService.java b/build/android/src/main/java/com/multicraft/game/UnzipService.java similarity index 65% rename from build/android/src/main/java/mobi/MultiCraft/UnzipService.java rename to build/android/src/main/java/com/multicraft/game/UnzipService.java index dce70fa7e..8fa240512 100644 --- a/build/android/src/main/java/mobi/MultiCraft/UnzipService.java +++ b/build/android/src/main/java/com/multicraft/game/UnzipService.java @@ -1,4 +1,4 @@ -package mobi.MultiCraft; +package com.multicraft.game; import android.app.IntentService; import android.app.Notification; @@ -7,9 +7,9 @@ import android.app.NotificationManager; import android.content.Context; import android.content.Intent; import android.os.Build; -import android.util.Log; -import java.io.BufferedInputStream; +import com.crashlytics.android.Crashlytics; + import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -26,17 +26,24 @@ public class UnzipService extends IntentService { public static final String ACTION_PROGRESS = "progress"; private NotificationManager mNotifyManager; private int id = 1; - private int percent = 0; - private int size; public UnzipService() { - super("mobi.MultiCraft.UnzipService"); + super("com.multicraft.game.UnzipService"); } + private void isDir(String dir, String unzipLocation) { + File f = new File(unzipLocation + dir); + + if (!f.isDirectory()) { + f.mkdirs(); + } + } + + @Override protected void onHandleIntent(Intent intent) { createNotification(); - unzipLoop(intent); + unzip(intent); } @@ -78,51 +85,44 @@ public class UnzipService extends IntentService { mNotifyManager.notify(id, builder.build()); } - private void unzipLoop(Intent intent) { - String[] zips = intent.getStringArrayExtra(EXTRA_KEY_IN_FILE); + private void unzip(Intent intent) { + String[] file = intent.getStringArrayExtra(EXTRA_KEY_IN_FILE); String location = intent.getStringExtra(EXTRA_KEY_IN_LOCATION); - size = getSummarySize(zips); - try { - for (String z : zips) { - unzipFile(z, location); - } - } catch (IOException e) { - Log.e("WTF", e.getMessage() == null ? "Unzip failed" : e.getMessage()); - } - } - - @SuppressWarnings("TryFinallyCanBeTryWithResources") - private void unzipFile(String zipFile, String targetDirectory) throws IOException { - ZipInputStream zis = new ZipInputStream( - new BufferedInputStream(new FileInputStream(zipFile))); - try { - ZipEntry ze; - int count; - byte[] buffer = new byte[8192]; - while ((ze = zis.getNextEntry()) != null) { - File file = new File(targetDirectory, ze.getName()); - File dir = ze.isDirectory() ? file : file.getParentFile(); - if (!dir.isDirectory() && !dir.mkdirs()) - throw new FileNotFoundException("Failed to ensure directory: " + - dir.getAbsolutePath()); - if (ze.isDirectory()) { - percent++; - continue; - } - FileOutputStream fileOutputStream = new FileOutputStream(file); + int per = 0; + int size = getSummarySize(file); + for (String f : file) { + try { try { - while ((count = zis.read(buffer)) != -1) { - fileOutputStream.write(buffer, 0, count); - percent++; - int progress = 100 * percent / size; - publishProgress(progress); + FileInputStream fin = new FileInputStream(f); + ZipInputStream zin = new ZipInputStream(fin); + ZipEntry ze; + while ((ze = zin.getNextEntry()) != null) { + if (ze.isDirectory()) { + per++; + isDir(ze.getName(), location); + } else { + per++; + int progress = 100 * per / size; + // send update + publishProgress(progress); + FileOutputStream f_out = new FileOutputStream(location + ze.getName()); + byte[] buffer = new byte[8192]; + int len; + while ((len = zin.read(buffer)) != -1) { + f_out.write(buffer, 0, len); + } + f_out.close(); + zin.closeEntry(); + f_out.close(); + } } - } finally { - fileOutputStream.close(); + zin.close(); + } catch (FileNotFoundException e) { + Crashlytics.logException(e); } + } catch (IOException e) { + Crashlytics.logException(e); } - } finally { - zis.close(); } } @@ -139,7 +139,7 @@ public class UnzipService extends IntentService { ZipFile zipSize = new ZipFile(z); size += zipSize.size(); } catch (IOException e) { - Log.e("WTF", e.getMessage() == null ? "Unzip failed" : e.getMessage()); + Crashlytics.logException(e); } } return size; @@ -151,4 +151,4 @@ public class UnzipService extends IntentService { mNotifyManager.cancel(id); publishProgress(-1); } -} \ No newline at end of file +} diff --git a/build/android/src/main/java/mobi/MultiCraft/WVersionManager.java b/build/android/src/main/java/com/multicraft/game/WVersionManager.java similarity index 72% rename from build/android/src/main/java/mobi/MultiCraft/WVersionManager.java rename to build/android/src/main/java/com/multicraft/game/WVersionManager.java index f3b55e622..16ca7903b 100644 --- a/build/android/src/main/java/mobi/MultiCraft/WVersionManager.java +++ b/build/android/src/main/java/com/multicraft/game/WVersionManager.java @@ -1,9 +1,8 @@ -package mobi.MultiCraft; +package com.multicraft.game; +import android.annotation.SuppressLint; import android.app.Activity; -import android.app.AlertDialog; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; @@ -13,8 +12,8 @@ import android.os.AsyncTask; import android.preference.PreferenceManager; import android.text.Editable; import android.text.Html; -import android.util.Log; -import android.view.ContextThemeWrapper; + +import com.crashlytics.android.Crashlytics; import org.json.JSONException; import org.json.JSONObject; @@ -31,8 +30,8 @@ import java.net.URL; import java.util.Calendar; import java.util.Locale; -class WVersionManager { - private static final String TAG = "WVersionManager"; + +class WVersionManager implements DialogsCallback { private DialogsCallback sCallback = null; private CustomTagHandler customTagHandler; private String PREF_IGNORE_VERSION_CODE = "w.ignore.version.code"; @@ -42,21 +41,14 @@ class WVersionManager { private Drawable icon; private String title; private String message; - private String updateNowLabel; - private String remindMeLaterLabel; - private String ignoreThisVersionLabel; private String updateUrl; private String versionContentUrl; - private int reminderTimer; private int mVersionCode; - private AlertDialogButtonListener listener; - private boolean mDialogCancelable = false; private ActivityListener al; WVersionManager(Activity act) { this.activity = act; al = (ActivityListener) act; - this.listener = new AlertDialogButtonListener(); this.customTagHandler = new CustomTagHandler(); setLaunchTimes(); } @@ -72,7 +64,7 @@ class WVersionManager { void checkVersion() { String versionContentUrl = getVersionContentUrl(); if (versionContentUrl == null) { - Log.e(TAG, "Please set versionContentUrl first"); + Crashlytics.log("Please set versionContentUrl first"); return; } @@ -89,22 +81,15 @@ class WVersionManager { } void showDialog() { - ContextThemeWrapper ctw = new ContextThemeWrapper(activity, R.style.CustomLollipopDialogStyle); - AlertDialog.Builder builder = new AlertDialog.Builder(ctw); - builder.setIcon(getIcon()); - builder.setTitle(getTitle()); - builder.setMessage(Html.fromHtml(getMessage(), null, getCustomTagHandler())); - - builder.setPositiveButton(getUpdateNowLabel(), listener); - builder.setNeutralButton(getRemindMeLaterLabel(), listener); - builder.setNegativeButton(getIgnoreThisVersionLabel(), listener); - - builder.setCancelable(isDialogCancelable()); - - AlertDialog dialog = builder.create(); - if (activity != null && !activity.isFinishing()) { - dialog.show(); - } + AlertDialogHelper dialogHelper = new AlertDialogHelper(activity); + dialogHelper.setListener(this); + dialogHelper.setIcon(getIcon()); + dialogHelper.setTitle(getTitle()); + dialogHelper.setMessage(Html.fromHtml(getMessage(), null, getCustomTagHandler())); + dialogHelper.setButtonPositive(getUpdateNowLabel()); + dialogHelper.setButtonNeutral(getRemindMeLaterLabel()); + dialogHelper.setButtonNegative(getIgnoreThisVersionLabel()); + dialogHelper.showAlert("WVersionManager"); } private void setLaunchTimes() { @@ -115,27 +100,15 @@ class WVersionManager { } private String getUpdateNowLabel() { - return updateNowLabel != null ? updateNowLabel : activity.getString(R.string.update); - } - - public void setUpdateNowLabel(String updateNowLabel) { - this.updateNowLabel = updateNowLabel; + return activity.getString(R.string.update); } private String getRemindMeLaterLabel() { - return remindMeLaterLabel != null ? remindMeLaterLabel : activity.getString(R.string.later); - } - - public void setRemindMeLaterLabel(String remindMeLaterLabel) { - this.remindMeLaterLabel = remindMeLaterLabel; + return activity.getString(R.string.later); } private String getIgnoreThisVersionLabel() { - return ignoreThisVersionLabel != null ? ignoreThisVersionLabel : activity.getString(R.string.ignore); - } - - public void setIgnoreThisVersionLabel(String ignoreThisVersionLabel) { - this.ignoreThisVersionLabel = ignoreThisVersionLabel; + return activity.getString(R.string.ignore); } private String getMessage() { @@ -181,13 +154,7 @@ class WVersionManager { } int getReminderTimer() { - return reminderTimer > 0 ? reminderTimer : 1; - } - - public void setReminderTimer(int minutes) { - if (minutes > 0) { - reminderTimer = minutes; - } + return 1; } void updateNow(String url) { @@ -197,7 +164,7 @@ class WVersionManager { Intent intent = new Intent(Intent.ACTION_VIEW, uri); activity.startActivity(intent); } catch (Exception e) { - Log.e(TAG, "is update url correct?" + e); + Crashlytics.logException(e); } } @@ -255,43 +222,26 @@ class WVersionManager { return customTagHandler; } - private boolean isDialogCancelable() { - return mDialogCancelable; + @Override + public void onPositive(String source) { + sCallback.onPositive("WVersionManager"); } - public void setDialogCancelable(boolean dialogCancelable) { - mDialogCancelable = dialogCancelable; + @Override + public void onNegative(String source) { + sCallback.onNegative("WVersionManager"); + } + + @Override + public void onNeutral(String source) { + sCallback.onNeutral("WVersionManager"); } interface ActivityListener { void isShowUpdateDialog(boolean flag); } - private class AlertDialogButtonListener implements DialogInterface.OnClickListener { - - @Override - public void onClick(DialogInterface dialog, int which) { - switch (which) { - case AlertDialog.BUTTON_POSITIVE: - if (sCallback != null) { - sCallback.onPositive("WVersionManager"); - } - break; - case AlertDialog.BUTTON_NEUTRAL: - if (sCallback != null) { - sCallback.onCancelled("WVersionManager"); - } - remindMeLater(getReminderTimer()); - break; - case AlertDialog.BUTTON_NEGATIVE: - if (sCallback != null) { - sCallback.onNegative("WVersionManager"); - } - break; - } - } - } - + @SuppressLint("StaticFieldLeak") private class VersionContentRequest extends AsyncTask { Context context; @@ -316,22 +266,22 @@ class WVersionManager { result = bo.toString(); bo.close(); } catch (MalformedURLException e) { - Log.e("WTF", "Malformed content: " + e.getMessage()); + Crashlytics.logException(e); } catch (ProtocolException e) { - Log.e("WTF", "Protocol error: " + e.getMessage()); + Crashlytics.logException(e); } catch (IOException e) { - Log.e("WTF", "IO error: " + e.getMessage()); + Crashlytics.logException(e); } return result; } @Override protected void onPostExecute(String result) { + PreferencesHelper pf = PreferencesHelper.getInstance(activity); mVersionCode = 0; - String content; - String packageName; if (result != null) { try { + String content; if (!result.startsWith("{")) { // for response who append with unknown char result = result.substring(1); } @@ -345,8 +295,12 @@ class WVersionManager { } else { content = json.optString("content_en"); } - packageName = json.optString("package"); + String packageName = json.optString("package"); setUpdateUrl("market://details?id=" + packageName); + int adsDelay = json.optInt("ads_delay"); + int adsRepeat = json.optInt("ads_repeat"); + pf.saveSettings(PreferencesHelper.ADS_DELAY, adsDelay); + pf.saveSettings(PreferencesHelper.ADS_REPEAT, adsRepeat); int currentVersionCode = getCurrentVersionCode(); if (currentVersionCode < mVersionCode) { if (mVersionCode != getIgnoreVersionCode()) { @@ -364,10 +318,10 @@ class WVersionManager { al.isShowUpdateDialog(false); } } catch (JSONException e) { - Log.e(TAG, "is your server response have valid json format?"); + Crashlytics.logException(e); al.isShowUpdateDialog(false); } catch (Exception e) { - Log.e(TAG, e.toString()); + Crashlytics.logException(e); al.isShowUpdateDialog(false); } } else { @@ -391,4 +345,4 @@ class WVersionManager { } } } -} \ No newline at end of file +} diff --git a/build/android/src/main/java/mobi/MultiCraft/CopyZipTask.java b/build/android/src/main/java/mobi/MultiCraft/CopyZipTask.java deleted file mode 100644 index 37939fa10..000000000 --- a/build/android/src/main/java/mobi/MultiCraft/CopyZipTask.java +++ /dev/null @@ -1,82 +0,0 @@ -package mobi.MultiCraft; - -import android.content.Context; -import android.content.Intent; -import android.os.AsyncTask; -import android.util.Log; -import android.view.View; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.ref.WeakReference; - -import static mobi.MultiCraft.MainActivity.unzipLocation; - - -public class CopyZipTask extends AsyncTask { - - private WeakReference contextRef; - private CallBackListener listener; - private String[] zips; - - CopyZipTask(Context context) { - contextRef = new WeakReference<>(context); - } - - @Override - protected String doInBackground(String... params) { - zips = params; - for (String s : zips) { - copyAssets(s); - } - return "Done"; - - } - - - @Override - protected void onPostExecute(String result) { - listener.updateViews(R.string.loading, View.VISIBLE, View.GONE); - startUnzipService(zips); - - } - - private void copyAssets(String zipName) { - String filename = zipName.substring(zipName.lastIndexOf("/") + 1); - InputStream in; - OutputStream out; - try { - in = contextRef.get().getAssets().open(filename); - out = new FileOutputStream(zipName); - copyFile(in, out); - in.close(); - out.flush(); - out.close(); - } catch (IOException e) { - Log.e("WTF", "Failed to copy asset file: " + e.getMessage()); - } - } - - private void copyFile(InputStream in, OutputStream out) throws IOException { - byte[] buffer = new byte[1024]; - int read; - while ((read = in.read(buffer)) != -1) { - out.write(buffer, 0, read); - } - } - - private void startUnzipService(String[] file) { - // Start MyIntentService - Intent intentMyIntentService = new Intent(contextRef.get(), UnzipService.class); - intentMyIntentService.putExtra(UnzipService.EXTRA_KEY_IN_FILE, file); - intentMyIntentService.putExtra(UnzipService.EXTRA_KEY_IN_LOCATION, unzipLocation); - contextRef.get().startService(intentMyIntentService); - - } - - void setListener(CallBackListener listener) { - this.listener = listener; - } -} diff --git a/build/android/src/main/java/mobi/MultiCraft/PermissionManager.java b/build/android/src/main/java/mobi/MultiCraft/PermissionManager.java deleted file mode 100644 index 4e1d65fda..000000000 --- a/build/android/src/main/java/mobi/MultiCraft/PermissionManager.java +++ /dev/null @@ -1,88 +0,0 @@ -package mobi.MultiCraft; - -import android.app.Activity; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.preference.PreferenceManager; -import android.support.v4.app.ActivityCompat; - -import java.util.ArrayList; - -import static android.Manifest.permission.ACCESS_COARSE_LOCATION; -import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; -import static mobi.MultiCraft.PreferencesHelper.TAG_RESTORE_BACKUP; - -class PermissionManager { - static ArrayList permissionsToRequest; - static ArrayList permissionsRejected; - private Activity activity; - private SharedPreferences sharedPreferences; - private PreferencesHelper pf; - - PermissionManager(Activity activity) { - this.activity = activity; - pf = PreferencesHelper.getInstance(activity); - sharedPreferences = PreferenceManager.getDefaultSharedPreferences(activity); - } - - String[] requestPermissions() { - ArrayList permissions = new ArrayList<>(); - permissions.add(WRITE_EXTERNAL_STORAGE); - permissions.add(ACCESS_COARSE_LOCATION); - //filter out the permissions we have already accepted - permissionsToRequest = findUnAskedPermissions(permissions); - //get the permissions we have asked for before but are not granted.. - //we will store this in a global list to access later. - permissionsRejected = findRejectedPermissions(permissions); - if (permissionsToRequest.size() > 0) {//we need to ask for permissions - for (String perm : permissionsToRequest) { - markAsAsked(perm); - } - return permissionsToRequest.toArray(new String[permissionsToRequest.size()]); - } else if (permissionsRejected.size() > 0 && pf.getLaunchTimes() % 3 == 0) { - return permissionsRejected.toArray(new String[permissionsRejected.size()]); - } - return new String[]{}; - } - - boolean hasPermission(String permission) { - return ActivityCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED; - } - - private boolean shouldWeAsk(String permission) { - if (pf.getLaunchTimes() > 1 && permission.equals(WRITE_EXTERNAL_STORAGE)) { - sharedPreferences.edit().clear().apply(); - pf.saveSettings(TAG_RESTORE_BACKUP, true); - } - return sharedPreferences.getBoolean(permission, true); - } - - private void markAsAsked(String permission) { - sharedPreferences.edit().putBoolean(permission, false).apply(); - } - - private ArrayList findUnAskedPermissions(ArrayList wanted) { - ArrayList result = new ArrayList<>(); - - for (String perm : wanted) { - if (!hasPermission(perm) && shouldWeAsk(perm)) { - result.add(perm); - } - } - - return result; - } - - private ArrayList findRejectedPermissions(ArrayList wanted) { - ArrayList result = new ArrayList<>(); - - for (String perm : wanted) { - if (!hasPermission(perm) && !shouldWeAsk(perm)) { - result.add(perm); - } - } - - return result; - } -} - diff --git a/build/android/src/main/res/layout/input_dialog.xml b/build/android/src/main/res/layout/input_dialog.xml index 9d0bd3335..786510487 100644 --- a/build/android/src/main/res/layout/input_dialog.xml +++ b/build/android/src/main/res/layout/input_dialog.xml @@ -2,4 +2,4 @@ \ No newline at end of file + android:layout_height="50dp" /> \ No newline at end of file diff --git a/build/android/src/main/res/layout/rate_dialog.xml b/build/android/src/main/res/layout/rate_dialog.xml index b8d2be228..ddc1ebbb7 100644 --- a/build/android/src/main/res/layout/rate_dialog.xml +++ b/build/android/src/main/res/layout/rate_dialog.xml @@ -35,9 +35,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end" + android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" - android:layout_marginTop="16dp" android:background="@android:color/transparent" android:enabled="false" android:text="@string/rate_submit" diff --git a/build/android/src/main/res/values-ru/strings.xml b/build/android/src/main/res/values-ru/strings.xml index 78a196da8..49c798d1b 100644 --- a/build/android/src/main/res/values-ru/strings.xml +++ b/build/android/src/main/res/values-ru/strings.xml @@ -6,33 +6,30 @@ Загрузка… Загрузка MultiCraft Осталось меньше минуты… + Произошла ошибка, игра будет перезапущена автоматически + Недостаточно места для записи файлов игры, пожалуйста освободите место SD карте - Для корректной работы, игре требуется разрешение записывать в память устройтсва. + Разрешение на запись необходимо для распаковки текстур и игровых файлов. Доступ к местоположению обеспечивает Вам лучшее взаимодействие с игрой + Закрыть игру + Настройки + Вы не можете использовать MultiCraft без разрешения на запись. \nПожалуйста, включите его в [Настройки] -> [Разрешения]> Оцените MultiCraft! Название - ОЦЕНИТЬ Описание + ОЦЕНИТЬ Нам жаль, что Вам не понравилась игра! - Загрузка рекомендаций \n для Вас \n%1$s Игнорировать Позже Обновить - Сообщение - - - Супер предложение! - Полностью отключите рекламу \n и активируйте Pro-режим со скидкой 75%! - Закрыть - Отключить рекламу! Для полноценной игры, MultiCraft требует подключение к интернету.\nВ противном случае невозможно обновление игры, а так же не доступен мультиплеер! Wi-Fi 3G/4G - \ No newline at end of file + diff --git a/build/android/src/main/res/values/strings.xml b/build/android/src/main/res/values/strings.xml index 5f2f7ea6c..6e710644c 100644 --- a/build/android/src/main/res/values/strings.xml +++ b/build/android/src/main/res/values/strings.xml @@ -2,24 +2,28 @@ MultiCraft - 1.1.11.6 + 1.2 Preparing to update… Loading… Loading MultiCraft Less than 1 minute… + Unexpected issue, the game will be restarted automatically + No space left for game files, please free space on SD card - Game need permission to write files to storage memory. + Storage permissions is necessary to unpack textures and game data. Location permission provide you better interaction with game + Close game + App settings + You cannot use MultiCraft without storage permission. \nPlease turn on it at [Settings] -> [Permissions]> Please, rate MultiCraft! Title - SUBMIT Description + SUBMIT We are sorry that you did not like the game! - Loading recommendations \n for you \n %1$s Update @@ -27,13 +31,6 @@ Ignore - Message - - - Special Offer! - Only for 0.99$ \nDisable ads forever \nand activate Pro features! - Close - Disable Ads! MultiCraft requires an internet connection to use all game features.\nOtherwise, you will not get updates and multiplayer will be not available! @@ -44,4 +41,5 @@ We care about your privacy and data security. We keep this app free by showing ads.\n\nCan we continue to use your data to tailor ads for you?\n\nOur partners will collect data and use a unique identifier on your device to show you ads. By agreeing, you confirm that you are 16 years old. You can learn how we and our partners collect and use data on\nPrivacy Policy. Agree Disagree + \ No newline at end of file diff --git a/build/android/src/main/res/xml/network_security_config.xml b/build/android/src/main/res/xml/network_security_config.xml new file mode 100644 index 000000000..f18e1f040 --- /dev/null +++ b/build/android/src/main/res/xml/network_security_config.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/games/default/files/default/textures/default_snowball.png b/games/default/files/default/textures/default_snowball.png index ed79dbb7b..183cd3467 100644 Binary files a/games/default/files/default/textures/default_snowball.png and b/games/default/files/default/textures/default_snowball.png differ