diff --git a/build/android/app/build.gradle b/build/android/app/build.gradle index 42d79f66..2b0a6643 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 + compileSdkVersion 30 buildToolsVersion '30.0.3' ndkVersion '22.1.7171670' defaultConfig { applicationId 'com.multicraft.game' - minSdkVersion 16 - //noinspection OldTargetApi - targetSdkVersion 29 - versionCode 150 - versionName "1.15.6" - multiDexEnabled true + minSdkVersion 19 + targetSdkVersion 30 + versionCode 170 + versionName "1.16.0" } // load properties @@ -62,21 +62,10 @@ dependencies { implementation project(':native') /* Third-party libraries */ - implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'androidx.appcompat:appcompat-resources:1.2.0' - implementation 'androidx.multidex:multidex:2.0.1' - implementation 'androidx.preference:preference:1.1.1' - implementation 'io.reactivex.rxjava2:rxjava:2.2.21' - 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' - //noinspection GradleDependency - implementation 'net.lingala.zip4j:zip4j:2.6.4' - - /* Analytics libraries */ - //noinspection GradleDynamicVersion - //implementation 'com.bugsnag:bugsnag-android-core:5.+' + implementation 'androidx.appcompat:appcompat:1.3.0' + implementation 'androidx.appcompat:appcompat-resources:1.3.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'io.reactivex.rxjava3:rxjava:3.0.13' + implementation 'io.reactivex.rxjava3:rxandroid:3.0.0' + implementation 'net.lingala.zip4j:zip4j:2.9.0' } diff --git a/build/android/app/src/main/AndroidManifest.xml b/build/android/app/src/main/AndroidManifest.xml index 1431cd02..1780493b 100644 --- a/build/android/app/src/main/AndroidManifest.xml +++ b/build/android/app/src/main/AndroidManifest.xml @@ -4,37 +4,43 @@ package="com.multicraft.game" android:installLocation="auto"> - - + + + + + + tools:ignore="UnusedAttribute" + tools:replace="android:fullBackupContent"> + android:permission="android.permission.BIND_JOB_SERVICE" /> + 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 698041ff..00000000 --- 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 52% 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 03e9e827..a1d2c272 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,26 +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; - -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); - 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 1404de9d..a6e55c3f 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,60 +20,42 @@ 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.KEYBOARD_QWERTY; +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.getTotalMem; +import static com.multicraft.game.helpers.Utilities.makeFullScreen; + import android.app.NativeActivity; -import android.content.Context; import android.content.res.Configuration; import android.os.Bundle; -import android.text.InputType; import android.view.KeyEvent; -import android.view.WindowManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager.LayoutParams; +import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; -import android.widget.EditText; +import android.widget.Button; import androidx.appcompat.app.AlertDialog; -import com.bugsnag.android.Bugsnag; -import com.multicraft.game.helpers.PreferencesHelper; - -import io.reactivex.Completable; -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.AdManager.initAd; -import static com.multicraft.game.AdManager.setAdsCallback; -import static com.multicraft.game.AdManager.startAd; -import static com.multicraft.game.AdManager.stopAd; -import static com.multicraft.game.helpers.PreferencesHelper.getInstance; -import static com.multicraft.game.helpers.Utilities.makeFullScreen; +import com.google.android.material.textfield.TextInputEditText; +import com.google.android.material.textfield.TextInputLayout; public class GameActivity extends NativeActivity { 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); System.exit(0); } } private int messageReturnCode = -1; private String messageReturnValue = ""; - private boolean consent, isMultiPlayer; - private PreferencesHelper pf; - private Disposable adInitSub; private boolean hasKeyboard; - public static native void putMessageBoxResult(String text); - public static native void pauseGame(); public static native void keyboardEvent(boolean keyboard); @@ -81,45 +63,20 @@ public class GameActivity extends NativeActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Bundle bundle = getIntent().getExtras(); - consent = bundle.getBoolean("consent", true); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON); hasKeyboard = !(getResources().getConfiguration().hardKeyboardHidden == KEYBOARD_QWERTY); keyboardEvent(hasKeyboard); - pf = getInstance(this); - if (pf.isAdsEnable()) { - adInitSub = Completable.fromAction(() -> initAd(this, consent)) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(() -> setAdsCallback(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(); - adInitSub.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 @@ -128,6 +85,12 @@ public class GameActivity extends NativeActivity { pauseGame(); } + @Override + protected void onResume() { + super.onResume(); + makeFullScreen(getWindow()); + } + @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -138,28 +101,37 @@ public class GameActivity extends NativeActivity { } } + @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); + View layout = LayoutInflater.from(this).inflate(R.layout.input_text, null); + TextInputLayout inputLayout = layout.findViewById(R.id.inputLayout); + TextInputEditText editText = layout.findViewById(R.id.editText); + String hintText = (!hint.isEmpty()) ? hint : getResources().getString( + (editType == 3) ? R.string.input_password : R.string.input_text); + inputLayout.setHint(hintText); + builder.setView(layout); AlertDialog alertDialog = builder.create(); 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); + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); + 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(); @@ -169,8 +141,17 @@ public class GameActivity extends NativeActivity { return false; }); 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(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); + getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); messageReturnValue = current; messageReturnCode = -1; }); @@ -180,6 +161,7 @@ public class GameActivity extends NativeActivity { return messageReturnCode; } + @SuppressWarnings("unused") public String getDialogValue() { messageReturnCode = -1; return messageReturnValue; @@ -190,25 +172,12 @@ public class GameActivity extends NativeActivity { } 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() { - if (isMultiPlayer && pf.isAdsEnable()) - startAd(this, false, true); } } 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 index 48fc61e2..8c3beb41 100644 --- a/build/android/app/src/main/java/com/multicraft/game/MainActivity.java +++ b/build/android/app/src/main/java/com/multicraft/game/MainActivity.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,95 +20,65 @@ with this program; if not, write to the Free Software Foundation, Inc., package com.multicraft.game; -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.ActivityNotFoundException; +import static android.content.DialogInterface.BUTTON_NEUTRAL; +import static android.provider.Settings.ACTION_WIFI_SETTINGS; +import static android.provider.Settings.ACTION_WIRELESS_SETTINGS; +import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; +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.Constants.FILES; +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.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.copyInputStreamToFile; +import static com.multicraft.game.helpers.Utilities.deleteFiles; +import static com.multicraft.game.helpers.Utilities.finishApp; +import static com.multicraft.game.helpers.Utilities.getIcon; +import static com.multicraft.game.helpers.Utilities.isConnected; +import static com.multicraft.game.helpers.Utilities.makeFullScreen; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.graphics.BlendMode; -import android.graphics.BlendModeColorFilter; import android.graphics.Color; -import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; -import android.net.Uri; -import android.os.Build; import android.os.Bundle; -import android.os.Environment; -import android.provider.Settings; -import android.text.Html; -import android.text.method.LinkMovementMethod; -import android.view.Gravity; import android.view.View; -import android.view.WindowManager; +import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; -import android.widget.Toast; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.graphics.BlendModeColorFilterCompat; +import androidx.core.graphics.BlendModeCompat; -import com.bugsnag.android.Bugsnag; -import com.multicraft.game.callbacks.CallBackListener; -import com.multicraft.game.callbacks.DialogsCallback; -import com.multicraft.game.helpers.AlertDialogHelper; -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 org.apache.commons.io.FilenameUtils; 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.HashMap; import java.util.List; -import java.util.Map; -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 io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.schedulers.Schedulers; -import static com.multicraft.game.helpers.ApiLevelHelper.isGreaterOrEqual; -import static com.multicraft.game.helpers.ApiLevelHelper.isGreaterOrEqualOreo; -import static com.multicraft.game.helpers.ApiLevelHelper.isGreaterOrEqualQ; -import static com.multicraft.game.helpers.PreferencesHelper.TAG_BUILD_NUMBER; -import static com.multicraft.game.helpers.PreferencesHelper.TAG_CONSENT_ASKED; -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.getStoreUrl; -import static com.multicraft.game.helpers.Utilities.makeFullScreen; - -public class MainActivity extends AppCompatActivity implements CallBackListener, DialogsCallback { - public final static Map zipLocations = new HashMap<>(); - private final static String SERVER_URL = "http://updates.multicraft.world/"; - public final static String UPDATE_LINK = SERVER_URL + "Android.json"; - private final static int REQUEST_CONNECTION = 104; - private final static List EU_COUNTRIES = Arrays.asList( - "AT", "BE", "BG", "HR", "CY", "CZ", - "DK", "EE", "FI", "FR", "DE", "GR", - "HU", "IE", "IT", "LV", "LT", "LU", - "MT", "NL", "PL", "PT", "RO", "SK", - "SI", "ES", "SE", "GB", "IS", "LI", "NO"); - private static String FILES, GAMES; - private final String versionName = BuildConfig.VERSION_NAME; - private String unzipLocation, appData; - private boolean consent; - private ProgressBar mProgressBar, mProgressBarIndeterminate; - private TextView mLoading; - private VersionManagerHelper versionManagerHelper = null; +public class MainActivity extends AppCompatActivity { + private ProgressBar mProgressBar, mProgressBarIndet; + private TextView mLoadingText; private PreferencesHelper pf; - private Disposable connectionSub, versionManagerSub, cleanSub, copySub; private final BroadcastReceiver myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -116,38 +86,56 @@ public class MainActivity extends AppCompatActivity implements CallBackListener, if (intent != null) progress = intent.getIntExtra(UnzipService.ACTION_PROGRESS, 0); if (progress >= 0) { - if (mProgressBar != null) { - showProgress(R.string.loading, R.string.loadingp, progress); - } + showProgress(R.string.loading, R.string.loadingp, progress); } else { - runGame(); + deleteFiles(Collections.singletonList(FILES), getCacheDir()); + if (progress == UNZIP_FAILURE) { + String msg = intent.getStringExtra(ACTION_FAILURE); + showRestartDialog(msg); + } else if (progress == UNZIP_SUCCESS) { + pf.saveSettings(TAG_BUILD_NUMBER, versionName); + startNative(); + } } } }; + private File externalStorage, filesDir, cacheDir; + private Disposable cleanSub, copySub, connectionSub; - // helpful utilities @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + getWindow().addFlags(FLAG_KEEP_SCREEN_ON); + try { + getSupportActionBar().hide(); + } catch (Exception ignored) { + } setContentView(R.layout.activity_main); + mLoadingText = findViewById(R.id.tv_progress); + mProgressBar = findViewById(R.id.PB); + mProgressBarIndet = findViewById(R.id.PB_Indet); + boolean isException = false; + try { + filesDir = getFilesDir(); + cacheDir = getCacheDir(); + externalStorage = getExternalFilesDir(null); + if (filesDir == null || cacheDir == null || externalStorage == null) + throw new IOException(getString(R.string.space_error)); + } catch (IOException e) { + isException = true; + String msg = getString(R.string.restart, e.getLocalizedMessage()); + if (e.getMessage().contains(NO_SPACE_LEFT)) { + msg = NO_SPACE_LEFT; + } + showRestartDialog(msg); + } + if (isException) { + return; + } pf = PreferencesHelper.getInstance(this); 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); + lateInit(); } @Override @@ -158,357 +146,184 @@ public class MainActivity extends AppCompatActivity implements CallBackListener, @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(); - unregisterReceiver(myReceiver); - } - - private void initZipLocations() { - File externalDir = getExternalFilesDir(null); - unzipLocation = externalDir + File.separator; - if (externalDir == null) { - externalDir = Environment.getExternalStorageDirectory(); - unzipLocation = externalDir + File.separator + "Android/data/com.multicraft.game" + File.separator; - } - appData = getFilesDir() + File.separator; - File cacheDir = getCacheDir(); - String cachePath = cacheDir + File.separator; - if (cacheDir == null) - cachePath = unzipLocation + "cache" + File.separator; - - FILES = cachePath + "Files.zip"; - GAMES = cachePath + "games.zip"; - zipLocations.put(FILES, appData); - zipLocations.put(GAMES, appData); - } - - private void addLaunchTimes() { - int i = pf.getLaunchTimes(); - i++; - pf.saveSettings(TAG_LAUNCH_TIMES, i); - } - - private void createDataFolder() { - File folder = new File(unzipLocation); - if (!folder.mkdirs() && !folder.isDirectory()) - Bugsnag.leaveBreadcrumb(folder + " (unzipLocation) folder was not created"); - } - - // interface - private void showProgress(int textMessage, int progressMessage, int progress) { - if (mProgressBar.getVisibility() == View.GONE) - updateViews(textMessage, View.VISIBLE, View.GONE, View.VISIBLE); - 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 (isGreaterOrEqualQ()) - progressDrawable.setColorFilter(new BlendModeColorFilter(color, BlendMode.SRC_IN)); - else - progressDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); - } - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - if (hasFocus) - makeFullScreen(this); - } - - // GDPR check - private void askGdpr() { - if (pf.isAskConsent() && isGdprSubject()) - showGdprDialog(); - else { - consent = true; - startNative(); - } - } - - private void init() { - try { - initZipLocations(); - } catch (Exception e) { - showRestartDialog(""); - } - mProgressBar = findViewById(R.id.PB1); - mProgressBarIndeterminate = findViewById(R.id.PB2); - mLoading = findViewById(R.id.tv_progress); - RateMe.onStart(this); - if (!pf.isCreateShortcut() && !isGreaterOrEqualOreo()) - addShortcut(this); - checkAppVersion(); - } - - // game logic - private void checkRateDialog() { - if (RateMe.shouldShowRateDialog()) { - updateViews(R.string.empty, View.GONE, View.GONE, View.GONE); - RateMe.showRateDialog(); - RateMe.setListener(this); - } else - askGdpr(); - } - - void showUpdateDialog() { - AlertDialogHelper dialogHelper = new AlertDialogHelper(this); - dialogHelper.setListener(this); - dialogHelper.setIcon(getIcon(this)); - dialogHelper.setTitle(getString(R.string.available)); - dialogHelper.setMessage(Html.fromHtml( - versionManagerHelper.getMessage(), null, versionManagerHelper.getCustomTagHandler())); - dialogHelper.setButtonPositive(getString(R.string.update)); - dialogHelper.setButtonNeutral(getString(R.string.later)); - dialogHelper.showAlert("VersionManager"); - } - - private void checkUrlVersion() { - versionManagerHelper = new VersionManagerHelper(this); - if (versionManagerHelper.isCheckVersion()) - versionManagerSub = Observable.fromCallable(() -> versionManagerHelper.getJson()) - .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() { - deleteFiles(Arrays.asList(FILES, GAMES)); - pf.saveSettings(TAG_BUILD_NUMBER, versionName); - connectionSub = checkConnection(); - } - - private void startNative() { - Intent intent = new Intent(this, GameActivity.class); - intent.putExtra("consent", consent); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK); - startActivity(intent); - } - - private boolean isGdprSubject() { - String locale; - if (isGreaterOrEqual(Build.VERSION_CODES.N)) - locale = getResources().getConfiguration().getLocales().get(0).getCountry(); - else - locale = getResources().getConfiguration().locale.getCountry(); - return EU_COUNTRIES.contains(locale.toUpperCase()); + if (connectionSub != null) connectionSub.dispose(); + if (myReceiver != null) unregisterReceiver(myReceiver); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CONNECTION) { - checkUrlVersion(); - } else askGdpr(); - } - - private void cleanUpOldFiles(boolean isAll) { - updateViews(R.string.preparing, View.VISIBLE, View.VISIBLE, View.GONE); - List filesList; - if (isAll) - filesList = Collections.singletonList(unzipLocation); - else { - filesList = Arrays.asList(unzipLocation + "cache", - unzipLocation + "builtin", appData + "builtin", - unzipLocation + "games", appData + "games", - unzipLocation + "debug.txt"); - } - cleanSub = Observable.fromCallable(() -> deleteFiles(filesList)) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> startCopy(isAll)); - } - - private void checkAppVersion() { - if (pf.getBuildNumber().equals(versionName)) { - mProgressBarIndeterminate.setVisibility(View.VISIBLE); - runGame(); - } else if (pf.getBuildNumber().equals("0")) { - createDataFolder(); - cleanUpOldFiles(true); - } else { - createDataFolder(); - cleanUpOldFiles(false); + checkAppVersion(); } } - public void updateViews(int text, int textVisib, int progressIndetermVisib, int progressVisib) { - mLoading.setText(text); - mLoading.setVisibility(textVisib); - mProgressBarIndeterminate.setVisibility(progressIndetermVisib); - mProgressBar.setVisibility(progressVisib); + @Override + protected void onResume() { + super.onResume(); + makeFullScreen(getWindow()); } - public void isShowDialog(boolean flag) { - if (flag) { - updateViews(R.string.loading, View.VISIBLE, View.VISIBLE, View.GONE); - showUpdateDialog(); - } else - checkRateDialog(); + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + if (hasFocus) makeFullScreen(getWindow()); } + private void addLaunchTimes() { + int launchTimes = pf.getLaunchTimes() + 1; + pf.saveSettings(TAG_LAUNCH_TIMES, launchTimes); + } + + // interface + private void showProgress(int textMessage, int progressMessage, int progress) { + if (mProgressBar == null) return; + if (mProgressBar.getVisibility() == View.GONE) { + updateViews(textMessage, View.GONE, View.VISIBLE); + mProgressBar.setProgress(0); + } else if (progress > 0) { + mLoadingText.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); + progressDrawable.setColorFilter( + BlendModeColorFilterCompat.createBlendModeColorFilterCompat(color, BlendModeCompat.SRC_IN)); + } + } + + private void lateInit() { + addLaunchTimes(); + if (!pf.isCreateShortcut()) addShortcut(this); + connectionSub = checkConnection(); + } + + // check connection available private Disposable checkConnection() { - return Observable.fromCallable(Utilities::isReachable) + return Observable.fromCallable(() -> isConnected(this)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .timeout(4000, TimeUnit.MILLISECONDS) .subscribe(result -> { - if (result) checkUrlVersion(); + if (result) checkAppVersion(); else showConnectionDialog(); }, throwable -> runOnUiThread(this::showConnectionDialog)); } - private void startCopy(boolean isAll) { - String[] zips; - if (isAll) - zips = new String[]{FILES, GAMES}; - else - zips = new String[]{FILES, GAMES}; - copySub = Completable.fromAction(() -> copyAssets(zips)) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(() -> startUnzipService(zips), - throwable -> { - if (throwable.getLocalizedMessage().contains("ENOSPC")) - showRestartDialog("ENOSPC"); - else showRestartDialog("UKNWN"); - }); - } - - private void copyAssets(String[] zips) throws IOException { - for (String zipName : zips) { - String filename = FilenameUtils.getName(zipName); - try (InputStream in = getAssets().open(filename)) { - FileUtils.copyInputStreamToFile(in, new File(zipName)); - } + // connection dialog + private void showConnectionDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setIcon(getIcon(this)) + .setTitle(R.string.conn_title) + .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) -> checkAppVersion()) + .setCancelable(false); + final AlertDialog dialog = builder.create(); + makeFullScreen(dialog.getWindow()); + if (!isFinishing()) { + dialog.show(); + Button button = dialog.getButton(BUTTON_NEUTRAL); + if (button != null) button.setTextColor(Color.RED); } } - private void startUnzipService(String[] file) { + private void startHandledActivity(Intent intent) { + try { + startActivityForResult(intent, REQUEST_CONNECTION); + } catch (Exception e) { + checkAppVersion(); + } + } + + private void startNative() { + Intent intent = new Intent(this, GameActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + } + + private void cleanUpOldFiles() { + updateViews(R.string.preparing, View.VISIBLE, View.GONE); + List filesList = Arrays.asList( + new File(externalStorage, "cache"), + new File(externalStorage, "debug.txt"), + new File(filesDir, "builtin"), + new File(cacheDir, FILES) + ); + Completable delObs = Completable.fromAction(() -> deleteFiles(filesList)); + cleanSub = delObs.subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::startCopy); + } + + private void checkAppVersion() { + String prefVersion; + try { + prefVersion = pf.getBuildNumber(); + } catch (ClassCastException e) { + prefVersion = "1"; + } + + if (prefVersion.equals(versionName)) + startNative(); + else + cleanUpOldFiles(); + } + + private void updateViews(int text, int progressIndetVisib, int progressVisib) { + mLoadingText.setText(text); + mLoadingText.setVisibility(View.VISIBLE); + mProgressBarIndet.setVisibility(progressIndetVisib); + mProgressBar.setVisibility(progressVisib); + } + + private void startCopy() { + List zips = new ArrayList<>(Collections.singletonList(FILES)); + + copySub = Observable.fromCallable(() -> copyAssets(zips)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + if (result) startUnzipService(zips); + }); + } + + private boolean copyAssets(List zips) { + for (String zipName : zips) { + try (InputStream in = getAssets().open("data/" + zipName)) { + copyInputStreamToFile(new File(cacheDir, zipName), in); + } catch (IOException e) { + if (e.getLocalizedMessage().contains(NO_SPACE_LEFT)) + runOnUiThread(() -> showRestartDialog(NO_SPACE_LEFT)); + else { + runOnUiThread(() -> showRestartDialog(e.getLocalizedMessage())); + } + return false; + } + } + return true; + } + + private void startUnzipService(List file) { Intent intent = new Intent(this, UnzipService.class); - intent.putExtra(UnzipService.EXTRA_KEY_IN_FILE, file); - startService(intent); + intent.putStringArrayListExtra(UnzipService.EXTRA_KEY_IN_FILE, (ArrayList) file); + UnzipService.enqueueWork(this, intent); } private void showRestartDialog(final String source) { - String message; - if ("ENOSPC".equals(source)) - message = getString(R.string.no_space); - else - message = getString(R.string.restart); - final AlertDialogHelper dialogHelper = new AlertDialogHelper(this); - dialogHelper.setListener(this); - dialogHelper.setMessage(message); - dialogHelper.setButtonPositive(getString(android.R.string.ok)); - dialogHelper.showAlert("Restart"); - } - - 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 showGdprDialog() { - AlertDialogHelper dialogHelper = new AlertDialogHelper(this); - dialogHelper.setListener(this); - dialogHelper.setIcon(getIcon(this)); - dialogHelper.setTitle(getString(R.string.app_name)); - TextView tv = new TextView(this); - tv.setText(R.string.gdpr_main_text); - tv.setPadding(20, 0, 20, 0); - tv.setGravity(Gravity.CENTER); - tv.setMovementMethod(LinkMovementMethod.getInstance()); - dialogHelper.setTV(tv); - dialogHelper.setButtonPositive(getString(R.string.gdpr_agree)); - dialogHelper.setButtonNegative(getString(R.string.gdpr_disagree)); - dialogHelper.showAlert("GdprDialog"); - } - - private void showConnectionDialog() { - AlertDialogHelper dialogHelper = new AlertDialogHelper(this); - dialogHelper.setListener(this); - dialogHelper.setMessage(getString(R.string.conn_message)); - dialogHelper.setButtonPositive(getString(R.string.conn_wifi)); - dialogHelper.setButtonNegative(getString(R.string.conn_mobile)); - dialogHelper.setButtonNeutral(getString(R.string.ignore)); - dialogHelper.showAlert("ConnectionDialog"); - } - - @Override - public void onPositive(String source) { - if ("RateMe".equals(source)) { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getStoreUrl())); - startActivity(intent); - Toast.makeText(this, R.string.thank, Toast.LENGTH_LONG).show(); - finish(); - } else if ("Restart".equals(source)) - restartApp(); - else if ("ConnectionDialog".equals(source)) - try { - startActivityForResult(new Intent(Settings.ACTION_WIFI_SETTINGS), REQUEST_CONNECTION); - } catch (ActivityNotFoundException e) { - Bugsnag.notify(e); - askGdpr(); - } - else if ("GdprDialog".equals(source)) { - pf.saveSettings(TAG_CONSENT_ASKED, false); - consent = true; - startNative(); - } else { - versionManagerHelper.updateNow(versionManagerHelper.getUpdateUrl()); - finish(); - } - } - - @Override - public void onNegative(String source) { - if ("RateMe".equals(source)) - askGdpr(); - else if ("ConnectionDialog".equals(source)) - try { - startActivityForResult(new Intent(Settings.ACTION_WIRELESS_SETTINGS), REQUEST_CONNECTION); - } catch (ActivityNotFoundException e) { - Bugsnag.notify(e); - askGdpr(); - } - else if ("GdprDialog".equals(source)) { - pf.saveSettings(TAG_CONSENT_ASKED, false); - consent = false; - startNative(); - } else - checkRateDialog(); - } - - @Override - public void onNeutral(String source) { - if ("RateMe".equals(source)) - askGdpr(); - else if ("ConnectionDialog".equals(source)) - askGdpr(); - else { - versionManagerHelper.remindMeLater(); - checkRateDialog(); - } + boolean space = NO_SPACE_LEFT.equals(source); + String message = space ? getString(R.string.no_space) : source; + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage(message) + .setPositiveButton(R.string.ok, (dialogInterface, i) -> finishApp(!space, this)) + .setCancelable(false); + final AlertDialog dialog = builder.create(); + makeFullScreen(dialog.getWindow()); + if (!isFinishing()) + dialog.show(); } } diff --git a/build/android/app/src/main/java/com/multicraft/game/MyApplication.java b/build/android/app/src/main/java/com/multicraft/game/MyApplication.java deleted file mode 100644 index 3972f78d..00000000 --- a/build/android/app/src/main/java/com/multicraft/game/MyApplication.java +++ /dev/null @@ -1,33 +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 androidx.multidex.MultiDexApplication; - -import com.bugsnag.android.Bugsnag; - -public class MyApplication extends MultiDexApplication { - @Override - public void onCreate() { - super.onCreate(); - Bugsnag.start(this); - } -} diff --git a/build/android/app/src/main/java/com/multicraft/game/RateMe.java b/build/android/app/src/main/java/com/multicraft/game/RateMe.java deleted file mode 100644 index 316ce043..00000000 --- a/build/android/app/src/main/java/com/multicraft/game/RateMe.java +++ /dev/null @@ -1,140 +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.Dialog; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.view.View; -import android.widget.RatingBar; -import android.widget.Toast; - -import androidx.appcompat.app.AppCompatActivity; - -import com.bugsnag.android.Bugsnag; -import com.multicraft.game.callbacks.DialogsCallback; -import com.multicraft.game.helpers.PreferencesHelper; - -import java.lang.ref.WeakReference; -import java.util.Date; - -import static com.multicraft.game.helpers.ApiLevelHelper.isGreaterOrEqualKitkat; - -class RateMe { - private static final int INSTALL_DAYS = 5; - private static final int LAUNCH_TIMES = 4; - private static final String PREF_NAME = "RateMe"; - private static final String KEY_INSTALL_DATE = "rta_install_date"; - private static final String KEY_OPT_OUT = "rta_opt_out"; - private static Date mInstallDate = new Date(); - private static boolean mOptOut = false; - private static DialogsCallback sCallback = null; - - private static WeakReference activityRef = null; - - static void setListener(DialogsCallback callback) { - sCallback = callback; - } - - static void onStart(AppCompatActivity activity) { - activityRef = new WeakReference<>(activity); - SharedPreferences pref = activity.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); - Editor editor = pref.edit(); - // If it is the first launch, save the date in shared preference. - if (pref.getLong(KEY_INSTALL_DATE, 0) == 0L) - storeInstallDate(activity, editor); - editor.apply(); - - mInstallDate = new Date(pref.getLong(KEY_INSTALL_DATE, 0)); - mOptOut = pref.getBoolean(KEY_OPT_OUT, false); - } - - static boolean shouldShowRateDialog() { - if (mOptOut) - return false; - else { - if (PreferencesHelper.getInstance(activityRef.get()).getLaunchTimes() % LAUNCH_TIMES == 0) - return true; - long threshold = INSTALL_DAYS * 24 * 60 * 60 * 1000L; - return new Date().getTime() - mInstallDate.getTime() >= threshold; - } - } - - static void showRateDialog() { - final AppCompatActivity activity = activityRef.get(); - final Dialog dialog = new Dialog(activity, R.style.RateMe); - dialog.setCancelable(false); - if (isGreaterOrEqualKitkat()) - 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) { - sCallback.onPositive("RateMe"); - dialog.dismiss(); - setOptOut(activity); - } else { - sCallback.onNegative("RateMe"); - dialog.dismiss(); - Toast.makeText(activity, R.string.sad, Toast.LENGTH_LONG).show(); - clearSharedPreferences(activity); - } - }); - dialog.setOnCancelListener(dialog1 -> { - sCallback.onNeutral("RateMe"); - clearSharedPreferences(activity); - }); - if (!activity.isFinishing()) - dialog.show(); - else - sCallback.onNegative("RateMe"); - } - - private static void clearSharedPreferences(AppCompatActivity activity) { - Editor editor = activity.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit(); - editor.remove(KEY_INSTALL_DATE); - editor.apply(); - } - - private static void setOptOut(final AppCompatActivity activity) { - Editor editor = activity.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit(); - editor.putBoolean(KEY_OPT_OUT, true); - editor.apply(); - } - - private static void storeInstallDate(final AppCompatActivity activity, Editor editor) { - Date installDate = new Date(); - PackageManager packageManager = activity.getPackageManager(); - try { - PackageInfo pkgInfo = packageManager.getPackageInfo(activity.getPackageName(), 0); - installDate = new Date(pkgInfo.firstInstallTime); - } catch (PackageManager.NameNotFoundException e) { - Bugsnag.notify(e); - } - editor.putLong(KEY_INSTALL_DATE, installDate.getTime()); - } -} diff --git a/build/android/app/src/main/java/com/multicraft/game/RemoteSettings.java b/build/android/app/src/main/java/com/multicraft/game/RemoteSettings.java deleted file mode 100644 index 0826027c..00000000 --- a/build/android/app/src/main/java/com/multicraft/game/RemoteSettings.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 java.util.List; - -public class RemoteSettings { - private int versionCode = 0; - private List badVersionCodes; - private String packageName, content; - private int adsDelay = -1; - private int adsRepeat = -1; - private boolean adsEnabled = true; - - public int getVersionCode() { - return versionCode; - } - - public void setVersionCode(int versionCode) { - this.versionCode = versionCode; - } - - public List getBadVersionCodes() { - return badVersionCodes; - } - - public void setBadVersionCodes(List badVersionCodes) { - this.badVersionCodes = badVersionCodes; - } - - public String getPackageName() { - return packageName; - } - - public void setPackageName(String packageName) { - this.packageName = packageName; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public int getAdsDelay() { - return adsDelay; - } - - public void setAdsDelay(int adsDelay) { - this.adsDelay = adsDelay; - } - - public int getAdsRepeat() { - return adsRepeat; - } - - public void setAdsRepeat(int adsRepeat) { - this.adsRepeat = adsRepeat; - } - - public boolean isAdsEnabled() { - return adsEnabled; - } - - public void setAdsEnabled(boolean adsEnabled) { - this.adsEnabled = adsEnabled; - } -} 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 22944c2b..00000000 --- a/build/android/app/src/main/java/com/multicraft/game/UnzipService.java +++ /dev/null @@ -1,163 +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 net.lingala.zip4j.ZipFile; -import net.lingala.zip4j.io.inputstream.ZipInputStream; -import net.lingala.zip4j.model.LocalFileHeader; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -import static com.multicraft.game.MainActivity.zipLocations; -import static com.multicraft.game.helpers.ApiLevelHelper.isGreaterOrEqualOreo; - -public class UnzipService extends IntentService { - public static final String ACTION_UPDATE = "com.multicraft.game.UPDATE"; - public static final String EXTRA_KEY_IN_FILE = "file"; - public static final String ACTION_PROGRESS = "progress"; - private final int id = 1; - private NotificationManager mNotifyManager; - - 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 String getSettings() { - return getString(R.string.gdpr_main_text); - } - - 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 (isGreaterOrEqualOreo()) { - 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) { - String[] zips = intent.getStringArrayExtra(EXTRA_KEY_IN_FILE); - int per = 0; - int size = getSummarySize(zips); - for (String zip : zips) { - File zipFile = new File(zip); - LocalFileHeader localFileHeader; - int readLen; - byte[] readBuffer = new byte[8192]; - try (FileInputStream fileInputStream = new FileInputStream(zipFile); - ZipInputStream zipInputStream = new ZipInputStream(fileInputStream)) { - while ((localFileHeader = zipInputStream.getNextEntry()) != null) { - String fileName = localFileHeader.getFileName(); - if (localFileHeader.isDirectory()) { - ++per; - isDir(fileName, zipLocations.get(zip)); - } else { - File extractedFile = new File(fileName); - publishProgress(100 * ++per / size); - try (OutputStream outputStream = new FileOutputStream(zipLocations.get(zip) + extractedFile)) { - while ((readLen = zipInputStream.read(readBuffer)) != -1) { - outputStream.write(readBuffer, 0, readLen); - } - } - } - } - } catch (FileNotFoundException e) { - Bugsnag.notify(e); - } catch (IOException e) { - Bugsnag.notify(e); - } - } - } - - private void publishProgress(int progress) { - Intent intentUpdate = new Intent(ACTION_UPDATE); - intentUpdate.putExtra(ACTION_PROGRESS, progress); - sendBroadcast(intentUpdate); - } - - private int getSummarySize(String[] zips) { - int size = 0; - for (String z : zips) { - try { - ZipFile zipFile = new ZipFile(z); - size += zipFile.getFileHeaders().size(); - } catch (IOException e) { - Bugsnag.notify(e); - } - } - return size; - } - - @Override - public void onDestroy() { - super.onDestroy(); - mNotifyManager.cancel(id); - publishProgress(-1); - } -} diff --git a/build/android/app/src/main/java/com/multicraft/game/UnzipService.kt b/build/android/app/src/main/java/com/multicraft/game/UnzipService.kt new file mode 100644 index 00000000..e1e86775 --- /dev/null +++ b/build/android/app/src/main/java/com/multicraft/game/UnzipService.kt @@ -0,0 +1,156 @@ +/* +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.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.content.Context +import android.content.Intent +import androidx.core.app.JobIntentService +import com.multicraft.game.helpers.ApiLevelHelper.isOreo +import com.multicraft.game.helpers.Utilities.copyInputStreamToFile +import net.lingala.zip4j.ZipFile +import net.lingala.zip4j.io.inputstream.ZipInputStream +import net.lingala.zip4j.model.LocalFileHeader +import java.io.File +import java.io.FileInputStream +import java.io.IOException +import java.util.* + +class UnzipService : JobIntentService() { + private val id = 1 + private var mNotifyManager: NotificationManager? = null + private lateinit var failureMessage: String + private var isSuccess = true + + override fun onHandleWork(intent: Intent) { + createNotification() + unzip(intent) + } + + override fun onDestroy() { + super.onDestroy() + if (mNotifyManager != null) mNotifyManager!!.cancel(id) + publishProgress(if (isSuccess) UNZIP_SUCCESS else UNZIP_FAILURE) + } + + private fun createNotification() { + val name = "com.multicraft.game" + val channelId = "MultiCraft channel" + val description = "notifications from MultiCraft" + val builder: Notification.Builder + if (mNotifyManager == null) mNotifyManager = + getSystemService(NOTIFICATION_SERVICE) as NotificationManager + if (isOreo) { + val importance = NotificationManager.IMPORTANCE_LOW + var mChannel: NotificationChannel? = null + if (mNotifyManager != null) mChannel = + mNotifyManager!!.getNotificationChannel(channelId) + if (mChannel == null) { + mChannel = NotificationChannel(channelId, name, importance) + mChannel.description = description + // Configure the notification channel, NO SOUND + mChannel.setSound(null, null) + mChannel.enableLights(false) + mChannel.enableVibration(false) + mNotifyManager!!.createNotificationChannel(mChannel) + } + builder = Notification.Builder(this, channelId) + } else @Suppress("DEPRECATION") { + builder = 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()) + } + + @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") + private fun unzip(intent: Intent?) { + try { + val zips: ArrayList = + intent?.getStringArrayListExtra(EXTRA_KEY_IN_FILE) + ?: throw NullPointerException("No data received") + val cache = cacheDir.toString() + val files = filesDir.toString() + var per = 0 + val size = getSummarySize(zips, cache) + for (zip in zips) { + val zipFile = File(cache, zip) + var localFileHeader: LocalFileHeader? + FileInputStream(zipFile).use { fileInputStream -> + ZipInputStream( + fileInputStream + ).use { zipInputStream -> + while (zipInputStream.nextEntry.also { localFileHeader = it } != null) { + if (localFileHeader == null) continue + val extracted = File(files, localFileHeader!!.fileName) + if (localFileHeader!!.isDirectory) + extracted.mkdirs() + else + extracted.copyInputStreamToFile(zipInputStream) + ++per + publishProgress(100 * per / size) + } + } + } + } + } catch (e: IOException) { + failureMessage = e.localizedMessage + isSuccess = false + } catch (e: NullPointerException) { + failureMessage = e.localizedMessage + isSuccess = false + } + } + + private fun publishProgress(progress: Int) { + val intentUpdate = Intent(ACTION_UPDATE) + intentUpdate.putExtra(ACTION_PROGRESS, progress) + if (!isSuccess) intentUpdate.putExtra(ACTION_FAILURE, failureMessage) + sendBroadcast(intentUpdate) + } + + private fun getSummarySize(zips: List, path: String): Int { + var size = 1 + for (zip in zips) { + val zipFile = ZipFile(File(path, zip)) + size += zipFile.fileHeaders.size + } + return size + } + + companion object { + const val ACTION_UPDATE = "com.multicraft.game.UPDATE" + const val EXTRA_KEY_IN_FILE = "com.multicraft.game.file" + const val ACTION_PROGRESS = "com.multicraft.game.progress" + const val ACTION_FAILURE = "com.multicraft.game.failure" + const val UNZIP_SUCCESS = -1 + const val UNZIP_FAILURE = -2 + private const val JOB_ID = 1 + + @JvmStatic + fun enqueueWork(context: Context, work: Intent) { + enqueueWork(context, UnzipService::class.java, JOB_ID, work) + } + } +} 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/callbacks/CallBackListener.java deleted file mode 100644 index 1a7bd889..00000000 --- a/build/android/app/src/main/java/com/multicraft/game/callbacks/CallBackListener.java +++ /dev/null @@ -1,25 +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.callbacks; - -public interface CallBackListener { - void onEvent(boolean isContinue); -} diff --git a/build/android/app/src/main/java/com/multicraft/game/helpers/AlertDialogHelper.java b/build/android/app/src/main/java/com/multicraft/game/helpers/AlertDialogHelper.java deleted file mode 100644 index 339e5dc5..00000000 --- a/build/android/app/src/main/java/com/multicraft/game/helpers/AlertDialogHelper.java +++ /dev/null @@ -1,133 +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.graphics.drawable.Drawable; -import android.widget.TextView; - -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.app.AppCompatActivity; - -import com.multicraft.game.callbacks.DialogsCallback; - - -public class AlertDialogHelper { - private final AppCompatActivity activity; - private DialogsCallback sCallback = null; - private Drawable icon = null; - private String title = null; - private CharSequence message = null; - private TextView tv = null; - private String buttonPositive = null; - private String buttonNegative = null; - private String buttonNeutral = null; - - public AlertDialogHelper(AppCompatActivity activity) { - this.activity = activity; - } - - private Drawable getIcon() { - return icon; - } - - public void setIcon(Drawable icon) { - this.icon = icon; - } - - private String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - private CharSequence getMessage() { - return message; - } - - public void setMessage(CharSequence message) { - this.message = message; - } - - private TextView getTV() { - return tv; - } - - public void setTV(TextView tv) { - this.tv = tv; - } - - private String getButtonPositive() { - return buttonPositive; - } - - public void setButtonPositive(String buttonPositive) { - this.buttonPositive = buttonPositive; - } - - private String getButtonNegative() { - return buttonNegative; - } - - public void setButtonNegative(String buttonNegative) { - this.buttonNegative = buttonNegative; - } - - private String getButtonNeutral() { - return buttonNeutral; - } - - public void setButtonNeutral(String buttonNeutral) { - this.buttonNeutral = buttonNeutral; - } - - public void setListener(DialogsCallback callback) { - sCallback = callback; - } - - public void showAlert(final String source) { - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - if (getIcon() != null) builder.setIcon(getIcon()); - if (getTitle() != null) builder.setTitle(getTitle()); - if (getMessage() != null) builder.setMessage(getMessage()); - if (getTV() != null) builder.setView(getTV()); - if (getButtonPositive() != null) - builder.setPositiveButton(getButtonPositive(), (dialogInterface, i) -> { - dialogInterface.dismiss(); - sCallback.onPositive(source); - }); - if (getButtonNegative() != null) - builder.setNegativeButton(getButtonNegative(), (dialogInterface, i) -> { - dialogInterface.dismiss(); - sCallback.onNegative(source); - }); - if (getButtonNeutral() != null) - builder.setNeutralButton(getButtonNeutral(), (dialogInterface, i) -> { - dialogInterface.dismiss(); - sCallback.onNeutral(source); - }); - builder.setCancelable(false); - final AlertDialog dialog = builder.create(); - if (!activity.isFinishing()) - dialog.show(); - } -} 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 6c982b67..00000000 --- a/build/android/app/src/main/java/com/multicraft/game/helpers/ApiLevelHelper.java +++ /dev/null @@ -1,49 +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.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 isGreaterOrEqualKitkat() { - return isGreaterOrEqual(KITKAT); - } - - public static boolean isGreaterOrEqualLollipop() { - return isGreaterOrEqual(LOLLIPOP); - } - - public static boolean isGreaterOrEqualOreo() { - return isGreaterOrEqual(O); - } - - public static boolean isGreaterOrEqualQ() { - return isGreaterOrEqual(Q); - } -} diff --git a/build/android/app/src/main/java/com/multicraft/game/AdManager.java b/build/android/app/src/main/java/com/multicraft/game/helpers/ApiLevelHelper.kt similarity index 53% rename from build/android/app/src/main/java/com/multicraft/game/AdManager.java rename to build/android/app/src/main/java/com/multicraft/game/helpers/ApiLevelHelper.kt index 2564e6f4..bafbc4e1 100644 --- a/build/android/app/src/main/java/com/multicraft/game/AdManager.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,25 +18,26 @@ 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 android.app.Activity; +import android.os.Build +import android.os.Build.VERSION.SDK_INT +import android.os.Build.VERSION_CODES.KITKAT +import android.os.Build.VERSION_CODES.O -class AdManager { - - static void initAd(final Activity activity, boolean consent) { - // NDA code here +object ApiLevelHelper { + private fun isGreaterOrEqual(versionCode: Int): Boolean { + return SDK_INT >= versionCode } - static void setAdsCallback(final Activity activity) { - // NDA code here - } + @JvmStatic + val isKitKat: Boolean + get() = isGreaterOrEqual(KITKAT) - static void startAd(final Activity activity, boolean isFirstTime, boolean isShowNow) { - // NDA code here - } + val isMarshmallow: Boolean + get() = isGreaterOrEqual(Build.VERSION_CODES.M) - static void stopAd() { - // NDA code here - } + @JvmStatic + val isOreo: Boolean + get() = isGreaterOrEqual(O) } diff --git a/build/android/app/src/main/java/com/multicraft/game/callbacks/DialogsCallback.java b/build/android/app/src/main/java/com/multicraft/game/helpers/Constants.kt similarity index 66% rename from build/android/app/src/main/java/com/multicraft/game/callbacks/DialogsCallback.java rename to build/android/app/src/main/java/com/multicraft/game/helpers/Constants.kt index 571434e1..bc2ef8bf 100644 --- a/build/android/app/src/main/java/com/multicraft/game/callbacks/DialogsCallback.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,12 +18,13 @@ 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 DialogsCallback { - void onPositive(String source); +import com.multicraft.game.BuildConfig - void onNegative(String source); - - void onNeutral(String source); +object Constants { + const val REQUEST_CONNECTION = 104 + const val NO_SPACE_LEFT = "ENOSPC" + const val FILES = "Files.zip" + const val versionName = BuildConfig.VERSION_NAME } 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 d22686e3..00000000 --- a/build/android/app/src/main/java/com/multicraft/game/helpers/PermissionHelper.java +++ /dev/null @@ -1,95 +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.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()) { - 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 -> { - listener.onEvent(tedPermissionResult.isGranted()); - }); - } - - @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 -> { - listener.onEvent(tedPermissionResult.isGranted()); - }); - } -} 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 index a40b188f..6766e0fa 100644 --- 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 @@ -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 @@ -23,19 +23,10 @@ package com.multicraft.game.helpers; import android.content.Context; import android.content.SharedPreferences; -import com.multicraft.game.RemoteSettings; - 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_CONSENT_ASKED = "consentAsked"; - public static final String TAG_COPY_OLD_WORLDS = "copyOldWorlds"; - public static final String IS_LOADED = "interstitialLoaded"; - public static final String RV_LOADED = "rewardedVideoLoaded"; - private static final String ADS_DELAY = "adsDelay"; - private static final String ADS_REPEAT = "adsRepeat"; - private static final String ADS_ENABLE = "adsEnable"; private static final String SETTINGS = "MultiCraftSettings"; private static PreferencesHelper instance; @@ -59,22 +50,6 @@ public class PreferencesHelper { 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(TAG_CONSENT_ASKED, true); - } - - public boolean isWorldsCopied() { - return sharedPreferences.getBoolean(TAG_COPY_OLD_WORLDS, false); - } - public String getBuildNumber() { return sharedPreferences.getString(TAG_BUILD_NUMBER, "0"); } @@ -83,18 +58,6 @@ public class PreferencesHelper { return sharedPreferences.getInt(TAG_LAUNCH_TIMES, 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 void saveSettings(String tag, boolean bool) { sharedPreferences.edit().putBoolean(tag, bool).apply(); } @@ -106,12 +69,4 @@ public class PreferencesHelper { public void saveSettings(String tag, int value) { sharedPreferences.edit().putInt(tag, value).apply(); } - - public void saveAdsSettings(RemoteSettings remoteSettings) { - int delay = remoteSettings.getAdsDelay(); - int repeat = remoteSettings.getAdsRepeat(); - if (delay != -1) saveSettings(ADS_DELAY, delay); - if (repeat != -1) saveSettings(ADS_REPEAT, repeat); - saveSettings(ADS_ENABLE, remoteSettings.isAdsEnabled()); - } } 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 e493d569..00000000 --- a/build/android/app/src/main/java/com/multicraft/game/helpers/Utilities.java +++ /dev/null @@ -1,125 +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.BuildConfig; -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.List; - -import static com.multicraft.game.helpers.ApiLevelHelper.isGreaterOrEqualKitkat; -import static com.multicraft.game.helpers.PreferencesHelper.TAG_SHORTCUT_EXIST; - -public class Utilities { - private static final String appPackage = BuildConfig.APPLICATION_ID; - - 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 boolean deleteFiles(List files) { - boolean result = true; - for (String f : files) { - File file = new File(f); - if (file.exists()) { - result = result && FileUtils.deleteQuietly(file); - } - } - return result; - } - - public static String getStoreUrl() { - String store = "market://details?id="; - return store + appPackage; - } - - public static void makeFullScreen(Activity activity) { - if (isGreaterOrEqualKitkat()) - 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 = 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.sendBroadcast(addIntent); - } -} 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 00000000..45d3fdad --- /dev/null +++ b/build/android/app/src/main/java/com/multicraft/game/helpers/Utilities.kt @@ -0,0 +1,163 @@ +/* +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.graphics.drawable.Drawable +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.isKitKat +import com.multicraft.game.helpers.ApiLevelHelper.isMarshmallow +import com.multicraft.game.helpers.ApiLevelHelper.isOreo +import com.multicraft.game.helpers.PreferencesHelper.TAG_SHORTCUT_EXIST +import com.multicraft.game.helpers.PreferencesHelper.getInstance +import java.io.File +import java.io.InputStream +import kotlin.math.roundToInt +import kotlin.system.exitProcess + +@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") +object Utilities { + @JvmStatic + fun deleteFiles(files: List, path: File) { + for (f in files) { + val file = File(path, f) + if (file.exists()) file.deleteRecursively() + } + } + + @JvmStatic + fun deleteFiles(files: List) { + for (file in files) + if (file.exists()) file.deleteRecursively() + } + + @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 (isKitKat) @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 + } else { + WindowCompat.setDecorFitsSystemWindows(window, false) + WindowInsetsControllerCompat(window, window.decorView).let { controller -> + controller.hide(statusBars() or navigationBars()) + controller.systemBarsBehavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + } + } + } + + @JvmStatic + fun getIcon(activity: Activity): Drawable? { + return try { + activity.packageManager.getApplicationIcon(activity.packageName) + } catch (e: PackageManager.NameNotFoundException) { + ContextCompat.getDrawable(activity, R.mipmap.ic_launcher) + } + } + + @JvmStatic + @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 + getInstance(activity).saveSettings(TAG_SHORTCUT_EXIST, true) + } + + @JvmStatic + @SuppressLint("UnspecifiedImmutableFlag") + fun finishApp(restart: Boolean, activity: Activity) { + if (restart) { + 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) + } + + @JvmStatic + fun File.copyInputStreamToFile(inputStream: InputStream) { + this.outputStream().use { fileOut -> inputStream.copyTo(fileOut) } + } + + @JvmStatic + 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 9d176304..00000000 --- a/build/android/app/src/main/java/com/multicraft/game/helpers/VersionManagerHelper.java +++ /dev/null @@ -1,207 +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.bugsnag.android.Bugsnag; -import com.multicraft.game.BuildConfig; -import com.multicraft.game.RemoteSettings; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONTokener; -import org.xml.sax.XMLReader; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; -import java.util.Locale; -import java.util.concurrent.TimeUnit; - -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; - -import static com.multicraft.game.MainActivity.UPDATE_LINK; -import static com.multicraft.game.helpers.Utilities.getStoreUrl; - -public class VersionManagerHelper { - private static final String JSON_VERSION_CODE = "version_code"; - private static final String JSON_VERSION_CODE_BAD = "version_code_bad"; - private static final String JSON_PACKAGE = "package"; - private static final String JSON_CONTENT_RU = "content_ru"; - private static final String JSON_CONTENT_EN = "content_en"; - private static final String JSON_ADS_DELAY = "ads_delay"; - private static final String JSON_ADS_REPEAT = "ads_repeat"; - private static final String JSON_ADS_ENABLE = "ads_enable"; - private final CustomTagHandler customTagHandler; - private final String PREF_REMINDER_TIME = "w.reminder.time"; - private final AppCompatActivity activity; - private final int versionCode = BuildConfig.VERSION_CODE; - 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 List convertToList(JSONArray badVersions) throws JSONException { - List badVersionList = new ArrayList<>(); - if (badVersions != null) { - for (int i = 0; i < badVersions.length(); i++) - badVersionList.add(badVersions.getInt(i)); - } - return badVersionList; - } - - private RemoteSettings parseJson(String result) throws JSONException { - RemoteSettings remoteSettings = new RemoteSettings(); - PreferencesHelper pf = PreferencesHelper.getInstance(activity); - if (!result.startsWith("{")) // for response who append with unknown char - result = result.substring(1); - String mResult = result; - // json format from server: - JSONObject json = new JSONObject(new JSONTokener(mResult)); - remoteSettings.setVersionCode(json.getInt(JSON_VERSION_CODE)); - remoteSettings.setBadVersionCodes(convertToList(json.getJSONArray(JSON_VERSION_CODE_BAD))); - String lang = Locale.getDefault().getLanguage(); - String content = lang.equals("ru") ? JSON_CONTENT_RU : JSON_CONTENT_EN; - remoteSettings.setContent(json.getString(content)); - setMessage(remoteSettings.getContent()); - remoteSettings.setPackageName(json.getString(JSON_PACKAGE)); - setUpdateUrl("market://details?id=" + remoteSettings.getPackageName()); - remoteSettings.setAdsDelay(json.getInt(JSON_ADS_DELAY)); - remoteSettings.setAdsRepeat(json.getInt(JSON_ADS_REPEAT)); - remoteSettings.setAdsEnabled(json.getBoolean(JSON_ADS_ENABLE)); - pf.saveAdsSettings(remoteSettings); - return remoteSettings; - } - - public boolean isShow(String result) { - if (result.equals("{}")) return false; - RemoteSettings remoteSettings; - try { - remoteSettings = parseJson(result); - } catch (JSONException e) { - return false; - } - return (versionCode < remoteSettings.getVersionCode()) || - isBadVersion(remoteSettings.getBadVersionCodes()); - } - - public String getJson() { - OkHttpClient client = new OkHttpClient.Builder() - .callTimeout(3000, TimeUnit.MILLISECONDS) - .build(); - Request request = new Request.Builder() - .url(UPDATE_LINK) - .build(); - try { - Response response = client.newCall(request).execute(); - return response.body().string(); - } catch (IOException | NullPointerException e) { - // nothing - } - return "{}"; - } - - 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) { - Bugsnag.notify(e); - } - } - } - - 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/res/drawable/background.png b/build/android/app/src/main/res/drawable/background.png index 55afbb6f..84f1fd4c 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 f5e0ff00..00000000 --- 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 d72c5785..00000000 --- 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/ic_launcher_background.xml b/build/android/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index fe5102ec..00000000 --- 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/layout/activity_main.xml b/build/android/app/src/main/res/layout/activity_main.xml index 1f364d80..24dd23e1 100644 --- a/build/android/app/src/main/res/layout/activity_main.xml +++ b/build/android/app/src/main/res/layout/activity_main.xml @@ -3,8 +3,8 @@ android:layout_height="match_parent"> + 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 00000000..a27bf6e2 --- /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 e0515207..00000000 --- a/build/android/app/src/main/res/layout/rate_dialog.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - -