diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
index 7dea86961..4cc1c0016 100644
--- a/.github/workflows/android.yml
+++ b/.github/workflows/android.yml
@@ -24,10 +24,10 @@ jobs:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- - name: Set up JDK 1.8
+ - name: Set up JDK 11
uses: actions/setup-java@v1
with:
- java-version: 1.8
+ java-version: '11'
- name: Install GNU gettext
run: sudo apt install gettext
- name: Build with Gradle
@@ -35,10 +35,10 @@ jobs:
- name: Save armeabi artifact
uses: actions/upload-artifact@v2
with:
- name: Minetest-armeabi-v7a.apk
+ name: MultiCraft-armeabi-v7a.apk
path: build/android/app/build/outputs/apk/release/app-armeabi-v7a-release-unsigned.apk
- name: Save arm64 artifact
uses: actions/upload-artifact@v2
with:
- name: Minetest-arm64-v8a.apk
+ name: MultiCraft-arm64-v8a.apk
path: build/android/app/build/outputs/apk/release/app-arm64-v8a-release-unsigned.apk
diff --git a/build/android/app/build.gradle b/build/android/app/build.gradle
index 6f0ba6e21..1c4b83e07 100644
--- a/build/android/app/build.gradle
+++ b/build/android/app/build.gradle
@@ -1,16 +1,16 @@
apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+
android {
- compileSdkVersion 29
- buildToolsVersion '30.0.3'
- ndkVersion '22.0.7026061'
+ compileSdkVersion 31
+ buildToolsVersion '31.0.0'
+ ndkVersion '23.1.7779620'
defaultConfig {
applicationId 'com.multicraft.game'
- minSdkVersion 16
- //noinspection OldTargetApi
- targetSdkVersion 29
+ minSdkVersion 19
+ targetSdkVersion 31
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
versionCode project.versionCode
- multiDexEnabled true
}
// load properties
@@ -55,6 +55,10 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
+
+ buildFeatures {
+ viewBinding true
+ }
}
import com.android.build.OutputFile
@@ -131,19 +135,9 @@ dependencies {
implementation project(':native')
/* Third-party libraries */
- implementation 'androidx.multidex:multidex:2.0.1'
- implementation 'androidx.preference:preference:1.1.1'
- implementation 'com.google.android.play:core:1.9.1'
- implementation 'io.reactivex.rxjava2:rxjava:2.2.20'
- implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
- //noinspection GradleDependency
- implementation 'com.squareup.okhttp3:okhttp:3.12.12'
- //noinspection GradleDependency
- implementation 'commons-io:commons-io:2.5'
- implementation 'gun0912.ted:tedpermission-rx2:2.2.3'
- implementation 'com.google.code.gson:gson:2.8.6'
-
- /* Analytics libraries */
- //noinspection GradleDynamicVersion
- /*implementation 'com.bugsnag:bugsnag-android-core:5.+'*/
+ implementation 'androidx.appcompat:appcompat:1.4.0'
+ implementation 'androidx.appcompat:appcompat-resources:1.4.0'
+ implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
+ implementation 'androidx.work:work-runtime-ktx:2.7.1'
+ implementation 'com.google.android.material:material:1.4.0'
}
diff --git a/build/android/app/src/main/AndroidManifest.xml b/build/android/app/src/main/AndroidManifest.xml
index 8b5e52a65..f10ffb170 100644
--- a/build/android/app/src/main/AndroidManifest.xml
+++ b/build/android/app/src/main/AndroidManifest.xml
@@ -4,12 +4,10 @@
package="com.multicraft.game"
android:installLocation="auto">
-
+
-
+
@@ -59,6 +56,7 @@
-
-
diff --git a/build/android/app/src/main/java/com/bugsnag/android/Bugsnag.java b/build/android/app/src/main/java/com/bugsnag/android/Bugsnag.java
deleted file mode 100644
index 698041ff3..000000000
--- a/build/android/app/src/main/java/com/bugsnag/android/Bugsnag.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.bugsnag.android;
-
-import android.app.Application;
-import android.util.Log;
-
-public class Bugsnag {
- public static void notify(Throwable e) {
- Log.getStackTraceString(e);
- }
-
- public static void leaveBreadcrumb(String s) {
- Log.d("Bugsnag", s);
- }
-
- public static void start(Application application) {
- Log.d("Bugsnag", "Bugsnag initialized");
- }
-}
diff --git a/build/android/app/src/main/java/com/multicraft/game/CustomEditText.java b/build/android/app/src/main/java/com/multicraft/game/CustomEditText.kt
similarity index 50%
rename from build/android/app/src/main/java/com/multicraft/game/CustomEditText.java
rename to build/android/app/src/main/java/com/multicraft/game/CustomEditText.kt
index c32d68325..a1d2c2729 100644
--- a/build/android/app/src/main/java/com/multicraft/game/CustomEditText.java
+++ b/build/android/app/src/main/java/com/multicraft/game/CustomEditText.kt
@@ -1,7 +1,7 @@
/*
MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
+Copyright (C) 2014-2021 MoNTE48, Maksim Gamarnik
+Copyright (C) 2014-2021 ubulem, Bektur Mambetov
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -18,28 +18,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-package com.multicraft.game;
+package com.multicraft.game
-import android.content.Context;
-import android.view.KeyEvent;
-import android.view.inputmethod.InputMethodManager;
+import android.content.Context
+import android.util.AttributeSet
+import android.view.KeyEvent
+import android.view.inputmethod.InputMethodManager
-import androidx.appcompat.widget.AppCompatEditText;
-
-import java.util.Objects;
-
-public class CustomEditText extends AppCompatEditText {
- public CustomEditText(Context context) {
- super(context);
- }
-
- @Override
- public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+class CustomEditText constructor(context: Context, attrs: AttributeSet) :
+ com.google.android.material.textfield.TextInputEditText(context, attrs) {
+ override fun onKeyPreIme(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK) {
- InputMethodManager mgr = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- Objects.requireNonNull(mgr).hideSoftInputFromWindow(this.getWindowToken(), 0);
+ val mgr = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+ mgr.hideSoftInputFromWindow(this.windowToken, 0)
}
- return false;
+ return false
}
}
diff --git a/build/android/app/src/main/java/com/multicraft/game/GameActivity.java b/build/android/app/src/main/java/com/multicraft/game/GameActivity.java
index 923cd6214..01c4b0b56 100644
--- a/build/android/app/src/main/java/com/multicraft/game/GameActivity.java
+++ b/build/android/app/src/main/java/com/multicraft/game/GameActivity.java
@@ -1,7 +1,7 @@
/*
MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
+Copyright (C) 2014-2021 MoNTE48, Maksim Gamarnik
+Copyright (C) 2014-2021 ubulem, Bektur Mambetov
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -20,72 +20,43 @@ with this program; if not, write to the Free Software Foundation, Inc.,
package com.multicraft.game;
-import android.app.ActivityManager;
+import static android.content.res.Configuration.HARDKEYBOARDHIDDEN_NO;
+import static android.text.InputType.TYPE_CLASS_TEXT;
+import static android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE;
+import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
+import static com.multicraft.game.helpers.Utilities.finishApp;
+import static com.multicraft.game.helpers.Utilities.getTotalMem;
+import static com.multicraft.game.helpers.Utilities.makeFullScreen;
+
import android.app.NativeActivity;
-import android.content.Context;
+import android.content.Intent;
import android.content.res.Configuration;
-import android.content.res.Resources;
+import android.net.Uri;
import android.os.Bundle;
-import android.text.InputType;
-import android.text.method.LinkMovementMethod;
-import android.view.Gravity;
import android.view.KeyEvent;
import android.view.WindowManager.LayoutParams;
+import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
import android.widget.EditText;
-import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
-import com.bugsnag.android.Bugsnag;
-import com.multicraft.game.helpers.PreferencesHelper;
-import com.multicraft.game.helpers.RateMeHelper;
-import com.multicraft.game.helpers.Utilities;
-
-import org.json.JSONObject;
-import org.json.JSONTokener;
-
-import io.reactivex.Completable;
-import io.reactivex.Observable;
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.Disposable;
-import io.reactivex.schedulers.Schedulers;
-
-import static android.content.res.Configuration.KEYBOARD_QWERTY;
-import static com.multicraft.game.helpers.AdManager.initAd;
-import static com.multicraft.game.helpers.AdManager.setAdsCallback;
-import static com.multicraft.game.helpers.AdManager.startAd;
-import static com.multicraft.game.helpers.AdManager.stopAd;
-import static com.multicraft.game.helpers.Constants.versionCode;
-import static com.multicraft.game.helpers.PreferencesHelper.IS_ASK_CONSENT;
-import static com.multicraft.game.helpers.PreferencesHelper.TAG_EXIT_GAME_COUNT;
-import static com.multicraft.game.helpers.PreferencesHelper.TAG_LAST_RATE_VERSION_CODE;
-import static com.multicraft.game.helpers.PreferencesHelper.getInstance;
-import static com.multicraft.game.helpers.Utilities.getIcon;
-import static com.multicraft.game.helpers.Utilities.makeFullScreen;
+import com.multicraft.game.databinding.InputTextBinding;
public class GameActivity extends NativeActivity {
+ public static boolean isMultiPlayer;
+
static {
try {
System.loadLibrary("MultiCraft");
- } catch (UnsatisfiedLinkError | OutOfMemoryError e) {
- Bugsnag.notify(e);
- System.exit(0);
- } catch (IllegalArgumentException i) {
- Bugsnag.notify(i);
- System.exit(0);
- } catch (Error | Exception e) {
- Bugsnag.notify(e);
+ } catch (UnsatisfiedLinkError e) {
System.exit(0);
}
}
private int messageReturnCode = -1;
private String messageReturnValue = "";
- private int height, width;
- private boolean consent, isMultiPlayer;
- private PreferencesHelper pf;
- private Disposable adInitSub, gdprSub;
private boolean hasKeyboard;
public static native void pauseGame();
@@ -95,118 +66,20 @@ public class GameActivity extends NativeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Bundle bundle = getIntent().getExtras();
- Resources resources = getResources();
- height = bundle != null ? bundle.getInt("height", 0) : resources.getDisplayMetrics().heightPixels;
- width = bundle != null ? bundle.getInt("width", 0) : resources.getDisplayMetrics().widthPixels;
getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
- hasKeyboard = !(resources.getConfiguration().hardKeyboardHidden == KEYBOARD_QWERTY);
+ hasKeyboard = getResources().getConfiguration().hardKeyboardHidden == HARDKEYBOARDHIDDEN_NO;
keyboardEvent(hasKeyboard);
- pf = getInstance(this);
- RateMeHelper.onStart(this);
- askGdpr();
- }
-
- private void subscribeAds() {
- if (pf.isAdsEnable()) {
- adInitSub = Completable.fromAction(() -> initAd(this, consent))
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(() -> setAdsCallback(this));
- }
- }
-
- // GDPR check
- private void askGdpr() {
- if (pf.isAskConsent())
- isGdprSubject();
- else {
- consent = true;
- subscribeAds();
- }
- }
-
- private void isGdprSubject() {
- gdprSub = Observable.fromCallable(() -> Utilities.getJson("http://adservice.google.com/getconfig/pubvendors"))
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(result -> {
- JSONObject json = new JSONObject(new JSONTokener(result));
- if (json.getBoolean("is_request_in_eea_or_unknown"))
- showGdprDialog();
- else {
- consent = true;
- subscribeAds();
- }
- },
- throwable -> {
- consent = true;
- subscribeAds();
- });
- }
-
- private void showGdprDialog() {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setIcon(getIcon(this));
- builder.setTitle(getString(R.string.app_name));
- TextView tv = new TextView(this);
- tv.setText(R.string.gdpr_main_text);
- tv.setTypeface(null);
- tv.setPadding(20, 0, 20, 0);
- tv.setGravity(Gravity.CENTER);
- tv.setMovementMethod(LinkMovementMethod.getInstance());
- builder.setView(tv);
- builder.setPositiveButton(getString(R.string.gdpr_agree), (dialogInterface, i) -> {
- dialogInterface.dismiss();
- pf.saveSettings(IS_ASK_CONSENT, false);
- consent = true;
- subscribeAds();
- });
- builder.setNegativeButton(getString(R.string.gdpr_disagree), (dialogInterface, i) -> {
- dialogInterface.dismiss();
- pf.saveSettings(IS_ASK_CONSENT, false);
- consent = false;
- subscribeAds();
- });
- builder.setCancelable(false);
- final AlertDialog dialog = builder.create();
- if (!isFinishing())
- dialog.show();
- }
-
- private void checkRateDialog() {
- if (RateMeHelper.shouldShowRateDialog()) {
- pf.saveSettings(TAG_LAST_RATE_VERSION_CODE, versionCode);
- runOnUiThread(() -> RateMeHelper.showRateDialog(this));
- }
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
- if (hasFocus)
- makeFullScreen(this);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- makeFullScreen(this);
+ if (hasFocus) makeFullScreen(getWindow());
}
@Override
public void onBackPressed() {
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (adInitSub != null) adInitSub.dispose();
- if (gdprSub != null) gdprSub.dispose();
- }
-
- public void showDialog(String acceptButton, String hint, String current, int editType) {
- runOnUiThread(() -> showDialogUI(hint, current, editType));
+ // Ignore the back press so MultiCraft can handle it
}
@Override
@@ -215,38 +88,51 @@ public class GameActivity extends NativeActivity {
pauseGame();
}
+ @Override
+ protected void onResume() {
+ super.onResume();
+ makeFullScreen(getWindow());
+ }
+
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- boolean statusKeyboard = !(getResources().getConfiguration().hardKeyboardHidden == KEYBOARD_QWERTY);
+ boolean statusKeyboard = getResources().getConfiguration().hardKeyboardHidden == HARDKEYBOARDHIDDEN_NO;
if (hasKeyboard != statusKeyboard) {
hasKeyboard = statusKeyboard;
keyboardEvent(hasKeyboard);
}
}
+ @SuppressWarnings("unused")
+ public void showDialog(String s, String hint, String current, int editType) {
+ runOnUiThread(() -> showDialogUI(hint, current, editType));
+ }
+
private void showDialogUI(String hint, String current, int editType) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
- EditText editText = new CustomEditText(this);
- builder.setView(editText);
+ if (editType == 1) builder.setPositiveButton(R.string.done, null);
+ InputTextBinding binding = InputTextBinding.inflate(getLayoutInflater());
+ String hintText = (!hint.isEmpty()) ? hint : getResources().getString(
+ (editType == 3) ? R.string.input_password : R.string.input_text);
+ binding.inputLayout.setHint(hintText);
+ builder.setView(binding.getRoot());
AlertDialog alertDialog = builder.create();
+ EditText editText = binding.editText;
editText.requestFocus();
- editText.setHint(hint);
editText.setText(current);
+ if (editType != 1) editText.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
final InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
- imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,
- InputMethodManager.HIDE_IMPLICIT_ONLY);
- if (editType == 1)
- editText.setInputType(InputType.TYPE_CLASS_TEXT |
- InputType.TYPE_TEXT_FLAG_MULTI_LINE);
- else if (editType == 3)
- editText.setInputType(InputType.TYPE_CLASS_TEXT |
- InputType.TYPE_TEXT_VARIATION_PASSWORD);
- else
- editText.setInputType(InputType.TYPE_CLASS_TEXT);
+ int inputType = TYPE_CLASS_TEXT;
+ if (editType == 1) {
+ inputType = inputType | TYPE_TEXT_FLAG_MULTI_LINE;
+ editText.setMaxLines(8);
+ } else if (editType == 3)
+ inputType = inputType | TYPE_TEXT_VARIATION_PASSWORD;
+ editText.setInputType(inputType);
editText.setSelection(editText.getText().length());
- editText.setOnKeyListener((view, KeyCode, event) -> {
- if (KeyCode == KeyEvent.KEYCODE_ENTER) {
+ editText.setOnEditorActionListener((view, KeyCode, event) -> {
+ if (KeyCode == KeyEvent.KEYCODE_ENTER || KeyCode == KeyEvent.KEYCODE_ENDCALL) {
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
messageReturnCode = 0;
messageReturnValue = editText.getText().toString();
@@ -255,7 +141,18 @@ public class GameActivity extends NativeActivity {
}
return false;
});
+ // should be above `show()`
+ alertDialog.getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
alertDialog.show();
+ Button button = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
+ if (button != null) {
+ button.setOnClickListener(view -> {
+ imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
+ messageReturnCode = 0;
+ messageReturnValue = editText.getText().toString();
+ alertDialog.dismiss();
+ });
+ }
alertDialog.setOnCancelListener(dialog -> {
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
messageReturnValue = current;
@@ -267,6 +164,7 @@ public class GameActivity extends NativeActivity {
return messageReturnCode;
}
+ @SuppressWarnings("unused")
public String getDialogValue() {
messageReturnCode = -1;
return messageReturnValue;
@@ -276,40 +174,32 @@ public class GameActivity extends NativeActivity {
return getResources().getDisplayMetrics().density;
}
- public int getDisplayHeight() {
- return height;
- }
-
- public int getDisplayWidth() {
- return width;
- }
-
public float getMemoryMax() {
- ActivityManager actManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
- ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
- float memory = 1.0f;
- if (actManager != null) {
- actManager.getMemoryInfo(memInfo);
- memory = memInfo.totalMem * 1.0f / (1024 * 1024 * 1024);
- memory = Math.round(memory * 100) / 100.0f;
- }
- return memory;
+ return getTotalMem(this);
}
public void notifyServerConnect(boolean multiplayer) {
isMultiPlayer = multiplayer;
- if (isMultiPlayer)
- stopAd();
}
public void notifyExitGame() {
- pf.saveSettings(TAG_EXIT_GAME_COUNT, pf.getExitGameCount() + 1);
- if (!isFinishing()) {
- if (isMultiPlayer) {
- if (pf.isAdsEnable())
- startAd(this, false, true);
- } else
- checkRateDialog();
+ }
+
+ @SuppressWarnings("unused")
+ public void openURI(String uri) {
+ try {
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
+ startActivity(browserIntent);
+ } catch (Exception ignored) {
}
}
+
+ @SuppressWarnings("unused")
+ public void finishGame(String exc) {
+ finishApp(true, this);
+ }
+
+ @SuppressWarnings("unused")
+ public void handleError(String exc) {
+ }
}
diff --git a/build/android/app/src/main/java/com/multicraft/game/JsonSettings.java b/build/android/app/src/main/java/com/multicraft/game/JsonSettings.java
deleted file mode 100644
index 6f407f0ef..000000000
--- a/build/android/app/src/main/java/com/multicraft/game/JsonSettings.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 3.0 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-package com.multicraft.game;
-
-import com.google.gson.annotations.SerializedName;
-
-import java.util.List;
-
-public class JsonSettings {
- @SerializedName(value = "version_code")
- private int versionCode;
- @SerializedName(value = "version_code_bad")
- private List badVersionCodes;
- @SerializedName(value = "rate_min_version_code")
- private int rateMinVersionCode;
- @SerializedName(value = "package")
- private String packageName;
- @SerializedName(value = "content_ru")
- private String contentRus;
- @SerializedName(value = "content_en")
- private String contentEng;
- @SerializedName(value = "ads_delay")
- private int adsDelay;
- @SerializedName(value = "ads_repeat")
- private int adsRepeat;
- @SerializedName(value = "ads_enable")
- private boolean adsEnabled;
- @SerializedName(value = "review_enable")
- private boolean reviewEnabled;
-
- public int getVersionCode() {
- return versionCode;
- }
-
- public List getBadVersionCodes() {
- return badVersionCodes;
- }
-
- public int getRateMinVersionCode() {
- return rateMinVersionCode;
- }
-
- public String getPackageName() {
- return packageName;
- }
-
- public int getAdsDelay() {
- return adsDelay;
- }
-
- public int getAdsRepeat() {
- return adsRepeat;
- }
-
- public boolean isAdsEnabled() {
- return adsEnabled;
- }
-
- public boolean isReviewEnabled() {
- return reviewEnabled;
- }
-
- public String getContentRus() {
- return contentRus;
- }
-
- public String getContentEng() {
- return contentEng;
- }
-}
diff --git a/build/android/app/src/main/java/com/multicraft/game/MainActivity.java b/build/android/app/src/main/java/com/multicraft/game/MainActivity.java
deleted file mode 100644
index 7c958e9eb..000000000
--- a/build/android/app/src/main/java/com/multicraft/game/MainActivity.java
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
-MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 3.0 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-package com.multicraft.game;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
-import android.graphics.BlendMode;
-import android.graphics.BlendModeColorFilter;
-import android.graphics.Color;
-import android.graphics.Point;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.os.Bundle;
-import android.text.Html;
-import android.view.Display;
-import android.view.View;
-import android.view.WindowManager.LayoutParams;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.app.AppCompatActivity;
-
-import com.bugsnag.android.Bugsnag;
-import com.google.android.play.core.appupdate.AppUpdateInfo;
-import com.google.android.play.core.appupdate.AppUpdateManager;
-import com.google.android.play.core.appupdate.AppUpdateManagerFactory;
-import com.google.android.play.core.install.InstallStateUpdatedListener;
-import com.google.android.play.core.install.model.AppUpdateType;
-import com.google.android.play.core.install.model.InstallStatus;
-import com.google.android.play.core.install.model.UpdateAvailability;
-import com.google.android.play.core.tasks.Task;
-import com.multicraft.game.callbacks.CallBackListener;
-import com.multicraft.game.helpers.PermissionHelper;
-import com.multicraft.game.helpers.PreferencesHelper;
-import com.multicraft.game.helpers.Utilities;
-import com.multicraft.game.helpers.VersionManagerHelper;
-
-import org.apache.commons.io.FileUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import io.reactivex.Completable;
-import io.reactivex.Observable;
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.Disposable;
-import io.reactivex.schedulers.Schedulers;
-
-import static android.provider.Settings.ACTION_WIFI_SETTINGS;
-import static android.provider.Settings.ACTION_WIRELESS_SETTINGS;
-import static com.multicraft.game.UnzipService.ACTION_FAILURE;
-import static com.multicraft.game.UnzipService.UNZIP_FAILURE;
-import static com.multicraft.game.UnzipService.UNZIP_SUCCESS;
-import static com.multicraft.game.helpers.ApiLevelHelper.isAndroidQ;
-import static com.multicraft.game.helpers.ApiLevelHelper.isJellyBeanMR1;
-import static com.multicraft.game.helpers.ApiLevelHelper.isLollipop;
-import static com.multicraft.game.helpers.ApiLevelHelper.isOreo;
-import static com.multicraft.game.helpers.Constants.FILES;
-import static com.multicraft.game.helpers.Constants.GAMES;
-import static com.multicraft.game.helpers.Constants.NO_SPACE_LEFT;
-import static com.multicraft.game.helpers.Constants.REQUEST_CONNECTION;
-import static com.multicraft.game.helpers.Constants.REQUEST_UPDATE;
-import static com.multicraft.game.helpers.Constants.UPDATE_LINK;
-import static com.multicraft.game.helpers.Constants.versionName;
-import static com.multicraft.game.helpers.PreferencesHelper.TAG_BUILD_NUMBER;
-import static com.multicraft.game.helpers.PreferencesHelper.TAG_LAUNCH_TIMES;
-import static com.multicraft.game.helpers.Utilities.addShortcut;
-import static com.multicraft.game.helpers.Utilities.deleteFiles;
-import static com.multicraft.game.helpers.Utilities.getIcon;
-import static com.multicraft.game.helpers.Utilities.getZipsFromAssets;
-import static com.multicraft.game.helpers.Utilities.makeFullScreen;
-
-public class MainActivity extends AppCompatActivity implements CallBackListener {
- private ArrayList zips;
- private int height, width;
- private ProgressBar mProgressBar, mProgressBarIndeterminate;
- private TextView mLoading;
- private VersionManagerHelper versionManagerHelper = null;
- private PreferencesHelper pf;
- private AppUpdateManager appUpdateManager;
- final InstallStateUpdatedListener listener = state -> {
- if (state.installStatus() == InstallStatus.DOWNLOADING) {
- if (mProgressBar != null) {
- int progress = (int) (state.bytesDownloaded() * 100 / state.totalBytesToDownload());
- showProgress(R.string.downloading, R.string.downloadingp, progress);
- }
- } else if (state.installStatus() == InstallStatus.DOWNLOADED) {
- appUpdateManager.completeUpdate();
- }
- };
- private Disposable connectionSub, versionManagerSub, cleanSub, copySub;
- private final BroadcastReceiver myReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- int progress = 0;
- if (intent != null)
- progress = intent.getIntExtra(UnzipService.ACTION_PROGRESS, 0);
- if (progress >= 0) {
- if (mProgressBar != null) {
- showProgress(R.string.loading, R.string.loadingp, progress);
- }
- } else if (progress == UNZIP_FAILURE) {
- Toast.makeText(MainActivity.this, intent.getStringExtra(ACTION_FAILURE), Toast.LENGTH_LONG).show();
- showRestartDialog("");
- } else if (progress == UNZIP_SUCCESS) {
- deleteFiles(Arrays.asList(FILES, GAMES), getCacheDir().toString());
- runGame();
- }
- }
- };
- private Task appUpdateInfoTask;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
- setContentView(R.layout.activity_main);
- pf = PreferencesHelper.getInstance(this);
- appUpdateManager = AppUpdateManagerFactory.create(this);
- appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();
- IntentFilter filter = new IntentFilter(UnzipService.ACTION_UPDATE);
- registerReceiver(myReceiver, filter);
- if (!isTaskRoot()) {
- finish();
- return;
- }
- addLaunchTimes();
- PermissionHelper permission = new PermissionHelper(this);
- permission.setListener(this);
- permission.askPermissions();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- makeFullScreen(this);
- appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
- if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED)
- appUpdateManager.completeUpdate();
- });
- }
-
- @Override
- public void onBackPressed() {
- // Prevent abrupt interruption when copy game files from assets
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (connectionSub != null) connectionSub.dispose();
- if (versionManagerSub != null) versionManagerSub.dispose();
- if (cleanSub != null) cleanSub.dispose();
- if (copySub != null) copySub.dispose();
- appUpdateManager.unregisterListener(listener);
- unregisterReceiver(myReceiver);
- }
-
- private void addLaunchTimes() {
- pf.saveSettings(TAG_LAUNCH_TIMES, pf.getLaunchTimes() + 1);
- }
-
- // interface
- private void showProgress(int textMessage, int progressMessage, int progress) {
- if (mProgressBar.getVisibility() == View.GONE) {
- updateViews(textMessage, View.VISIBLE, View.GONE, View.VISIBLE);
- mProgressBar.setProgress(0);
- } else if (progress > 0) {
- mLoading.setText(String.format(getResources().getString(progressMessage), progress));
- mProgressBar.setProgress(progress);
- // colorize the progress bar
- Drawable progressDrawable = ((LayerDrawable)
- mProgressBar.getProgressDrawable()).getDrawable(1);
- int color = Color.rgb(255 - progress * 2, progress * 2, 25);
- if (isAndroidQ())
- progressDrawable.setColorFilter(new BlendModeColorFilter(color, BlendMode.SRC_IN));
- else
- progressDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
- }
- }
-
- // real screen resolution
- private void getDefaultResolution() {
- Display display = getWindowManager().getDefaultDisplay();
- Point size = new Point();
- if (isJellyBeanMR1())
- display.getRealSize(size);
- else
- display.getSize(size);
- height = Math.min(size.x, size.y);
- width = Math.max(size.x, size.y);
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- super.onWindowFocusChanged(hasFocus);
- if (hasFocus)
- makeFullScreen(this);
- }
-
- private void init() {
- mProgressBar = findViewById(R.id.PB1);
- mProgressBarIndeterminate = findViewById(R.id.PB2);
- mLoading = findViewById(R.id.tv_progress);
- if (!pf.isCreateShortcut() && !isOreo())
- addShortcut(this);
- checkAppVersion();
- }
-
- void showUpdateDialog() {
- updateViews(R.string.loading, View.VISIBLE, View.VISIBLE, View.GONE);
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setIcon(getIcon(this))
- .setTitle(R.string.available)
- .setMessage(Html.fromHtml(
- versionManagerHelper.getMessage(), null, versionManagerHelper.getCustomTagHandler()))
- .setPositiveButton(R.string.update, (dialogInterface, i) -> {
- versionManagerHelper.updateNow(versionManagerHelper.getUpdateUrl());
- finish();
- })
- .setNeutralButton(R.string.later, (dialogInterface, i) -> {
- versionManagerHelper.remindMeLater();
- startNative();
- });
- builder.setCancelable(false);
- final AlertDialog dialog = builder.create();
- if (!isFinishing())
- dialog.show();
- }
-
- public void startUpdate() {
- appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
- if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
- && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
- try {
- appUpdateManager.startUpdateFlowForResult(
- appUpdateInfo, AppUpdateType.FLEXIBLE, this, REQUEST_UPDATE);
- } catch (IntentSender.SendIntentException e) {
- //Bugsnag.notify(e);
- showUpdateDialog();
- }
- } else {
- showUpdateDialog();
- }
- });
- appUpdateInfoTask.addOnFailureListener(e -> {
- //Bugsnag.notify(e);
- showUpdateDialog();
- });
- }
-
- private void checkUrlVersion() {
- versionManagerHelper = new VersionManagerHelper(this);
- if (versionManagerHelper.isCheckVersion())
- versionManagerSub = Observable.fromCallable(() -> Utilities.getJson(UPDATE_LINK))
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .timeout(3000, TimeUnit.MILLISECONDS)
- .subscribe(result -> isShowDialog(versionManagerHelper.isShow(result)),
- throwable -> runOnUiThread(() -> isShowDialog(false)));
- else isShowDialog(false);
- }
-
- private void runGame() {
- pf.saveSettings(TAG_BUILD_NUMBER, versionName);
- connectionSub = checkConnection();
- }
-
- private void startNative() {
- getDefaultResolution();
- Intent intent = new Intent(this, GameActivity.class);
- intent.putExtra("height", height);
- intent.putExtra("width", width);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- startActivity(intent);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == REQUEST_CONNECTION) {
- checkUrlVersion();
- } else if (requestCode == REQUEST_UPDATE) {
- if (resultCode == RESULT_OK)
- appUpdateManager.registerListener(listener);
- else
- startNative();
- }
- }
-
- private void cleanUpOldFiles(boolean isAll) {
- updateViews(R.string.preparing, View.VISIBLE, View.VISIBLE, View.GONE);
- Completable delObs;
- File externalStorage = getExternalFilesDir(null);
- if (isAll)
- delObs = Completable.fromAction(() -> deleteFiles(Collections.singletonList(externalStorage)));
- else {
- List filesList = Arrays.asList(new File(externalStorage, "cache"),
- new File(getFilesDir(), "builtin"),
- new File(getFilesDir(), "games"),
- new File(externalStorage, "debug.txt"));
- delObs = Completable.fromAction(() -> deleteFiles(filesList));
- }
- cleanSub = delObs.subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(() -> startCopy(isAll));
- }
-
- private void checkAppVersion() {
- String prefVersion;
- try {
- prefVersion = pf.getBuildNumber();
- } catch (ClassCastException e) {
- prefVersion = "1";
- }
- if (prefVersion.equals(versionName)) {
- mProgressBarIndeterminate.setVisibility(View.VISIBLE);
- runGame();
- } else {
- cleanUpOldFiles(prefVersion.equals("0"));
- }
- }
-
- public void updateViews(int text, int textVisib, int progressIndetermVisib, int progressVisib) {
- mLoading.setText(text);
- mLoading.setVisibility(textVisib);
- mProgressBarIndeterminate.setVisibility(progressIndetermVisib);
- mProgressBar.setVisibility(progressVisib);
- }
-
- public void isShowDialog(boolean flag) {
- if (flag) {
- if (isLollipop())
- startUpdate();
- else
- showUpdateDialog();
- } else
- startNative();
- }
-
- private Disposable checkConnection() {
- return Observable.fromCallable(Utilities::isReachable)
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .timeout(4000, TimeUnit.MILLISECONDS)
- .subscribe(result -> {
- if (result) checkUrlVersion();
- else showConnectionDialog();
- },
- throwable -> runOnUiThread(this::showConnectionDialog));
- }
-
- private void startCopy(boolean isAll) {
- zips = getZipsFromAssets(this);
- copySub = Completable.fromAction(() -> runOnUiThread(() -> copyAssets(zips)))
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(() -> startUnzipService(zips));
- }
-
- private void copyAssets(ArrayList zips) {
- for (String zipName : zips) {
- try (InputStream in = getAssets().open("data/" + zipName)) {
- FileUtils.copyInputStreamToFile(in, new File(getCacheDir(), zipName));
- } catch (IOException e) {
- Bugsnag.leaveBreadcrumb("Failed to copy " + zipName);
- if (e.getLocalizedMessage().contains(NO_SPACE_LEFT))
- showRestartDialog(NO_SPACE_LEFT);
- else {
- showRestartDialog("");
- Bugsnag.notify(e);
- }
- }
- }
- }
-
- private void startUnzipService(ArrayList file) {
- Intent intent = new Intent(this, UnzipService.class);
- intent.putStringArrayListExtra(UnzipService.EXTRA_KEY_IN_FILE, file);
- startService(intent);
- }
-
- private void showRestartDialog(final String source) {
- String message;
- if (NO_SPACE_LEFT.equals(source))
- message = getString(R.string.no_space);
- else
- message = getString(R.string.restart);
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setMessage(message)
- .setPositiveButton(R.string.ok, (dialogInterface, i) -> restartApp());
- builder.setCancelable(false);
- final AlertDialog dialog = builder.create();
- if (!isFinishing())
- dialog.show();
- }
-
- private void restartApp() {
- Intent intent = new Intent(getApplicationContext(), MainActivity.class);
- int mPendingIntentId = 1337;
- AlarmManager mgr = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
- if (mgr != null)
- mgr.set(AlarmManager.RTC, System.currentTimeMillis(), PendingIntent.getActivity(
- getApplicationContext(), mPendingIntentId, intent, PendingIntent.FLAG_CANCEL_CURRENT));
- System.exit(0);
- }
-
- @Override
- public void onEvent(boolean isContinue) {
- if (isFinishing()) return;
- if (isContinue) init();
- else finish();
- }
-
- private void showConnectionDialog() {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setMessage(R.string.conn_message)
- .setPositiveButton(R.string.conn_wifi, (dialogInterface, i) -> startHandledActivity(new Intent(ACTION_WIFI_SETTINGS)))
- .setNegativeButton(R.string.conn_mobile, (dialogInterface, i) -> startHandledActivity(new Intent(ACTION_WIRELESS_SETTINGS)))
- .setNeutralButton(R.string.ignore, (dialogInterface, i) -> startNative());
- builder.setCancelable(false);
- final AlertDialog dialog = builder.create();
- if (!isFinishing())
- dialog.show();
- }
-
- private void startHandledActivity(Intent intent) {
- try {
- startActivityForResult(intent, REQUEST_CONNECTION);
- } catch (Exception e) {
- startNative();
- }
- }
-}
diff --git a/build/android/app/src/main/java/com/multicraft/game/MainActivity.kt b/build/android/app/src/main/java/com/multicraft/game/MainActivity.kt
new file mode 100644
index 000000000..e45018b74
--- /dev/null
+++ b/build/android/app/src/main/java/com/multicraft/game/MainActivity.kt
@@ -0,0 +1,266 @@
+/*
+MultiCraft
+Copyright (C) 2014-2021 MoNTE48, Maksim Gamarnik
+Copyright (C) 2014-2021 ubulem, Bektur Mambetov
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 3.0 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+package com.multicraft.game
+
+import android.content.DialogInterface
+import android.content.Intent
+import android.content.SharedPreferences
+import android.graphics.Color
+import android.graphics.drawable.LayerDrawable
+import android.os.Bundle
+import android.provider.Settings.ACTION_WIFI_SETTINGS
+import android.provider.Settings.ACTION_WIRELESS_SETTINGS
+import android.view.View
+import android.view.WindowManager
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.graphics.BlendModeColorFilterCompat
+import androidx.core.graphics.BlendModeCompat
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.lifecycleScope
+import androidx.work.WorkInfo
+import com.multicraft.game.databinding.ActivityMainBinding
+import com.multicraft.game.helpers.Constants.NO_SPACE_LEFT
+import com.multicraft.game.helpers.Constants.REQUEST_CONNECTION
+import com.multicraft.game.helpers.PreferenceHelper
+import com.multicraft.game.helpers.PreferenceHelper.TAG_BUILD_VER
+import com.multicraft.game.helpers.PreferenceHelper.TAG_LAUNCH_TIMES
+import com.multicraft.game.helpers.PreferenceHelper.TAG_SHORTCUT_EXIST
+import com.multicraft.game.helpers.PreferenceHelper.getBoolValue
+import com.multicraft.game.helpers.PreferenceHelper.getIntValue
+import com.multicraft.game.helpers.PreferenceHelper.getStringValue
+import com.multicraft.game.helpers.PreferenceHelper.set
+import com.multicraft.game.helpers.Utilities.addShortcut
+import com.multicraft.game.helpers.Utilities.copyInputStreamToFile
+import com.multicraft.game.helpers.Utilities.finishApp
+import com.multicraft.game.helpers.Utilities.getIcon
+import com.multicraft.game.helpers.Utilities.isConnected
+import com.multicraft.game.helpers.Utilities.makeFullScreen
+import com.multicraft.game.workmanager.UnzipWorker.Companion.PROGRESS
+import com.multicraft.game.workmanager.WorkerViewModel
+import com.multicraft.game.workmanager.WorkerViewModelFactory
+import kotlinx.coroutines.launch
+import java.io.File
+import java.io.IOException
+
+class MainActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityMainBinding
+ private var externalStorage: File? = null
+ private val sep = File.separator
+ private lateinit var prefs: SharedPreferences
+ private val versionName = BuildConfig.VERSION_NAME
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ prefs = PreferenceHelper.init(this)
+ var storageUnavailable = false
+ try {
+ externalStorage = getExternalFilesDir(null)
+ if (filesDir == null || cacheDir == null || externalStorage == null)
+ throw IOException("Bad disk space state")
+ } catch (e: IOException) {
+ storageUnavailable = true
+ showRestartDialog(e.message!!.contains(NO_SPACE_LEFT))
+ }
+ if (storageUnavailable) return
+ lateInit()
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ @Suppress("DEPRECATION")
+ super.onActivityResult(requestCode, resultCode, data)
+ if (requestCode == REQUEST_CONNECTION)
+ checkAppVersion()
+
+ }
+
+ override fun onBackPressed() {
+ // Prevent abrupt interruption when copy game files from assets
+ }
+
+ override fun onResume() {
+ super.onResume()
+ makeFullScreen(window)
+ }
+
+ override fun onWindowFocusChanged(hasFocus: Boolean) {
+ super.onWindowFocusChanged(hasFocus)
+ if (hasFocus) makeFullScreen(window)
+ }
+
+ private fun addLaunchTimes() {
+ val launchTimes = prefs.getIntValue(TAG_LAUNCH_TIMES) + 1
+ prefs[TAG_LAUNCH_TIMES] = launchTimes
+ }
+
+ // interface
+ private fun showProgress(textMessage: Int, progressMessage: Int, progress: Int) {
+ if (binding.progressBar.visibility == View.GONE) {
+ binding.tvProgress.setText(textMessage)
+ binding.progressCircle.visibility = View.GONE
+ binding.progressBar.visibility = View.VISIBLE
+ binding.progressBar.progress = 0
+ } else if (progress > 0) {
+ binding.tvProgress.text = String.format(getString(progressMessage), progress)
+ binding.progressBar.progress = progress
+ // colorize the progress bar
+ val progressDrawable =
+ (binding.progressBar.progressDrawable as LayerDrawable).getDrawable(1)
+ val color = Color.rgb(255 - progress * 2, progress * 2, 25)
+ progressDrawable.colorFilter =
+ BlendModeColorFilterCompat.createBlendModeColorFilterCompat(
+ color, BlendModeCompat.SRC_IN
+ )
+ }
+ }
+
+ private fun lateInit() {
+ addLaunchTimes()
+ if (!prefs.getBoolValue(TAG_SHORTCUT_EXIST)) try {
+ addShortcut(this)
+ } catch (ignored: Exception) {
+ }
+ checkConnection()
+ }
+
+ private fun startNative() {
+ val initLua = File(filesDir, "builtin${sep}mainmenu${sep}init.lua")
+ if (initLua.exists() && initLua.canRead()) {
+ val intent = Intent(this, GameActivity::class.java)
+ intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ startActivity(intent)
+ } else {
+ prefs[TAG_BUILD_VER] = "0"
+ showRestartDialog(false)
+ }
+ }
+
+ private fun prepareToRun() {
+ binding.tvProgress.setText(R.string.preparing)
+ binding.progressCircle.visibility = View.VISIBLE
+ binding.progressBar.visibility = View.GONE
+ val filesList = listOf(
+ File(externalStorage, "builtin"),
+ File(externalStorage, "cache"), // ToDo: remove me!
+ File(externalStorage, "games${sep}default"),
+ File(externalStorage, "textures${sep}base"),
+ File(externalStorage, "debug.txt"),
+ File(filesDir, "builtin"),
+ File(filesDir, "games"),
+ File(filesDir, "textures${sep}base")
+ )
+ val zips = assets.list("data")!!.toList()
+ lifecycleScope.launch {
+ filesList.forEach { it.deleteRecursively() }
+ zips.forEach {
+ try {
+ assets.open("data$sep$it").use { input ->
+ File(cacheDir, it).copyInputStreamToFile(input)
+ }
+ } catch (e: IOException) {
+ runOnUiThread { showRestartDialog(e.message!!.contains(NO_SPACE_LEFT)) }
+ return@forEach
+ }
+ }
+ startUnzipWorker(zips)
+ }
+ }
+
+ private fun checkAppVersion() {
+ val prefVersion = prefs.getStringValue(TAG_BUILD_VER)
+ if (prefVersion == versionName)
+ startNative()
+ else
+ prepareToRun()
+ }
+
+ // check connection available
+ private fun checkConnection() = lifecycleScope.launch {
+ val result = isConnected(this@MainActivity)
+ if (result) checkAppVersion()
+ else try {
+ showConnectionDialog()
+ } catch (e: Exception) {
+ checkAppVersion()
+ }
+ }
+
+ private fun startUnzipWorker(file: List) {
+ val viewModelFactory = WorkerViewModelFactory(application, file.toTypedArray())
+ val viewModel = ViewModelProvider(this, viewModelFactory).get(WorkerViewModel::class.java)
+ viewModel.unzippingWorkObserver
+ .observe(this, Observer { workInfo ->
+ if (workInfo == null)
+ return@Observer
+ val progress = workInfo.progress.getInt(PROGRESS, 0)
+ showProgress(R.string.loading, R.string.loadingp, progress)
+
+ if (workInfo.state.isFinished) {
+ if (workInfo.state == WorkInfo.State.FAILED) {
+ showRestartDialog(false)
+ } else if (workInfo.state == WorkInfo.State.SUCCEEDED) {
+ prefs[TAG_BUILD_VER] = versionName
+ startNative()
+ }
+ }
+ })
+ viewModel.startOneTimeWorkRequest()
+ }
+
+ private fun showRestartDialog(space: Boolean) {
+ val message = if (space) getString(R.string.no_space) else getString(R.string.restart)
+ val builder = AlertDialog.Builder(this)
+ builder.setMessage(message)
+ .setPositiveButton(R.string.ok) { _, _ -> finishApp(!space, this) }
+ .setCancelable(false)
+ val dialog = builder.create()
+ makeFullScreen(dialog.window!!)
+ if (!isFinishing) dialog.show()
+ }
+
+ // connection dialog
+ private fun showConnectionDialog() {
+ val builder = AlertDialog.Builder(this)
+ builder.setIcon(getIcon(this))
+ .setTitle(R.string.conn_title)
+ .setMessage(R.string.conn_message)
+ .setPositiveButton(R.string.conn_wifi) { _, _ ->
+ @Suppress("DEPRECATION")
+ startActivityForResult(Intent(ACTION_WIFI_SETTINGS), REQUEST_CONNECTION)
+ }
+ .setNegativeButton(R.string.conn_mobile) { _, _ ->
+ @Suppress("DEPRECATION")
+ startActivityForResult(Intent(ACTION_WIRELESS_SETTINGS), REQUEST_CONNECTION)
+ }
+ .setNeutralButton(R.string.ignore) { _, _ -> checkAppVersion() }
+ .setCancelable(false)
+ val dialog = builder.create()
+ makeFullScreen(dialog.window!!)
+ if (!isFinishing) {
+ dialog.show()
+ dialog.getButton(DialogInterface.BUTTON_NEUTRAL)?.setTextColor(Color.RED)
+ }
+ }
+}
diff --git a/build/android/app/src/main/java/com/multicraft/game/UnzipService.java b/build/android/app/src/main/java/com/multicraft/game/UnzipService.java
deleted file mode 100644
index 9362e68b5..000000000
--- a/build/android/app/src/main/java/com/multicraft/game/UnzipService.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
-MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 3.0 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-package com.multicraft.game;
-
-import android.app.IntentService;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.Intent;
-
-import com.bugsnag.android.Bugsnag;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-import java.util.zip.ZipInputStream;
-
-import static com.multicraft.game.helpers.ApiLevelHelper.isOreo;
-import static com.multicraft.game.helpers.Constants.NO_SPACE_LEFT;
-import static com.multicraft.game.helpers.Utilities.getLocationByZip;
-import static com.multicraft.game.helpers.Utilities.getZipsFromAssets;
-
-public class UnzipService extends IntentService {
- public static final String ACTION_UPDATE = "com.multicraft.game.UPDATE";
- public static final String EXTRA_KEY_IN_FILE = "com.multicraft.game.file";
- public static final String ACTION_PROGRESS = "com.multicraft.game.progress";
- public static final String ACTION_FAILURE = "com.multicraft.game.failure";
- public static final int UNZIP_SUCCESS = -1;
- public static final int UNZIP_FAILURE = -2;
- private final int id = 1;
- private NotificationManager mNotifyManager;
- private String failureMessage;
- private boolean isSuccess = true;
-
- public UnzipService() {
- super("com.multicraft.game.UnzipService");
- }
-
- private void isDir(String dir, String unzipLocation) {
- File f = new File(unzipLocation, dir);
- if (!f.mkdirs() && !f.isDirectory())
- Bugsnag.leaveBreadcrumb(f + " (destination) folder was not created");
- }
-
- @Override
- protected void onHandleIntent(Intent intent) {
- createNotification();
- unzip(intent);
- }
-
- private void createNotification() {
- // There are hardcoding only for show it's just strings
- String name = "com.multicraft.game";
- String channelId = "MultiCraft channel"; // The user-visible name of the channel.
- String description = "notifications from MultiCraft"; // The user-visible description of the channel.
- Notification.Builder builder;
- if (mNotifyManager == null)
- mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- if (isOreo()) {
- int importance = NotificationManager.IMPORTANCE_LOW;
- NotificationChannel mChannel = null;
- if (mNotifyManager != null)
- mChannel = mNotifyManager.getNotificationChannel(channelId);
- if (mChannel == null) {
- mChannel = new NotificationChannel(channelId, name, importance);
- mChannel.setDescription(description);
- // Configure the notification channel, NO SOUND
- mChannel.setSound(null, null);
- mChannel.enableLights(false);
- mChannel.enableVibration(false);
- mNotifyManager.createNotificationChannel(mChannel);
- }
- builder = new Notification.Builder(this, channelId);
- } else
- builder = new Notification.Builder(this);
- builder.setContentTitle(getString(R.string.notification_title))
- .setContentText(getString(R.string.notification_description))
- .setSmallIcon(R.drawable.update);
- mNotifyManager.notify(id, builder.build());
- }
-
- private void unzip(Intent intent) {
- ArrayList zips;
- if (intent != null)
- zips = intent.getStringArrayListExtra(EXTRA_KEY_IN_FILE);
- else
- zips = getZipsFromAssets(this);
- String cacheDir = getCacheDir().toString();
- int per = 0;
- int size = getSummarySize(zips, cacheDir);
- byte[] readBuffer = new byte[8192];
- for (String zip : zips) {
- String location = getLocationByZip(this, zip);
- File zipFile = new File(cacheDir, zip);
- ZipEntry ze;
- int readLen;
- try (FileInputStream fileInputStream = new FileInputStream(zipFile);
- ZipInputStream zipInputStream = new ZipInputStream(fileInputStream)) {
- while ((ze = zipInputStream.getNextEntry()) != null) {
- String fileName = ze.getName();
- if (ze.isDirectory()) {
- ++per;
- isDir(fileName, location);
- } else {
- File extractedFile = new File(location, fileName);
- publishProgress(100 * ++per / size);
- try (OutputStream outputStream = new FileOutputStream(extractedFile)) {
- while ((readLen = zipInputStream.read(readBuffer)) != -1) {
- outputStream.write(readBuffer, 0, readLen);
- }
- }
- }
- }
- } catch (IOException e) {
- if (!e.getLocalizedMessage().contains(NO_SPACE_LEFT))
- Bugsnag.notify(e);
- failureMessage = e.getLocalizedMessage();
- isSuccess = false;
- }
- }
- }
-
- private void publishProgress(int progress) {
- Intent intentUpdate = new Intent(ACTION_UPDATE);
- intentUpdate.putExtra(ACTION_PROGRESS, progress);
- if (!isSuccess) intentUpdate.putExtra(ACTION_FAILURE, failureMessage);
- sendBroadcast(intentUpdate);
- }
-
- private int getSummarySize(ArrayList zips, String path) {
- int size = 0;
- for (String z : zips) {
- try {
- ZipFile zipFile = new ZipFile(new File(path, z));
- size += zipFile.size();
- } catch (IOException e) {
- Bugsnag.notify(e);
- }
- }
- return size;
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mNotifyManager.cancel(id);
- publishProgress(isSuccess ? UNZIP_SUCCESS : UNZIP_FAILURE);
- }
-}
diff --git a/build/android/app/src/main/java/com/multicraft/game/helpers/ApiLevelHelper.java b/build/android/app/src/main/java/com/multicraft/game/helpers/ApiLevelHelper.java
deleted file mode 100644
index e97ff4da0..000000000
--- a/build/android/app/src/main/java/com/multicraft/game/helpers/ApiLevelHelper.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 3.0 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-package com.multicraft.game.helpers;
-
-import static android.os.Build.VERSION.SDK_INT;
-import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
-import static android.os.Build.VERSION_CODES.KITKAT;
-import static android.os.Build.VERSION_CODES.LOLLIPOP;
-import static android.os.Build.VERSION_CODES.O;
-import static android.os.Build.VERSION_CODES.Q;
-
-public class ApiLevelHelper {
- public static boolean isGreaterOrEqual(int versionCode) {
- return SDK_INT >= versionCode;
- }
-
- public static boolean isJellyBeanMR1() {
- return isGreaterOrEqual(JELLY_BEAN_MR1);
- }
-
- public static boolean isKitkat() {
- return isGreaterOrEqual(KITKAT);
- }
-
- public static boolean isLollipop() {
- return isGreaterOrEqual(LOLLIPOP);
- }
-
- public static boolean isOreo() {
- return isGreaterOrEqual(O);
- }
-
- public static boolean isAndroidQ() {
- return isGreaterOrEqual(Q);
- }
-}
diff --git a/build/android/app/src/main/java/com/multicraft/game/MyApplication.java b/build/android/app/src/main/java/com/multicraft/game/helpers/ApiLevelHelper.kt
similarity index 61%
rename from build/android/app/src/main/java/com/multicraft/game/MyApplication.java
rename to build/android/app/src/main/java/com/multicraft/game/helpers/ApiLevelHelper.kt
index 3972f78da..468932ee8 100644
--- a/build/android/app/src/main/java/com/multicraft/game/MyApplication.java
+++ b/build/android/app/src/main/java/com/multicraft/game/helpers/ApiLevelHelper.kt
@@ -1,7 +1,7 @@
/*
MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
+Copyright (C) 2014-2021 MoNTE48, Maksim Gamarnik
+Copyright (C) 2014-2021 ubulem, Bektur Mambetov
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -18,16 +18,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-package com.multicraft.game;
+package com.multicraft.game.helpers
-import androidx.multidex.MultiDexApplication;
+import android.os.Build.VERSION.SDK_INT
+import android.os.Build.VERSION_CODES.*
-import com.bugsnag.android.Bugsnag;
+object ApiLevelHelper {
+ private fun isGreaterOrEqual(versionCode: Int) = SDK_INT >= versionCode
-public class MyApplication extends MultiDexApplication {
- @Override
- public void onCreate() {
- super.onCreate();
- Bugsnag.start(this);
- }
+ fun isLollipop() = isGreaterOrEqual(LOLLIPOP)
+
+ fun isMarshmallow() = isGreaterOrEqual(M)
+
+ fun isOreo() = isGreaterOrEqual(O)
}
diff --git a/build/android/app/src/main/java/com/multicraft/game/helpers/Constants.java b/build/android/app/src/main/java/com/multicraft/game/helpers/Constants.java
deleted file mode 100644
index 688b4a0a6..000000000
--- a/build/android/app/src/main/java/com/multicraft/game/helpers/Constants.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 3.0 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-package com.multicraft.game.helpers;
-
-import com.multicraft.game.BuildConfig;
-
-public class Constants {
- public static final int REQUEST_CONNECTION = 104;
- public static final int REQUEST_UPDATE = 102;
- public static final int SESSION_COUNT = 5;
- public static final String NO_SPACE_LEFT = "ENOSPC";
- public static final String FILES = "Files.zip";
- public static final String GAMES = "games.zip";
- public static final int versionCode = BuildConfig.VERSION_CODE;
- public static final String versionName = BuildConfig.VERSION_NAME;
- public static final String appPackage = BuildConfig.APPLICATION_ID;
- public static final String UPDATE_LINK = "http://updates.multicraft.world/Android.json";
-}
diff --git a/build/android/app/src/main/java/com/multicraft/game/callbacks/CallBackListener.java b/build/android/app/src/main/java/com/multicraft/game/helpers/Constants.kt
similarity index 74%
rename from build/android/app/src/main/java/com/multicraft/game/callbacks/CallBackListener.java
rename to build/android/app/src/main/java/com/multicraft/game/helpers/Constants.kt
index 1a7bd889a..ac918cf50 100644
--- a/build/android/app/src/main/java/com/multicraft/game/callbacks/CallBackListener.java
+++ b/build/android/app/src/main/java/com/multicraft/game/helpers/Constants.kt
@@ -1,7 +1,7 @@
/*
MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
+Copyright (C) 2014-2021 MoNTE48, Maksim Gamarnik
+Copyright (C) 2014-2021 ubulem, Bektur Mambetov
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -18,8 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-package com.multicraft.game.callbacks;
+package com.multicraft.game.helpers
-public interface CallBackListener {
- void onEvent(boolean isContinue);
+object Constants {
+ const val REQUEST_CONNECTION = 104
+ const val NO_SPACE_LEFT = "ENOSPC"
}
diff --git a/build/android/app/src/main/java/com/multicraft/game/helpers/PermissionHelper.java b/build/android/app/src/main/java/com/multicraft/game/helpers/PermissionHelper.java
deleted file mode 100644
index e850294f3..000000000
--- a/build/android/app/src/main/java/com/multicraft/game/helpers/PermissionHelper.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
-MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 3.0 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-package com.multicraft.game.helpers;
-
-import android.annotation.SuppressLint;
-
-import androidx.appcompat.app.AppCompatActivity;
-
-import com.multicraft.game.R;
-import com.multicraft.game.callbacks.CallBackListener;
-import com.tedpark.tedpermission.rx2.TedRx2Permission;
-
-import static android.Manifest.permission.ACCESS_FINE_LOCATION;
-import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
-
-public class PermissionHelper {
- private final AppCompatActivity activity;
- private CallBackListener listener;
- private PreferencesHelper pf;
-
- public PermissionHelper(AppCompatActivity activity) {
- this.activity = activity;
- }
-
- public void setListener(CallBackListener listener) {
- this.listener = listener;
- }
-
- public void askPermissions() {
- pf = PreferencesHelper.getInstance(activity);
- askStoragePermissions();
- }
-
- // permission block
- @SuppressLint("CheckResult")
- private void askStoragePermissions() {
- TedRx2Permission.with(activity)
- .setPermissions(WRITE_EXTERNAL_STORAGE)
- .request()
- .subscribe(tedPermissionResult -> {
- if (tedPermissionResult.isGranted()) {
- if (pf.getLaunchTimes() % 3 == 1)
- askLocationPermissions();
- else listener.onEvent(true);
- } else {
- if (TedRx2Permission.canRequestPermission(activity, WRITE_EXTERNAL_STORAGE))
- askStorageRationalePermissions();
- else askStorageWhenDoNotShow();
- }
- });
- }
-
- // storage permissions block
- @SuppressLint("CheckResult")
- private void askStorageRationalePermissions() {
- TedRx2Permission.with(activity)
- .setRationaleMessage(R.string.explain)
- .setDeniedMessage(R.string.denied)
- .setDeniedCloseButtonText(R.string.close_game)
- .setGotoSettingButtonText(R.string.settings)
- .setPermissions(WRITE_EXTERNAL_STORAGE)
- .request()
- .subscribe(tedPermissionResult -> {
- if (tedPermissionResult.isGranted()) {
- if (pf.getLaunchTimes() % 3 == 1)
- askLocationPermissions();
- else listener.onEvent(true);
- } else {
- listener.onEvent(false);
- }
- });
- }
-
- @SuppressLint("CheckResult")
- private void askStorageWhenDoNotShow() {
- TedRx2Permission.with(activity)
- .setDeniedMessage(R.string.denied)
- .setDeniedCloseButtonText(R.string.close_game)
- .setGotoSettingButtonText(R.string.settings)
- .setPermissions(WRITE_EXTERNAL_STORAGE)
- .request()
- .subscribe(tedPermissionResult -> {
- if (tedPermissionResult.isGranted()) {
- if (pf.getLaunchTimes() % 3 == 1)
- askLocationPermissions();
- else listener.onEvent(true);
- } else {
- listener.onEvent(false);
- }
- });
- }
-
- // location permissions block
- @SuppressLint("CheckResult")
- private void askLocationPermissions() {
- TedRx2Permission.with(activity)
- .setPermissions(ACCESS_FINE_LOCATION)
- .request()
- .subscribe(tedPermissionResult -> {
- if (tedPermissionResult.isGranted()) {
- listener.onEvent(true);
- } else {
- if (TedRx2Permission.canRequestPermission(activity, ACCESS_FINE_LOCATION))
- askLocationRationalePermissions();
- else listener.onEvent(true);
- }
- });
- }
-
- @SuppressLint("CheckResult")
- private void askLocationRationalePermissions() {
- TedRx2Permission.with(activity)
- .setRationaleMessage(R.string.location)
- .setPermissions(ACCESS_FINE_LOCATION)
- .request()
- .subscribe(tedPermissionResult -> listener.onEvent(true));
- }
-}
diff --git a/build/android/app/src/main/java/com/multicraft/game/helpers/PreferenceHelper.kt b/build/android/app/src/main/java/com/multicraft/game/helpers/PreferenceHelper.kt
new file mode 100644
index 000000000..8857b9a47
--- /dev/null
+++ b/build/android/app/src/main/java/com/multicraft/game/helpers/PreferenceHelper.kt
@@ -0,0 +1,63 @@
+/*
+MultiCraft
+Copyright (C) 2014-2021 MoNTE48, Maksim Gamarnik
+Copyright (C) 2014-2021 ubulem, Bektur Mambetov
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 3.0 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+package com.multicraft.game.helpers
+
+import android.content.Context
+import android.content.SharedPreferences
+
+object PreferenceHelper {
+ const val TAG_SHORTCUT_EXIST = "createShortcut"
+ const val TAG_BUILD_VER = "buildVer"
+ const val TAG_LAUNCH_TIMES = "launchTimes"
+
+ fun init(context: Context): SharedPreferences =
+ context.getSharedPreferences("MultiCraftSettings", Context.MODE_PRIVATE)
+
+ private inline fun SharedPreferences.edit(operation: (SharedPreferences.Editor) -> Unit) {
+ val editor = this.edit()
+ operation(editor)
+ editor.apply()
+ }
+
+ operator fun SharedPreferences.set(key: String, value: Any?) = when (value) {
+ is String? -> edit { it.putString(key, value) }
+ is Int -> edit { it.putInt(key, value) }
+ is Boolean -> edit { it.putBoolean(key, value) }
+ is Float -> edit { it.putFloat(key, value) }
+ is Long -> edit { it.putLong(key, value) }
+ else -> throw UnsupportedOperationException("Not yet implemented")
+ }
+
+ fun SharedPreferences.getBoolValue(key: String): Boolean = when (key) {
+ TAG_SHORTCUT_EXIST -> getBoolean(key, false)
+ else -> throw UnsupportedOperationException("Not yet implemented")
+ }
+
+ fun SharedPreferences.getIntValue(key: String) = when (key) {
+ TAG_LAUNCH_TIMES -> getInt(key, 0)
+ else -> throw UnsupportedOperationException("Not yet implemented")
+ }
+
+ fun SharedPreferences.getStringValue(key: String) = when (key) {
+ TAG_BUILD_VER -> getString(key, "0") as String
+ else -> throw UnsupportedOperationException("Not yet implemented")
+ }
+}
diff --git a/build/android/app/src/main/java/com/multicraft/game/helpers/PreferencesHelper.java b/build/android/app/src/main/java/com/multicraft/game/helpers/PreferencesHelper.java
deleted file mode 100644
index 4313eae5d..000000000
--- a/build/android/app/src/main/java/com/multicraft/game/helpers/PreferencesHelper.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 3.0 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-package com.multicraft.game.helpers;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-
-public class PreferencesHelper {
- public static final String TAG_SHORTCUT_EXIST = "createShortcut";
- public static final String TAG_BUILD_NUMBER = "buildNumber";
- public static final String TAG_LAUNCH_TIMES = "launchTimes";
- public static final String TAG_COPY_OLD_WORLDS = "copyOldWorlds";
- public static final String TAG_LAST_RATE_VERSION_CODE = "lastRateVersionCode";
- public static final String TAG_RATE_MIN_VERSION_CODE = "rateMinVersionCode";
- public static final String TAG_EXIT_GAME_COUNT = "exitGameCount";
- public static final String TAG_REVIEW_ENABLE = "reviewEnable";
- public static final String TAG_OPT_OUT = "optOut";
- public static final String IS_ASK_CONSENT = "isAskConsent";
- public static final String IS_LOADED = "interstitialLoaded";
- public static final String RV_LOADED = "rewardedVideoLoaded";
- public static final String ADS_DELAY = "adsDelay";
- public static final String ADS_REPEAT = "adsRepeat";
- public static final String ADS_ENABLE = "adsEnable";
- private static final String SETTINGS = "MultiCraftSettings";
-
- private static PreferencesHelper instance;
- private static SharedPreferences sharedPreferences;
-
- private PreferencesHelper(Context context) {
- sharedPreferences = context.getSharedPreferences(SETTINGS, Context.MODE_PRIVATE);
- }
-
- public static PreferencesHelper getInstance(Context context) {
- if (instance == null) {
- synchronized (PreferencesHelper.class) {
- if (instance == null)
- instance = new PreferencesHelper(context.getApplicationContext());
- }
- }
- return instance;
- }
-
- public boolean isCreateShortcut() {
- return sharedPreferences.getBoolean(TAG_SHORTCUT_EXIST, false);
- }
-
- public boolean isInterstitialLoaded() {
- return sharedPreferences.getBoolean(IS_LOADED, false);
- }
-
- public boolean isVideoLoaded() {
- return sharedPreferences.getBoolean(RV_LOADED, false);
- }
-
- public boolean isAskConsent() {
- return sharedPreferences.getBoolean(IS_ASK_CONSENT, true);
- }
-
- public boolean isWorldsCopied() {
- return sharedPreferences.getBoolean(TAG_COPY_OLD_WORLDS, false);
- }
-
- public String getBuildNumber() {
- return sharedPreferences.getString(TAG_BUILD_NUMBER, "0");
- }
-
- public int getLaunchTimes() {
- return sharedPreferences.getInt(TAG_LAUNCH_TIMES, 0);
- }
-
- public int getLastRateVersionCode() {
- return sharedPreferences.getInt(TAG_LAST_RATE_VERSION_CODE, 0);
- }
-
- public int getRateMinVersionCode() {
- return sharedPreferences.getInt(TAG_RATE_MIN_VERSION_CODE, 0);
- }
-
- public int getExitGameCount() {
- return sharedPreferences.getInt(TAG_EXIT_GAME_COUNT, 0);
- }
-
- public int getAdsDelay() {
- return sharedPreferences.getInt(ADS_DELAY, 600);
- }
-
- public int getAdsRepeat() {
- return sharedPreferences.getInt(ADS_REPEAT, 900);
- }
-
- public boolean isAdsEnable() {
- return sharedPreferences.getBoolean(ADS_ENABLE, true);
- }
-
- public boolean isReviewEnable() {
- return sharedPreferences.getBoolean(TAG_REVIEW_ENABLE, true);
- }
-
- public boolean isOptOut() {
- return sharedPreferences.getBoolean(TAG_OPT_OUT, false);
- }
-
- public void saveSettings(String tag, boolean bool) {
- sharedPreferences.edit().putBoolean(tag, bool).apply();
- }
-
- public void saveSettings(String tag, String value) {
- sharedPreferences.edit().putString(tag, value).apply();
- }
-
- public void saveSettings(String tag, int value) {
- sharedPreferences.edit().putInt(tag, value).apply();
- }
-}
diff --git a/build/android/app/src/main/java/com/multicraft/game/helpers/RateMeHelper.java b/build/android/app/src/main/java/com/multicraft/game/helpers/RateMeHelper.java
deleted file mode 100644
index 9dc014ca7..000000000
--- a/build/android/app/src/main/java/com/multicraft/game/helpers/RateMeHelper.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 3.0 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-package com.multicraft.game.helpers;
-
-import android.app.Dialog;
-import android.app.NativeActivity;
-import android.content.Intent;
-import android.net.Uri;
-import android.view.View;
-import android.widget.RatingBar;
-import android.widget.Toast;
-
-import com.multicraft.game.R;
-
-import static com.multicraft.game.helpers.ApiLevelHelper.isKitkat;
-import static com.multicraft.game.helpers.Constants.SESSION_COUNT;
-import static com.multicraft.game.helpers.PreferencesHelper.TAG_OPT_OUT;
-import static com.multicraft.game.helpers.Utilities.getStoreUrl;
-
-public class RateMeHelper {
- private static PreferencesHelper pf;
-
- public static void onStart(NativeActivity activity) {
- pf = PreferencesHelper.getInstance(activity);
- }
-
- private static boolean isEnoughTimePassed() {
- return (pf.getLastRateVersionCode() == 0) && pf.getLaunchTimes() >= SESSION_COUNT
- && pf.getExitGameCount() >= SESSION_COUNT;
- }
-
- private static boolean isWorthToReview() {
- return (pf.getLastRateVersionCode() != 0)
- && pf.getRateMinVersionCode() > pf.getLastRateVersionCode();
- }
-
- public static boolean shouldAskForReview() {
- return pf.isReviewEnable() && (isEnoughTimePassed() || isWorthToReview());
- }
-
- public static boolean shouldShowRateDialog() {
- if (pf.isOptOut())
- return false;
- else {
- return shouldAskForReview();
- }
- }
-
- public static void showRateDialog(NativeActivity activity) {
- final Dialog dialog = new Dialog(activity, R.style.RateMe);
- dialog.setCancelable(false);
- if (isKitkat())
- dialog.getWindow().getDecorView().setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
- dialog.setContentView(R.layout.rate_dialog);
- RatingBar ratingBar = dialog.findViewById(R.id.ratingBar);
- ratingBar.setOnRatingBarChangeListener((ratingBar1, rating, fromUser) -> {
- if (rating >= 4) {
- try {
- Toast.makeText(activity, R.string.thank, Toast.LENGTH_LONG).show();
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getStoreUrl()));
- activity.startActivity(intent);
- } catch (Exception e) {
- // nothing
- }
- dialog.dismiss();
- pf.saveSettings(TAG_OPT_OUT, true);
- } else {
- dialog.dismiss();
- Toast.makeText(activity, R.string.sad, Toast.LENGTH_LONG).show();
- }
- });
- if (!activity.isFinishing())
- dialog.show();
- }
-}
diff --git a/build/android/app/src/main/java/com/multicraft/game/helpers/Utilities.java b/build/android/app/src/main/java/com/multicraft/game/helpers/Utilities.java
deleted file mode 100644
index cca528ff9..000000000
--- a/build/android/app/src/main/java/com/multicraft/game/helpers/Utilities.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
-MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 3.0 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-package com.multicraft.game.helpers;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-
-import com.bugsnag.android.Bugsnag;
-import com.multicraft.game.MainActivity;
-import com.multicraft.game.R;
-
-import org.apache.commons.io.FileUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.Response;
-
-import static android.os.Environment.getExternalStorageDirectory;
-import static com.multicraft.game.helpers.ApiLevelHelper.isKitkat;
-import static com.multicraft.game.helpers.Constants.FILES;
-import static com.multicraft.game.helpers.Constants.GAMES;
-import static com.multicraft.game.helpers.Constants.appPackage;
-import static com.multicraft.game.helpers.PreferencesHelper.TAG_SHORTCUT_EXIST;
-
-public class Utilities {
- private static boolean isInternetAvailable(String url) {
- try {
- HttpURLConnection urlc =
- (HttpURLConnection) new URL(url).openConnection();
- urlc.setRequestProperty("Connection", "close");
- urlc.setConnectTimeout(2000);
- urlc.connect();
- int ResponseCode = urlc.getResponseCode();
- return ResponseCode == HttpURLConnection.HTTP_NO_CONTENT ||
- ResponseCode == HttpURLConnection.HTTP_OK;
- } catch (IOException e) {
- return false;
- }
- }
-
- public static boolean isReachable() {
- return isInternetAvailable("http://clients3.google.com/generate_204") ||
- isInternetAvailable("http://servers.multicraft.world");
- }
-
- public static void deleteFiles(List files, String path) {
- for (String f : files) {
- File file = new File(path, f);
- if (file.exists())
- FileUtils.deleteQuietly(file);
- }
- }
-
- public static void deleteFiles(List files) {
- for (File file : files) {
- if (file != null && file.exists())
- FileUtils.deleteQuietly(file);
- }
- }
-
- public static String getStoreUrl() {
- return "market://details?id=" + appPackage;
- }
-
- public static void makeFullScreen(Activity activity) {
- if (isKitkat())
- activity.getWindow().getDecorView().setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
- }
-
- public static Drawable getIcon(Activity activity) {
- try {
- return activity.getPackageManager().getApplicationIcon(activity.getPackageName());
- } catch (PackageManager.NameNotFoundException e) {
- Bugsnag.notify(e);
- return activity.getResources().getDrawable(R.mipmap.ic_launcher);
- }
- }
-
- public static void addShortcut(Activity activity) {
- ActivityManager activityManager =
- (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
- int size = 0;
- if (activityManager != null)
- size = activityManager.getLauncherLargeIconSize();
- Bitmap shortcutIconBitmap = ((BitmapDrawable) getIcon(activity)).getBitmap();
- if (shortcutIconBitmap.getWidth() != size || shortcutIconBitmap.getHeight() != size)
- shortcutIconBitmap = Bitmap.createScaledBitmap(shortcutIconBitmap, size, size, true);
- PreferencesHelper.getInstance(activity).saveSettings(TAG_SHORTCUT_EXIST, true);
- Intent shortcutIntent = new Intent(activity, MainActivity.class);
- shortcutIntent.setAction(Intent.ACTION_MAIN);
- Intent addIntent = new Intent();
- addIntent.putExtra("duplicate", false);
- addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
- addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, activity.getResources().getString(R.string.app_name));
- addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, shortcutIconBitmap);
- addIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
- activity.getApplicationContext().sendBroadcast(addIntent);
- }
-
- public static String getJson(String url) {
- OkHttpClient client = new OkHttpClient.Builder()
- .callTimeout(3000, TimeUnit.MILLISECONDS)
- .build();
- Request request = new Request.Builder()
- .url(url)
- .build();
- try {
- Response response = client.newCall(request).execute();
- return response.body().string();
- } catch (IOException | NullPointerException e) {
- return "{}";
- }
- }
-
- public static String getLocationByZip(Context context, String zipName) {
- String path;
- switch (zipName) {
- case FILES:
- case GAMES:
- path = context.getFilesDir().toString();
- break;
- default:
- throw new IllegalArgumentException("No such zip name");
- }
- return path;
- }
-
- public static ArrayList getZipsFromAssets(Context context) {
- try {
- return new ArrayList<>(Arrays.asList(context.getAssets().list("data")));
- } catch (IOException e) {
- return new ArrayList<>(Arrays.asList(FILES, GAMES));
- }
- }
-}
diff --git a/build/android/app/src/main/java/com/multicraft/game/helpers/Utilities.kt b/build/android/app/src/main/java/com/multicraft/game/helpers/Utilities.kt
new file mode 100644
index 000000000..b213044e5
--- /dev/null
+++ b/build/android/app/src/main/java/com/multicraft/game/helpers/Utilities.kt
@@ -0,0 +1,140 @@
+/*
+MultiCraft
+Copyright (C) 2014-2021 MoNTE48, Maksim Gamarnik
+Copyright (C) 2014-2021 ubulem, Bektur Mambetov
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 3.0 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+package com.multicraft.game.helpers
+
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.app.ActivityManager
+import android.app.AlarmManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.Bitmap
+import android.graphics.drawable.BitmapDrawable
+import android.net.ConnectivityManager
+import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
+import android.view.View
+import android.view.Window
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsCompat.Type.navigationBars
+import androidx.core.view.WindowInsetsCompat.Type.statusBars
+import androidx.core.view.WindowInsetsControllerCompat
+import androidx.core.view.WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+import com.multicraft.game.MainActivity
+import com.multicraft.game.R
+import com.multicraft.game.helpers.ApiLevelHelper.isLollipop
+import com.multicraft.game.helpers.ApiLevelHelper.isMarshmallow
+import com.multicraft.game.helpers.ApiLevelHelper.isOreo
+import com.multicraft.game.helpers.PreferenceHelper.TAG_SHORTCUT_EXIST
+import com.multicraft.game.helpers.PreferenceHelper.set
+import java.io.File
+import java.io.InputStream
+import kotlin.math.roundToInt
+import kotlin.system.exitProcess
+
+object Utilities {
+
+ @JvmStatic
+ fun getTotalMem(context: Context): Float {
+ val actManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+ val memInfo = ActivityManager.MemoryInfo()
+ actManager.getMemoryInfo(memInfo)
+ var memory = memInfo.totalMem * 1.0f / (1024 * 1024 * 1024)
+ memory = (memory * 100).roundToInt() / 100.0f
+ return memory
+ }
+
+ @JvmStatic
+ fun makeFullScreen(window: Window) {
+ if (isLollipop()) {
+ WindowCompat.setDecorFitsSystemWindows(window, false)
+ WindowInsetsControllerCompat(window, window.decorView).let {
+ it.hide(statusBars() or navigationBars())
+ it.systemBarsBehavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+ }
+ } else @Suppress("DEPRECATION") {
+ val decor = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ window.decorView.systemUiVisibility = decor
+ }
+ }
+
+ fun getIcon(activity: Activity) = try {
+ activity.packageManager.getApplicationIcon(activity.packageName)
+ } catch (e: PackageManager.NameNotFoundException) {
+ ContextCompat.getDrawable(activity, R.mipmap.ic_launcher)
+ }
+
+ @Suppress("DEPRECATION")
+ fun addShortcut(activity: AppCompatActivity) {
+ if (isOreo()) return
+ val activityManager = activity.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+ val size = activityManager.launcherLargeIconSize
+ var shortcutIconBitmap = (getIcon(activity) as BitmapDrawable).bitmap
+ if (shortcutIconBitmap.width != size || shortcutIconBitmap.height != size)
+ shortcutIconBitmap = Bitmap.createScaledBitmap(shortcutIconBitmap, size, size, true)
+ val shortcutIntent = Intent(activity, MainActivity::class.java)
+ shortcutIntent.action = Intent.ACTION_MAIN
+ val addIntent = Intent()
+ addIntent.putExtra("duplicate", false)
+ addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent)
+ addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, R.string.app_name)
+ addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, shortcutIconBitmap)
+ addIntent.action = "com.android.launcher.action.INSTALL_SHORTCUT"
+ activity.applicationContext.sendBroadcast(addIntent)
+ // save preference
+ PreferenceHelper.init(activity)[TAG_SHORTCUT_EXIST] = true
+ }
+
+ @JvmStatic
+ fun finishApp(restart: Boolean, activity: Activity) {
+ if (restart) @SuppressLint("UnspecifiedImmutableFlag") {
+ val intent = Intent(activity, activity::class.java)
+ val mPendingIntentId = 1337
+ val mgr = activity.getSystemService(Context.ALARM_SERVICE) as AlarmManager
+ mgr.set(
+ AlarmManager.RTC, System.currentTimeMillis(), PendingIntent.getActivity(
+ activity, mPendingIntentId, intent, PendingIntent.FLAG_CANCEL_CURRENT
+ )
+ )
+ }
+ exitProcess(0)
+ }
+
+ fun File.copyInputStreamToFile(inputStream: InputStream) =
+ this.outputStream().use { fileOut -> inputStream.copyTo(fileOut, 8192) }
+
+ fun isConnected(context: Context): Boolean {
+ val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+ if (isMarshmallow()) {
+ val activeNetwork = cm.activeNetwork ?: return false
+ val capabilities = cm.getNetworkCapabilities(activeNetwork) ?: return false
+ return capabilities.hasCapability(NET_CAPABILITY_VALIDATED)
+ } else @Suppress("DEPRECATION") {
+ val activeNetworkInfo = cm.activeNetworkInfo ?: return false
+ return activeNetworkInfo.isConnected
+ }
+ }
+}
diff --git a/build/android/app/src/main/java/com/multicraft/game/helpers/VersionManagerHelper.java b/build/android/app/src/main/java/com/multicraft/game/helpers/VersionManagerHelper.java
deleted file mode 100644
index e2bbfc491..000000000
--- a/build/android/app/src/main/java/com/multicraft/game/helpers/VersionManagerHelper.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
-MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 3.0 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-package com.multicraft.game.helpers;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.text.Editable;
-import android.text.Html;
-
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.preference.PreferenceManager;
-
-import com.google.gson.Gson;
-import com.multicraft.game.JsonSettings;
-
-import org.xml.sax.XMLReader;
-
-import java.util.Calendar;
-import java.util.List;
-import java.util.Locale;
-
-import static com.multicraft.game.helpers.Constants.versionCode;
-import static com.multicraft.game.helpers.PreferencesHelper.ADS_DELAY;
-import static com.multicraft.game.helpers.PreferencesHelper.ADS_ENABLE;
-import static com.multicraft.game.helpers.PreferencesHelper.ADS_REPEAT;
-import static com.multicraft.game.helpers.PreferencesHelper.TAG_RATE_MIN_VERSION_CODE;
-import static com.multicraft.game.helpers.PreferencesHelper.TAG_REVIEW_ENABLE;
-import static com.multicraft.game.helpers.Utilities.getStoreUrl;
-
-public class VersionManagerHelper {
- private final CustomTagHandler customTagHandler;
- private final String PREF_REMINDER_TIME = "w.reminder.time";
- private final AppCompatActivity activity;
- private String message, updateUrl;
-
- public VersionManagerHelper(AppCompatActivity act) {
- this.activity = act;
- this.customTagHandler = new CustomTagHandler();
- }
-
- public boolean isCheckVersion() {
- long currentTimeStamp = Calendar.getInstance().getTimeInMillis();
- long reminderTimeStamp = getReminderTime();
- return currentTimeStamp > reminderTimeStamp;
- }
-
- private boolean isBadVersion(List badVersions) {
- return badVersions.contains(versionCode);
- }
-
- private JsonSettings parseJson(String result) {
- JsonSettings settings = new Gson().fromJson(result, JsonSettings.class);
- String lang = Locale.getDefault().getLanguage();
- String content = lang.equals("ru") ? settings.getContentRus() : settings.getContentEng();
- setMessage(content);
- setUpdateUrl("market://details?id=" + settings.getPackageName());
- savePrefSettings(settings);
- return settings;
- }
-
- private void savePrefSettings(JsonSettings settings) {
- PreferencesHelper pf = PreferencesHelper.getInstance(activity);
- pf.saveSettings(TAG_RATE_MIN_VERSION_CODE, settings.getRateMinVersionCode());
- pf.saveSettings(TAG_REVIEW_ENABLE, settings.isReviewEnabled());
- pf.saveSettings(ADS_DELAY, settings.getAdsDelay());
- pf.saveSettings(ADS_REPEAT, settings.getAdsRepeat());
- pf.saveSettings(ADS_ENABLE, settings.isAdsEnabled());
- }
-
- public boolean isShow(String result) {
- if (result.equals("{}")) return false;
- JsonSettings jsonSettings = parseJson(result);
- return (versionCode < jsonSettings.getVersionCode()) ||
- isBadVersion(jsonSettings.getBadVersionCodes());
- }
-
- public String getMessage() {
- String defaultMessage = "What's new?";
- return message != null ? message : defaultMessage;
- }
-
- private void setMessage(String message) {
- this.message = message;
- }
-
- public String getUpdateUrl() {
- return updateUrl != null ? updateUrl : getStoreUrl();
- }
-
- private void setUpdateUrl(String updateUrl) {
- this.updateUrl = updateUrl;
- }
-
- public void updateNow(String url) {
- if (url != null) {
- try {
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- activity.startActivity(intent);
- } catch (Exception e) {
- // nothing
- }
- }
- }
-
- public void remindMeLater() {
- Calendar c = Calendar.getInstance();
- c.add(Calendar.MINUTE, 1);
- long reminderTimeStamp = c.getTimeInMillis();
- setReminderTime(reminderTimeStamp);
- }
-
- private long getReminderTime() {
- return PreferenceManager.getDefaultSharedPreferences(activity).getLong(
- PREF_REMINDER_TIME, 0);
- }
-
- private void setReminderTime(long reminderTimeStamp) {
- PreferenceManager.getDefaultSharedPreferences(activity).edit().putLong(
- PREF_REMINDER_TIME, reminderTimeStamp).apply();
- }
-
- public CustomTagHandler getCustomTagHandler() {
- return customTagHandler;
- }
-
- private static class CustomTagHandler implements Html.TagHandler {
- @Override
- public void handleTag(boolean opening, String tag, Editable output,
- XMLReader xmlReader) {
- // you may add more tag handler which are not supported by android here
- if ("li".equals(tag)) {
- if (opening)
- output.append(" \u2022 ");
- else
- output.append("\n");
- }
- }
- }
-}
diff --git a/build/android/app/src/main/java/com/multicraft/game/workmanager/UnzipWorker.kt b/build/android/app/src/main/java/com/multicraft/game/workmanager/UnzipWorker.kt
new file mode 100644
index 000000000..8a7edcb64
--- /dev/null
+++ b/build/android/app/src/main/java/com/multicraft/game/workmanager/UnzipWorker.kt
@@ -0,0 +1,103 @@
+/*
+MultiCraft
+Copyright (C) 2014-2021 MoNTE48, Maksim Gamarnik
+Copyright (C) 2014-2021 ubulem, Bektur Mambetov
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 3.0 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+package com.multicraft.game.workmanager
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.Context
+import android.content.Context.NOTIFICATION_SERVICE
+import androidx.core.app.NotificationCompat
+import androidx.work.CoroutineWorker
+import androidx.work.ForegroundInfo
+import androidx.work.WorkerParameters
+import androidx.work.workDataOf
+import com.multicraft.game.R
+import com.multicraft.game.helpers.ApiLevelHelper.isOreo
+import com.multicraft.game.helpers.Utilities.copyInputStreamToFile
+import java.io.File
+import java.io.IOException
+import java.util.zip.ZipFile
+
+class UnzipWorker(private val appContext: Context, workerParams: WorkerParameters) :
+ CoroutineWorker(appContext, workerParams) {
+
+ private fun createForegroundInfo(): ForegroundInfo {
+ if (isOreo()) {
+ val importance = NotificationManager.IMPORTANCE_DEFAULT
+ val mChannel = NotificationChannel(CHANNEL_ID, CHANNEL_NAME, importance)
+ mChannel.setSound(null, null)
+ mChannel.description = CHANNEL_DESC
+ val notificationManager =
+ appContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
+ notificationManager.createNotificationChannel(mChannel)
+ }
+
+ val notification = NotificationCompat.Builder(applicationContext, CHANNEL_ID)
+ .setContentTitle(appContext.getString(R.string.notification_title))
+ .setContentText(appContext.getString(R.string.notification_description))
+ .setSmallIcon(R.drawable.update)
+ .build()
+ return ForegroundInfo(NOTIFICATION_ID, notification)
+ }
+
+ override suspend fun doWork(): Result {
+ val zips = inputData.getStringArray(EXTRA_KEY_IN_FILE)!!
+ setForeground(createForegroundInfo())
+ var previousProgress = 0
+ return try {
+ var per = 0
+ val zipList = zips.map { ZipFile(File(appContext.cacheDir, it)) }
+ val size = zipList.sumOf { it.size() }
+ zipList.forEach { zip ->
+ zip.use {
+ it.entries().asSequence().forEach { entry ->
+ zip.getInputStream(entry).use { input ->
+ val filePath = File(appContext.filesDir, entry.name)
+ if (entry.isDirectory)
+ filePath.mkdirs()
+ else
+ filePath.copyInputStreamToFile(input)
+ val currentProgress = 100 * ++per / size
+ if (currentProgress > previousProgress) {
+ previousProgress = currentProgress
+ setProgress(workDataOf(PROGRESS to currentProgress))
+ }
+ }
+ }
+ }
+ }
+ Result.success()
+ } catch (e: IOException) {
+ Result.failure()
+ } finally {
+ zips.forEach { File(appContext.cacheDir, it).delete() }
+ }
+ }
+
+ companion object {
+ const val PROGRESS = "progress"
+ const val NOTIFICATION_ID = 1
+ const val CHANNEL_ID = "MultiCraft channel"
+ const val CHANNEL_NAME = "com.multicraft.game"
+ const val CHANNEL_DESC = "Notifications from MultiCraft"
+ const val EXTRA_KEY_IN_FILE = "com.multicraft.game.file"
+ }
+}
diff --git a/build/android/app/src/main/java/com/multicraft/game/workmanager/WorkerViewModel.kt b/build/android/app/src/main/java/com/multicraft/game/workmanager/WorkerViewModel.kt
new file mode 100644
index 000000000..35724059f
--- /dev/null
+++ b/build/android/app/src/main/java/com/multicraft/game/workmanager/WorkerViewModel.kt
@@ -0,0 +1,55 @@
+/*
+MultiCraft
+Copyright (C) 2014-2021 MoNTE48, Maksim Gamarnik
+Copyright (C) 2014-2021 ubulem, Bektur Mambetov
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 3.0 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+package com.multicraft.game.workmanager
+
+import android.app.Application
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.LiveData
+import androidx.work.OneTimeWorkRequest
+import androidx.work.WorkInfo
+import androidx.work.WorkManager
+import androidx.work.workDataOf
+import com.multicraft.game.workmanager.UnzipWorker.Companion.EXTRA_KEY_IN_FILE
+
+class WorkerViewModel(
+ application: Application,
+ private val zips: Array
+) :
+ AndroidViewModel(application) {
+
+ private val mWorkManager: WorkManager by lazy { WorkManager.getInstance(application) }
+
+ val unzippingWorkObserver: LiveData by lazy {
+ mWorkManager.getWorkInfoByIdLiveData(
+ unzippingWorkReq.id
+ )
+ }
+
+ private val unzippingWorkReq: OneTimeWorkRequest by lazy {
+ OneTimeWorkRequest.Builder(UnzipWorker::class.java)
+ .setInputData(workDataOf(EXTRA_KEY_IN_FILE to zips))
+ .build()
+ }
+
+ fun startOneTimeWorkRequest() {
+ mWorkManager.enqueue(unzippingWorkReq)
+ }
+}
diff --git a/build/android/app/src/main/java/com/multicraft/game/helpers/AdManager.java b/build/android/app/src/main/java/com/multicraft/game/workmanager/WorkerViewModelFactory.kt
similarity index 51%
rename from build/android/app/src/main/java/com/multicraft/game/helpers/AdManager.java
rename to build/android/app/src/main/java/com/multicraft/game/workmanager/WorkerViewModelFactory.kt
index 0eb087543..1547c6b27 100644
--- a/build/android/app/src/main/java/com/multicraft/game/helpers/AdManager.java
+++ b/build/android/app/src/main/java/com/multicraft/game/workmanager/WorkerViewModelFactory.kt
@@ -1,7 +1,7 @@
/*
MultiCraft
-Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik
-Copyright (C) 2014-2020 ubulem, Bektur Mambetov
+Copyright (C) 2014-2021 MoNTE48, Maksim Gamarnik
+Copyright (C) 2014-2021 ubulem, Bektur Mambetov
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -18,24 +18,23 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-package com.multicraft.game.helpers;
+package com.multicraft.game.workmanager
-import android.app.Activity;
+import android.app.Application
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
-public class AdManager {
- public static void initAd(final Activity activity, boolean consent) {
- // NDA code here
- }
- public static void setAdsCallback(final Activity activity) {
- // NDA code here
- }
-
- public static void startAd(final Activity activity, boolean isFirstTime, boolean isShowNow) {
- // NDA code here
- }
-
- public static void stopAd() {
- // NDA code here
+class WorkerViewModelFactory(
+ private val application: Application,
+ private val zips: Array
+) :
+ ViewModelProvider.Factory {
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(WorkerViewModel::class.java)) {
+ @Suppress("UNCHECKED_CAST")
+ return WorkerViewModel(application, zips) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class")
}
}
diff --git a/build/android/app/src/main/res/drawable/background.png b/build/android/app/src/main/res/drawable/background.png
index 55afbb6f4..84f1fd4c6 100644
Binary files a/build/android/app/src/main/res/drawable/background.png and b/build/android/app/src/main/res/drawable/background.png differ
diff --git a/build/android/app/src/main/res/drawable/custom_dialog_rounded.xml b/build/android/app/src/main/res/drawable/custom_dialog_rounded.xml
deleted file mode 100644
index f5e0ff00c..000000000
--- a/build/android/app/src/main/res/drawable/custom_dialog_rounded.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
diff --git a/build/android/app/src/main/res/drawable/custom_edittext_rounded.xml b/build/android/app/src/main/res/drawable/custom_edittext_rounded.xml
deleted file mode 100644
index d72c57859..000000000
--- a/build/android/app/src/main/res/drawable/custom_edittext_rounded.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
- -
-
-
-
-
-
-
-
-
diff --git a/build/android/app/src/main/res/drawable/custom_progress_bar.xml b/build/android/app/src/main/res/drawable/custom_progress_bar.xml
index da5ed98b9..bc8e70538 100644
--- a/build/android/app/src/main/res/drawable/custom_progress_bar.xml
+++ b/build/android/app/src/main/res/drawable/custom_progress_bar.xml
@@ -1,6 +1,6 @@
- -
+
-
- -
+
-
diff --git a/build/android/app/src/main/res/drawable/ic_launcher_background.xml b/build/android/app/src/main/res/drawable/ic_launcher_background.xml
deleted file mode 100644
index fe5102ec9..000000000
--- a/build/android/app/src/main/res/drawable/ic_launcher_background.xml
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/build/android/app/src/main/res/font/retron2000.ttf b/build/android/app/src/main/res/font/retron2000.ttf
new file mode 100644
index 000000000..f30c7e1b7
Binary files /dev/null and b/build/android/app/src/main/res/font/retron2000.ttf differ
diff --git a/build/android/app/src/main/res/layout/activity_main.xml b/build/android/app/src/main/res/layout/activity_main.xml
index 4778e3ec2..2b88a76a4 100644
--- a/build/android/app/src/main/res/layout/activity_main.xml
+++ b/build/android/app/src/main/res/layout/activity_main.xml
@@ -1,12 +1,10 @@
+ android:indeterminate="true" />
+ android:textColor="@color/not_white"
+ android:textSize="14sp" />
diff --git a/build/android/app/src/main/res/layout/input_text.xml b/build/android/app/src/main/res/layout/input_text.xml
new file mode 100644
index 000000000..a27bf6e29
--- /dev/null
+++ b/build/android/app/src/main/res/layout/input_text.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/build/android/app/src/main/res/layout/rate_dialog.xml b/build/android/app/src/main/res/layout/rate_dialog.xml
deleted file mode 100644
index e0515207d..000000000
--- a/build/android/app/src/main/res/layout/rate_dialog.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/build/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/build/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
index 110fbe9e0..4f0acc753 100644
--- a/build/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ b/build/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/build/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/build/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
index 110fbe9e0..4f0acc753 100644
--- a/build/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ b/build/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/build/android/app/src/main/res/mipmap-v25/ic_launcher_round.png b/build/android/app/src/main/res/mipmap-v25/ic_launcher_round.png
index 1751f0996..3845cc634 100644
Binary files a/build/android/app/src/main/res/mipmap-v25/ic_launcher_round.png and b/build/android/app/src/main/res/mipmap-v25/ic_launcher_round.png differ
diff --git a/build/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_foreground.png b/build/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_foreground.png
index 3039b99ec..9501d49f9 100644
Binary files a/build/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_foreground.png and b/build/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_foreground.png differ
diff --git a/build/android/app/src/main/res/mipmap/ic_launcher.png b/build/android/app/src/main/res/mipmap/ic_launcher.png
index 42c24d582..1774761ff 100644
Binary files a/build/android/app/src/main/res/mipmap/ic_launcher.png and b/build/android/app/src/main/res/mipmap/ic_launcher.png differ
diff --git a/build/android/app/src/main/res/values-ru/strings.xml b/build/android/app/src/main/res/values-ru/strings.xml
index ea3f62842..4f20a0e49 100644
--- a/build/android/app/src/main/res/values-ru/strings.xml
+++ b/build/android/app/src/main/res/values-ru/strings.xml
@@ -1,44 +1,22 @@
-
Подготовка к запуску…
Загрузка…
Загрузка… %d%%
- Загрузка новой версии…
- Загрузка новой версии… %d%%
Загрузка MultiCraft
Осталось меньше минуты…
Произошла ошибка, игра будет перезапущена автоматически
Недостаточно места для записи файлов игры, пожалуйста освободите место в памяти
-
- Разрешение на запись необходимо для распаковки текстур и игровых файлов.
- Доступ к местоположению обеспечивает Вам лучшее взаимодействие с игрой
- Закрыть игру
- Настройки
- Вы не можете играть в MultiCraft без разрешения на запись.\nПожалуйста, включите его в [Настройки] -> [Разрешения]>
-
-
- Оцените MultiCraft!
- Поделитесь впечатлениями
- ОЦЕНИТЬ
- Нам жаль, что Вам не понравилась игра!
- Пожалуйста, оставьте отзыв для нас. Спасибо!
-
- Загрузка\nрекомендации\nдля Вас:\n%d сек.
-
-
- Доступна Новая Версия!
- Игнорировать
- Позже
- Обновить
+ Введите Текст
+ Пароль
+ Готово
- Для полноценной игры, MultiCraft требует подключение к интернету.\nВ противном случае невозможно обновление игры, а так же не доступен мультиплеер!
+ Нет Интернет Подключения!
+ Для полноценной игры, MultiCraft требует подключение к Интернету.\nВ противном случае вам будет недоступно Обновление игры и режим Мультиплеера!
3G/4G
-
-
- Удалить старую версию MultiCraft?
+ Игнорировать
diff --git a/build/android/app/src/main/res/values/colors.xml b/build/android/app/src/main/res/values/colors.xml
new file mode 100644
index 000000000..f9399f3ae
--- /dev/null
+++ b/build/android/app/src/main/res/values/colors.xml
@@ -0,0 +1,4 @@
+
+
+ #fefefe
+
diff --git a/build/android/app/src/main/res/values/strings.xml b/build/android/app/src/main/res/values/strings.xml
index 5299c6037..4706dc98b 100644
--- a/build/android/app/src/main/res/values/strings.xml
+++ b/build/android/app/src/main/res/values/strings.xml
@@ -1,53 +1,26 @@
-
MultiCraft
Preparing to launch…
Loading…
Loading… %d%%
- Downloading new version…
- Downloading new version… %d%%
Loading MultiCraft
Less than 1 minute…
Unexpected issue, the game will be restarted automatically
No space left for game files, please free space in the memory
OK
-
- Storage permissions is necessary to unpack textures and game data.
- Location permission provide you better interaction with game
- Close game
- App settings
- You cannot play MultiCraft without storage permission.\nPlease turn on it at [Settings] -> [Permissions]>
-
-
- Please, rate MultiCraft!
- Describe your experience
- SUBMIT
- We are sorry that you did not like the game!
- Please leave a review for us. Thank you!
-
- Loading\nrecommendation\nfor you:\n%d sec.
-
-
- New Version Available!
- Update
- Later
- Ignore
+ Text Input
+ Password
+ Done
- MultiCraft requires an internet connection to use all game features.\nOtherwise, you will not get updates and multiplayer will be not available!
+ No Internet Connection!
+ MultiCraft requires an Internet connection to use all game features.\nOtherwise, you will not get Updates and Multiplayer mode will be not available!
Wi-Fi
Mobile Data
-
-
- Uninstall an old version of MultiCraft?
-
-
- We care about your privacy and data security. We keep this app free by showing ads.\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 Privacy Policy.
- Yes, I allow
- No
+ Ignore
diff --git a/build/android/app/src/main/res/values/styles.xml b/build/android/app/src/main/res/values/styles.xml
index 2e593bff5..296b3044b 100644
--- a/build/android/app/src/main/res/values/styles.xml
+++ b/build/android/app/src/main/res/values/styles.xml
@@ -1,22 +1,12 @@
-
-
-
-
-
diff --git a/build/android/app/src/main/res/xml/backup_rules.xml b/build/android/app/src/main/res/xml/backup_rules.xml
index 0c018f5cd..fb945b639 100644
--- a/build/android/app/src/main/res/xml/backup_rules.xml
+++ b/build/android/app/src/main/res/xml/backup_rules.xml
@@ -3,10 +3,4 @@
-
-
diff --git a/build/android/app/src/main/res/xml/network_security_config.xml b/build/android/app/src/main/res/xml/network_security_config.xml
deleted file mode 100644
index 8501de96d..000000000
--- a/build/android/app/src/main/res/xml/network_security_config.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
- 127.0.0.1
-
-
diff --git a/build/android/build.gradle b/build/android/build.gradle
index a08d0ffb6..441a2a21e 100644
--- a/build/android/build.gradle
+++ b/build/android/build.gradle
@@ -12,13 +12,12 @@ project.ext.set("versionCode", 100) // Android Version Code
buildscript {
repositories {
google()
- jcenter()
+ mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.1.2'
- //noinspection GradleDynamicVersion
- /*classpath 'com.bugsnag:bugsnag-android-gradle-plugin:5.+'*/
- classpath 'de.undercouch:gradle-download-task:4.1.1'
+ classpath 'com.android.tools.build:gradle:7.0.3'
+ classpath 'de.undercouch:gradle-download-task:4.1.2'
+ classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
@@ -27,7 +26,7 @@ buildscript {
allprojects {
repositories {
google()
- jcenter()
+ mavenCentral()
}
}
diff --git a/build/android/gradle/wrapper/gradle-wrapper.jar b/build/android/gradle/wrapper/gradle-wrapper.jar
index e708b1c02..7454180f2 100644
Binary files a/build/android/gradle/wrapper/gradle-wrapper.jar and b/build/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/build/android/gradle/wrapper/gradle-wrapper.properties b/build/android/gradle/wrapper/gradle-wrapper.properties
index 4b3690740..d1f39deff 100644
--- a/build/android/gradle/wrapper/gradle-wrapper.properties
+++ b/build/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Fri Feb 12 19:20:09 CET 2021
+#Thu Nov 11 00:49:46 CET 2021
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
diff --git a/build/android/native/build.gradle b/build/android/native/build.gradle
index fa99cb81a..10dfd9ce0 100644
--- a/build/android/native/build.gradle
+++ b/build/android/native/build.gradle
@@ -2,13 +2,12 @@ apply plugin: 'com.android.library'
apply plugin: 'de.undercouch.download'
android {
- compileSdkVersion 29
- buildToolsVersion '30.0.3'
- ndkVersion '22.0.7026061'
+ compileSdkVersion 31
+ buildToolsVersion '31.0.0'
+ ndkVersion '23.1.7779620'
defaultConfig {
- minSdkVersion 16
- //noinspection OldTargetApi
- targetSdkVersion 29
+ minSdkVersion 19
+ targetSdkVersion 31
externalNativeBuild {
ndkBuild {
arguments '-j' + Runtime.getRuntime().availableProcessors(),