1
0

Android: update Kotlin part (#150)

This commit is contained in:
Bektur 2023-10-26 21:25:16 +06:00 committed by mckaygerhard
parent a6f200ff21
commit 1538e5bc99
58 changed files with 645 additions and 415 deletions

View File

@ -2,13 +2,13 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
android { android {
compileSdkVersion 33 compileSdkVersion 34
buildToolsVersion '33.0.2' buildToolsVersion '34.0.0'
ndkVersion '25.2.9519653' ndkVersion '25.2.9519653'
defaultConfig { defaultConfig {
applicationId 'com.multicraft.game' applicationId 'com.multicraft.game'
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 33 targetSdkVersion 34
versionName "${versionMajor}.${versionMinor}.${versionPatch}" versionName "${versionMajor}.${versionMinor}.${versionPatch}"
versionCode project.versionCode versionCode project.versionCode
} }
@ -100,7 +100,7 @@ tasks.register('prepareAssetsFiles') {
tasks.register('zipAssetsFiles', Zip) { tasks.register('zipAssetsFiles', Zip) {
dependsOn prepareAssetsFiles dependsOn prepareAssetsFiles
archiveFileName = 'assets.zip' archiveFileName = 'assets.zip'
destinationDirectory = file('src/main/assets/data') destinationDirectory = file('src/main/assets')
from('build/assets/Files') from('build/assets/Files')
} }
@ -125,7 +125,8 @@ dependencies {
/* Third-party libraries */ /* Third-party libraries */
implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.appcompat:appcompat-resources:1.6.1' implementation 'androidx.appcompat:appcompat-resources:1.6.1'
implementation("androidx.browser:browser:1.6.0")
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
implementation 'androidx.work:work-runtime-ktx:2.8.1' implementation 'androidx.work:work-runtime-ktx:2.8.1'
implementation 'com.google.android.material:material:1.9.0' implementation 'com.google.android.material:material:1.10.0'
} }

View File

@ -28,7 +28,6 @@
<application <application
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="false"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
@ -42,8 +41,8 @@
android:value="3.0" /> android:value="3.0" />
<activity <activity
android:name="com.multicraft.game.MainActivity" android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|navigation|screenSize" android:configChanges="orientation|keyboardHidden|navigation|screenSize|screenLayout"
android:exported="true" android:exported="true"
android:maxAspectRatio="3.0" android:maxAspectRatio="3.0"
android:screenOrientation="sensorLandscape" android:screenOrientation="sensorLandscape"
@ -55,8 +54,8 @@
</activity> </activity>
<activity <activity
android:name="com.multicraft.game.GameActivity" android:name=".GameActivity"
android:configChanges="orientation|keyboard|keyboardHidden|navigation|screenSize|smallestScreenSize" android:configChanges="orientation|keyboard|keyboardHidden|navigation|screenSize|smallestScreenSize|screenLayout|uiMode"
android:exported="true" android:exported="true"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:launchMode="singleTask" android:launchMode="singleTask"
@ -72,6 +71,19 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".dialogs.ConnectionDialog"
android:configChanges="orientation|keyboardHidden|navigation|screenSize"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:theme="@style/CustomDialog" />
<activity
android:name=".dialogs.RestartDialog"
android:configChanges="orientation|keyboardHidden|navigation|screenSize"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:theme="@style/CustomDialog" />
</application> </application>
</manifest> </manifest>

View File

@ -1,7 +1,7 @@
/* /*
MultiCraft MultiCraft
Copyright (C) 2014-2022 MoNTE48, Maksim Gamarnik <Maksym48@pm.me> Copyright (C) 2014-2023 MoNTE48, Maksim Gamarnik <Maksym48@pm.me>
Copyright (C) 2014-2022 ubulem, Bektur Mambetov <berkut87@gmail.com> Copyright (C) 2014-2023 ubulem, Bektur Mambetov <berkut87@gmail.com>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,7 +1,7 @@
/* /*
MultiCraft MultiCraft
Copyright (C) 2014-2022 MoNTE48, Maksim Gamarnik <Maksym48@pm.me> Copyright (C) 2014-2023 MoNTE48, Maksim Gamarnik <Maksym48@pm.me>
Copyright (C) 2014-2022 ubulem, Bektur Mambetov <berkut87@gmail.com> Copyright (C) 2014-2023 ubulem, Bektur Mambetov <berkut87@gmail.com>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by
@ -20,11 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
package com.multicraft.game package com.multicraft.game
import android.content.Intent
import android.content.res.Configuration import android.content.res.Configuration
import android.content.res.Configuration.HARDKEYBOARDHIDDEN_NO
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.*
import android.text.InputType import android.text.InputType
import android.view.* import android.view.*
import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
@ -33,12 +31,15 @@ import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.browser.customtabs.CustomTabsIntent
import androidx.browser.customtabs.CustomTabsIntent.SHARE_STATE_OFF
import com.multicraft.game.MainActivity.Companion.radius import com.multicraft.game.MainActivity.Companion.radius
import com.multicraft.game.databinding.InputTextBinding import com.multicraft.game.databinding.*
import com.multicraft.game.databinding.MultilineInputBinding
import com.multicraft.game.helpers.* import com.multicraft.game.helpers.*
import com.multicraft.game.helpers.ApiLevelHelper.isOreo import com.multicraft.game.helpers.ApiLevelHelper.isOreo
import org.libsdl.app.SDLActivity import org.libsdl.app.SDLActivity
import java.util.*
import kotlin.system.exitProcess
class GameActivity : SDLActivity() { class GameActivity : SDLActivity() {
companion object { companion object {
@ -54,21 +55,21 @@ class GameActivity : SDLActivity() {
private var messageReturnValue = "" private var messageReturnValue = ""
private var hasKeyboard = false private var hasKeyboard = false
override fun getLibraries() = arrayOf("MultiCraft")
override fun getLibraries(): Array<String> { override fun getMainSharedObject() =
return arrayOf( "${getContext().applicationInfo.nativeLibraryDir}/libMultiCraft.so"
"MultiCraft"
)
}
override fun getMainSharedObject(): String {
return getContext().applicationInfo.nativeLibraryDir + "/libMultiCraft.so"
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) try {
super.onCreate(savedInstanceState)
} catch (e: Error) {
exitProcess(0)
} catch (e: Exception) {
exitProcess(0)
}
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
hasKeyboard = resources.configuration.hardKeyboardHidden == HARDKEYBOARDHIDDEN_NO hasKeyboard = hasHardKeyboard()
} }
override fun onWindowFocusChanged(hasFocus: Boolean) { override fun onWindowFocusChanged(hasFocus: Boolean) {
@ -88,15 +89,13 @@ class GameActivity : SDLActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (hasKeyboard) if (hasKeyboard) keyboardEvent(true)
keyboardEvent(hasKeyboard)
window.makeFullScreen() window.makeFullScreen()
} }
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig) super.onConfigurationChanged(newConfig)
val statusKeyboard = val statusKeyboard = hasHardKeyboard()
resources.configuration.hardKeyboardHidden == HARDKEYBOARDHIDDEN_NO
if (hasKeyboard != statusKeyboard) { if (hasKeyboard != statusKeyboard) {
hasKeyboard = statusKeyboard hasKeyboard = statusKeyboard
keyboardEvent(hasKeyboard) keyboardEvent(hasKeyboard)
@ -137,8 +136,8 @@ class GameActivity : SDLActivity() {
editText.inputType = inputType editText.inputType = inputType
editText.setSelection(editText.text?.length ?: 0) editText.setSelection(editText.text?.length ?: 0)
// for Android OS // for Android OS
editText.setOnEditorActionListener { _: TextView?, KeyCode: Int, _: KeyEvent? -> editText.setOnEditorActionListener { _: TextView?, keyCode: Int, _: KeyEvent? ->
if (KeyCode == KeyEvent.KEYCODE_ENTER || KeyCode == KeyEvent.KEYCODE_ENDCALL) { if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_ENDCALL) {
imm.hideSoftInputFromWindow(editText.windowToken, 0) imm.hideSoftInputFromWindow(editText.windowToken, 0)
messageReturnValue = editText.text.toString() messageReturnValue = editText.text.toString()
alertDialog.dismiss() alertDialog.dismiss()
@ -147,16 +146,17 @@ class GameActivity : SDLActivity() {
} }
return@setOnEditorActionListener false return@setOnEditorActionListener false
} }
// for Chrome OS if (isChromebook()) {
editText.setOnKeyListener { _: View?, KeyCode: Int, _: KeyEvent? -> editText.setOnKeyListener { _: View?, keyCode: Int, _: KeyEvent? ->
if (KeyCode == KeyEvent.KEYCODE_ENTER || KeyCode == KeyEvent.KEYCODE_ENDCALL) { if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_ENDCALL) {
imm.hideSoftInputFromWindow(editText.windowToken, 0) imm.hideSoftInputFromWindow(editText.windowToken, 0)
messageReturnValue = editText.text.toString() messageReturnValue = editText.text.toString()
alertDialog.dismiss() alertDialog.dismiss()
isInputActive = false isInputActive = false
return@setOnKeyListener true return@setOnKeyListener true
}
return@setOnKeyListener false
} }
return@setOnKeyListener false
} }
binding.input.setEndIconOnClickListener { binding.input.setEndIconOnClickListener {
imm.hideSoftInputFromWindow(editText.windowToken, 0) imm.hideSoftInputFromWindow(editText.windowToken, 0)
@ -174,7 +174,7 @@ class GameActivity : SDLActivity() {
// should be above `show()` // should be above `show()`
alertWindow.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE) alertWindow.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE)
alertDialog.show() alertDialog.show()
if (!resources.getBoolean(R.bool.isTablet)) if (!isTablet())
alertWindow.makeFullScreenAlert() alertWindow.makeFullScreenAlert()
alertDialog.setOnCancelListener { alertDialog.setOnCancelListener {
window.setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_HIDDEN) window.setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_HIDDEN)
@ -200,8 +200,8 @@ class GameActivity : SDLActivity() {
editText.setSelection(editText.text?.length ?: 0) editText.setSelection(editText.text?.length ?: 0)
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
// for Android OS // for Android OS
editText.setOnEditorActionListener { _: TextView?, KeyCode: Int, _: KeyEvent? -> editText.setOnEditorActionListener { _: TextView?, keyCode: Int, _: KeyEvent? ->
if (KeyCode == KeyEvent.KEYCODE_ENTER || KeyCode == KeyEvent.KEYCODE_ENDCALL) { if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_ENDCALL) {
imm.hideSoftInputFromWindow(editText.windowToken, 0) imm.hideSoftInputFromWindow(editText.windowToken, 0)
messageReturnValue = editText.text.toString() messageReturnValue = editText.text.toString()
alertDialog.dismiss() alertDialog.dismiss()
@ -210,16 +210,17 @@ class GameActivity : SDLActivity() {
} }
return@setOnEditorActionListener false return@setOnEditorActionListener false
} }
// for Chrome OS if (isChromebook()) {
editText.setOnKeyListener { _: View?, KeyCode: Int, _: KeyEvent? -> editText.setOnKeyListener { _: View?, keyCode: Int, _: KeyEvent? ->
if (KeyCode == KeyEvent.KEYCODE_ENTER || KeyCode == KeyEvent.KEYCODE_ENDCALL) { if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_ENDCALL) {
imm.hideSoftInputFromWindow(editText.windowToken, 0) imm.hideSoftInputFromWindow(editText.windowToken, 0)
messageReturnValue = editText.text.toString() messageReturnValue = editText.text.toString()
alertDialog.dismiss() alertDialog.dismiss()
isInputActive = false isInputActive = false
return@setOnKeyListener true return@setOnKeyListener true
}
return@setOnKeyListener false
} }
return@setOnKeyListener false
} }
binding.multiInput.setEndIconOnClickListener { binding.multiInput.setEndIconOnClickListener {
imm.hideSoftInputFromWindow(editText.windowToken, 0) imm.hideSoftInputFromWindow(editText.windowToken, 0)
@ -237,7 +238,7 @@ class GameActivity : SDLActivity() {
val alertWindow = alertDialog.window!! val alertWindow = alertDialog.window!!
alertWindow.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE) alertWindow.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE)
alertDialog.show() alertDialog.show()
if (!resources.getBoolean(R.bool.isTablet)) if (!isTablet())
alertWindow.makeFullScreenAlert() alertWindow.makeFullScreenAlert()
alertDialog.setOnCancelListener { alertDialog.setOnCancelListener {
window.setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_HIDDEN) window.setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_HIDDEN)
@ -270,9 +271,13 @@ class GameActivity : SDLActivity() {
@Suppress("unused") @Suppress("unused")
fun openURI(uri: String?) { fun openURI(uri: String?) {
val builder = CustomTabsIntent.Builder()
builder.setShareState(SHARE_STATE_OFF)
.setStartAnimations(this, R.anim.slide_in_bottom, R.anim.slide_out_top)
.setExitAnimations(this, R.anim.slide_in_top, R.anim.slide_out_bottom)
val customTabsIntent = builder.build()
try { try {
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(uri)) customTabsIntent.launchUrl(this, Uri.parse(uri))
startActivity(browserIntent)
} catch (ignored: Exception) { } catch (ignored: Exception) {
} }
} }
@ -292,7 +297,7 @@ class GameActivity : SDLActivity() {
@Suppress("unused") @Suppress("unused")
fun getSecretKey(key: String): String { fun getSecretKey(key: String): String {
return "Stub" return key
} }
@Suppress("unused") @Suppress("unused")

View File

@ -1,7 +1,7 @@
/* /*
MultiCraft MultiCraft
Copyright (C) 2014-2022 MoNTE48, Maksim Gamarnik <Maksym48@pm.me> Copyright (C) 2014-2023 MoNTE48, Maksim Gamarnik <Maksym48@pm.me>
Copyright (C) 2014-2022 ubulem, Bektur Mambetov <berkut87@gmail.com> Copyright (C) 2014-2023 ubulem, Bektur Mambetov <berkut87@gmail.com>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by
@ -22,18 +22,25 @@ package com.multicraft.game
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.graphics.Color import android.graphics.drawable.AnimationDrawable
import android.graphics.drawable.LayerDrawable
import android.os.Bundle import android.os.Bundle
import android.view.* import android.provider.Settings.ACTION_WIFI_SETTINGS
import android.provider.Settings.ACTION_WIRELESS_SETTINGS
import android.view.RoundedCorner
import android.view.WindowManager
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.graphics.BlendModeColorFilterCompat import androidx.lifecycle.Observer
import androidx.core.graphics.BlendModeCompat import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.* import androidx.lifecycle.lifecycleScope
import androidx.work.WorkInfo import androidx.work.WorkInfo
import com.multicraft.game.databinding.ActivityMainBinding import com.multicraft.game.databinding.ActivityMainBinding
import com.multicraft.game.dialogs.ConnectionDialog
import com.multicraft.game.helpers.* import com.multicraft.game.helpers.*
import com.multicraft.game.helpers.ApiLevelHelper.isAndroid12 import com.multicraft.game.helpers.ApiLevelHelper.isAndroid12
import com.multicraft.game.helpers.ApiLevelHelper.isPie
import com.multicraft.game.helpers.PreferenceHelper.TAG_BUILD_VER import com.multicraft.game.helpers.PreferenceHelper.TAG_BUILD_VER
import com.multicraft.game.helpers.PreferenceHelper.getStringValue import com.multicraft.game.helpers.PreferenceHelper.getStringValue
import com.multicraft.game.helpers.PreferenceHelper.set import com.multicraft.game.helpers.PreferenceHelper.set
@ -49,11 +56,14 @@ class MainActivity : AppCompatActivity() {
private var externalStorage: File? = null private var externalStorage: File? = null
private val sep = File.separator private val sep = File.separator
private lateinit var prefs: SharedPreferences private lateinit var prefs: SharedPreferences
private lateinit var restartStartForResult: ActivityResultLauncher<Intent>
private lateinit var connStartForResult: ActivityResultLauncher<Intent>
private val versionCode = BuildConfig.VERSION_CODE private val versionCode = BuildConfig.VERSION_CODE
private val versionName = "${BuildConfig.VERSION_NAME}+$versionCode" private val versionName = "${BuildConfig.VERSION_NAME}+$versionCode"
companion object { companion object {
var radius = 0 var radius = 0
const val NO_SPACE_LEFT = "ENOSPC"
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -61,30 +71,34 @@ class MainActivity : AppCompatActivity() {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
}
})
connStartForResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
checkAppVersion()
}
restartStartForResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == RESULT_OK)
finishApp(true)
else
finishApp(false)
}
try { try {
prefs = PreferenceHelper.init(this) prefs = PreferenceHelper.init(this)
externalStorage = getExternalFilesDir(null) externalStorage = getExternalFilesDir(null)
if (filesDir == null || cacheDir == null || externalStorage == null) listOf(filesDir, cacheDir, externalStorage).requireNoNulls()
throw IOException("Bad disk space state")
checkConnection() checkConnection()
} catch (e: Exception) { // Storage -> IOException, Prefs -> GeneralSecurityException } catch (e: Exception) {
showRestartDialog(!e.message!!.contains("ENOPSC")) val isRestart = e.message?.contains(NO_SPACE_LEFT) != true
showRestartDialog(restartStartForResult, isRestart)
} }
} }
@Deprecated("Deprecated in Java")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
@Suppress("DEPRECATION")
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 104)
checkAppVersion()
}
@Deprecated("Deprecated in Java")
override fun onBackPressed() {
// Prevent abrupt interruption when copy game files from assets
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
window.makeFullScreen() window.makeFullScreen()
@ -97,81 +111,66 @@ class MainActivity : AppCompatActivity() {
override fun onAttachedToWindow() { override fun onAttachedToWindow() {
super.onAttachedToWindow() super.onAttachedToWindow()
if (isAndroid12()) { if (isPie()) {
val insets = window.decorView.rootWindowInsets val cutout = window.decorView.rootWindowInsets.displayCutout
if (insets != null) { if (cutout != null) {
val tl = insets.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT) radius = 40
radius = tl?.radius ?: 0 }
if (isAndroid12()) {
val insets = window.decorView.rootWindowInsets
if (insets != null) {
val tl = insets.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT)
radius = tl?.radius ?: if (cutout != null) 40 else 0
}
} }
} }
} val animation = binding.loadingAnim.drawable as AnimationDrawable
animation.start()
// interface
private fun showProgress(textMessage: Int, progress: Int) {
if (binding.progressBar.visibility == View.GONE) {
binding.tvProgress.setText(textMessage)
binding.progressCircle.visibility = View.GONE
binding.progressBar.visibility = View.VISIBLE
binding.progressBar.progress = 0
} else if (progress > 0) {
val progressMessage = "${getString(textMessage)} $progress%"
binding.tvProgress.text = progressMessage
binding.progressBar.progress = progress
// colorize the progress bar
val progressBarDrawable =
(binding.progressBar.progressDrawable as LayerDrawable).getDrawable(0)
val progressDrawable = (progressBarDrawable as LayerDrawable).getDrawable(1)
val color = Color.rgb(255 - progress * 2, progress * 2, 25)
progressDrawable.colorFilter =
BlendModeColorFilterCompat.createBlendModeColorFilterCompat(
color, BlendModeCompat.SRC_IN
)
}
} }
private fun startNative() { private fun startNative() {
val initLua = File(filesDir, "builtin${sep}mainmenu${sep}init.lua") val initLua = File(filesDir, "builtin${sep}mainmenu${sep}init.lua")
if (initLua.exists() && initLua.canRead()) { if (initLua.exists() && initLua.canRead()) {
val intent = Intent(this, GameActivity::class.java) val intent = Intent(this, GameActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent) startActivity(intent)
} else { } else {
prefs[TAG_BUILD_VER] = "0" prefs[TAG_BUILD_VER] = "0"
showRestartDialog() showRestartDialog(restartStartForResult)
} }
} }
private fun prepareToRun() { private fun prepareToRun() {
binding.tvProgress.setText(R.string.preparing) val filesList = mutableListOf<File>().apply {
binding.progressCircle.visibility = View.VISIBLE addAll(listOf(
binding.progressBar.visibility = View.GONE "builtin",
val filesList = listOf( "client${sep}shaders",
File(externalStorage, "debug.txt"), "fonts",
File(filesDir, "builtin"), "games${sep}default",
File(filesDir, "client"), "textures${sep}base"
File(filesDir, "fonts"), ).map { File(filesDir, it) })
File(filesDir, "textures") }
)
val zips = assets.list("data")!!.toList() val zips = mutableListOf("assets.zip")
lifecycleScope.launch { lifecycleScope.launch {
filesList.forEach { it.deleteRecursively() } filesList.forEach { it.deleteRecursively() }
zips.forEach { zips.forEach {
try { try {
assets.open("data$sep$it").use { input -> assets.open(it).use { input ->
File(cacheDir, it).copyInputStreamToFile(input) File(cacheDir, it).copyInputStreamToFile(input)
} }
} catch (e: IOException) { } catch (e: IOException) {
runOnUiThread { showRestartDialog(!e.message!!.contains("ENOSPC")) } val isNotEnoughSpace = e.message!!.contains(NO_SPACE_LEFT)
runOnUiThread { showRestartDialog(restartStartForResult, !isNotEnoughSpace) }
return@forEach return@forEach
} }
} }
try { try {
startUnzipWorker(zips) startUnzipWorker(zips.toTypedArray())
} catch (e: Exception) { } catch (e: Exception) {
runOnUiThread { showRestartDialog() } runOnUiThread { showRestartDialog(restartStartForResult) }
} }
} }
} }
@ -184,31 +183,47 @@ class MainActivity : AppCompatActivity() {
prepareToRun() prepareToRun()
} }
private fun showConnectionDialog() {
val intent = Intent(this, ConnectionDialog::class.java)
val startForResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
when (it.resultCode) {
RESULT_OK -> connStartForResult.launch(Intent(ACTION_WIFI_SETTINGS))
RESULT_FIRST_USER -> connStartForResult.launch(Intent(ACTION_WIRELESS_SETTINGS))
else -> checkAppVersion()
}
}
startForResult.launch(intent)
}
// check connection available // check connection available
private fun checkConnection() = lifecycleScope.launch { private fun checkConnection() = lifecycleScope.launch {
val result = isConnected() if (isConnected()) checkAppVersion()
if (result) checkAppVersion()
else try { else try {
showConnectionDialog { checkAppVersion() } showConnectionDialog()
} catch (e: Exception) { } catch (e: Exception) {
checkAppVersion() checkAppVersion()
} }
} }
private fun startUnzipWorker(file: List<String>) { private fun startUnzipWorker(file: Array<String>) {
val viewModelFactory = WorkerViewModelFactory(application, file.toTypedArray()) val viewModelFactory = WorkerViewModelFactory(application, file)
val viewModel = ViewModelProvider(this, viewModelFactory)[WorkerViewModel::class.java] val viewModel = ViewModelProvider(this, viewModelFactory)[WorkerViewModel::class.java]
viewModel.unzippingWorkObserver viewModel.unzippingWorkObserver
.observe(this, Observer { workInfo -> .observe(this, Observer { workInfo ->
if (workInfo == null) if (workInfo == null)
return@Observer return@Observer
val progress = workInfo.progress.getInt(PROGRESS, 0) val progress = workInfo.progress.getInt(PROGRESS, 0)
showProgress(R.string.loading, progress) if (progress > 0) {
val progressMessage = "${getString(R.string.loading)} $progress%"
binding.tvProgress.text = progressMessage
}
if (workInfo.state.isFinished) { if (workInfo.state.isFinished) {
if (workInfo.state == WorkInfo.State.FAILED) { if (workInfo.state == WorkInfo.State.FAILED) {
val isRestart = workInfo.outputData.getBoolean("restart", true) val isRestart = workInfo.outputData.getBoolean("restart", true)
showRestartDialog(isRestart) showRestartDialog(restartStartForResult, isRestart)
} else if (workInfo.state == WorkInfo.State.SUCCEEDED) { } else if (workInfo.state == WorkInfo.State.SUCCEEDED) {
prefs[TAG_BUILD_VER] = versionName prefs[TAG_BUILD_VER] = versionName
startNative() startNative()

View File

@ -0,0 +1,96 @@
/*
MultiCraft
Copyright (C) 2014-2023 MoNTE48, Maksim Gamarnik <Maksym48@pm.me>
Copyright (C) 2014-2023 ubulem, Bektur Mambetov <berkut87@gmail.com>
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.dialogs
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import android.telephony.TelephonyManager
import android.telephony.TelephonyManager.SIM_STATE_READY
import android.view.View
import android.widget.LinearLayout
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import com.multicraft.game.databinding.ConnectionDialogBinding
import com.multicraft.game.helpers.ApiLevelHelper.isOreo
import com.multicraft.game.helpers.makeFullScreen
import org.libsdl.app.SDLActivity
class ConnectionDialog : AppCompatActivity() {
private fun isSimCardPresent(): Boolean {
val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
if (!isOreo())
return telephonyManager.simState == SIM_STATE_READY
val isFirstSimPresent = telephonyManager.getSimState(0) == SIM_STATE_READY
val isSecondSimPresent = telephonyManager.getSimState(1) == SIM_STATE_READY
return isFirstSimPresent || isSecondSimPresent
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ConnectionDialogBinding.inflate(layoutInflater)
if (SDLActivity.isTablet()) {
val param = LinearLayout.LayoutParams(
0,
LinearLayout.LayoutParams.WRAP_CONTENT,
0.5f
)
binding.connRoot.layoutParams = param
}
if (isSimCardPresent())
binding.mobile.visibility = View.VISIBLE
setContentView(binding.root)
onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
}
})
binding.wifi.setOnClickListener {
setResult(Activity.RESULT_OK)
finish()
}
binding.mobile.setOnClickListener {
setResult(Activity.RESULT_FIRST_USER)
finish()
}
binding.ignore.setOnClickListener {
setResult(Activity.RESULT_CANCELED)
finish()
}
}
override fun onResume() {
super.onResume()
window.makeFullScreen()
}
override fun attachBaseContext(base: Context?) {
val configuration = Configuration(base?.resources?.configuration)
configuration.fontScale = 1.0f
applyOverrideConfiguration(configuration)
super.attachBaseContext(base)
}
}

View File

@ -0,0 +1,76 @@
/*
MultiCraft
Copyright (C) 2014-2023 MoNTE48, Maksim Gamarnik <Maksym48@pm.me>
Copyright (C) 2014-2023 ubulem, Bektur Mambetov <berkut87@gmail.com>
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.dialogs
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import android.widget.LinearLayout
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import com.multicraft.game.databinding.RestartDialogBinding
import com.multicraft.game.helpers.makeFullScreen
import org.libsdl.app.SDLActivity
class RestartDialog : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = RestartDialogBinding.inflate(layoutInflater)
if (SDLActivity.isTablet()) {
val param = LinearLayout.LayoutParams(
0,
LinearLayout.LayoutParams.WRAP_CONTENT,
0.5f
)
binding.restartRoot.layoutParams = param
}
setContentView(binding.root)
onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
}
})
val message = intent.getStringExtra("message")!!
binding.errorDesc.text = message
binding.restart.setOnClickListener {
setResult(Activity.RESULT_OK)
finish()
}
binding.close.setOnClickListener {
setResult(Activity.RESULT_CANCELED)
finish()
}
}
override fun onResume() {
super.onResume()
window.makeFullScreen()
}
override fun attachBaseContext(base: Context?) {
val configuration = Configuration(base?.resources?.configuration)
configuration.fontScale = 1.0f
applyOverrideConfiguration(configuration)
super.attachBaseContext(base)
}
}

View File

@ -1,7 +1,7 @@
/* /*
MultiCraft MultiCraft
Copyright (C) 2014-2022 MoNTE48, Maksim Gamarnik <Maksym48@pm.me> Copyright (C) 2014-2023 MoNTE48, Maksim Gamarnik <Maksym48@pm.me>
Copyright (C) 2014-2022 ubulem, Bektur Mambetov <berkut87@gmail.com> Copyright (C) 2014-2023 ubulem, Bektur Mambetov <berkut87@gmail.com>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by
@ -30,5 +30,7 @@ object ApiLevelHelper {
fun isOreo() = isGreaterOrEqual(O) fun isOreo() = isGreaterOrEqual(O)
fun isPie() = isGreaterOrEqual(P)
fun isAndroid12() = isGreaterOrEqual(S) fun isAndroid12() = isGreaterOrEqual(S)
} }

View File

@ -1,7 +1,7 @@
/* /*
MultiCraft MultiCraft
Copyright (C) 2014-2022 MoNTE48, Maksim Gamarnik <Maksym48@pm.me> Copyright (C) 2014-2023 MoNTE48, Maksim Gamarnik <Maksym48@pm.me>
Copyright (C) 2014-2022 ubulem, Bektur Mambetov <berkut87@gmail.com> Copyright (C) 2014-2023 ubulem, Bektur Mambetov <berkut87@gmail.com>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,7 +1,7 @@
/* /*
MultiCraft MultiCraft
Copyright (C) 2014-2022 MoNTE48, Maksim Gamarnik <Maksym48@pm.me> Copyright (C) 2014-2023 MoNTE48, Maksim Gamarnik <Maksym48@pm.me>
Copyright (C) 2014-2022 ubulem, Bektur Mambetov <berkut87@gmail.com> Copyright (C) 2014-2023 ubulem, Bektur Mambetov <berkut87@gmail.com>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by
@ -23,31 +23,22 @@ package com.multicraft.game.helpers
import android.app.* import android.app.*
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.res.Configuration
import android.net.ConnectivityManager import android.net.*
import android.net.NetworkCapabilities import android.os.*
import android.provider.Settings
import android.view.View
import android.view.Window import android.view.Window
import androidx.appcompat.app.AlertDialog import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.* import androidx.core.view.*
import com.multicraft.game.R import com.multicraft.game.*
import com.multicraft.game.databinding.ConnDialogBinding import com.multicraft.game.databinding.*
import com.multicraft.game.databinding.RestartDialogBinding import com.multicraft.game.dialogs.RestartDialog
import com.multicraft.game.helpers.ApiLevelHelper.isAndroid12 import com.multicraft.game.helpers.ApiLevelHelper.isAndroid12
import java.io.File import com.multicraft.game.helpers.ApiLevelHelper.isMarshmallow
import java.io.InputStream import java.io.*
import kotlin.system.exitProcess import java.util.*
// Activity extensions // Activity extensions
fun AppCompatActivity.getIcon() = try {
packageManager.getApplicationIcon(packageName)
} catch (e: PackageManager.NameNotFoundException) {
ContextCompat.getDrawable(this, R.mipmap.ic_launcher)
}
fun Activity.finishApp(restart: Boolean) { fun Activity.finishApp(restart: Boolean) {
if (restart) { if (restart) {
val intent = Intent(this, this::class.java) val intent = Intent(this, this::class.java)
@ -61,72 +52,12 @@ fun Activity.finishApp(restart: Boolean) {
) )
) )
} }
exitProcess(0) finish()
} }
fun AppCompatActivity.defaultDialog(title: Int, view: View, style: Int = R.style.CustomDialog): AlertDialog { fun Activity.isConnected(): Boolean {
val builder = AlertDialog.Builder(this, style)
.setIcon(getIcon())
.setTitle(title)
.setCancelable(false)
.setView(view)
return builder.create()
}
fun AppCompatActivity.headlessDialog(
view: View,
style: Int = R.style.LightTheme,
isCancelable: Boolean = false
): AlertDialog {
val builder = AlertDialog.Builder(this, style)
.setCancelable(isCancelable)
.setView(view)
return builder.create()
}
fun AppCompatActivity.show(dialog: AlertDialog) {
window?.makeFullScreen()
if (!isFinishing) dialog.show()
}
fun AppCompatActivity.showConnectionDialog(listener: (() -> Unit)? = null) {
val binding = ConnDialogBinding.inflate(layoutInflater)
val dialog = defaultDialog(R.string.conn_title, binding.root)
binding.wifi.setOnClickListener {
dialog.dismiss()
startActivityForResult(
Intent(Settings.ACTION_WIFI_SETTINGS),
104
)
}
binding.mobile.setOnClickListener {
dialog.dismiss()
startActivityForResult(
Intent(Settings.ACTION_WIRELESS_SETTINGS),
104
)
}
binding.ignore.setOnClickListener {
dialog.dismiss()
listener?.invoke()
}
show(dialog)
}
fun AppCompatActivity.showRestartDialog(isRestart: Boolean = true) {
val message =
if (isRestart) getString(R.string.restart) else getString(R.string.no_space)
val binding = RestartDialogBinding.inflate(layoutInflater)
val dialog = headlessDialog(binding.root, R.style.CustomDialog)
binding.errorDesc.text = message
binding.close.setOnClickListener { finishApp(false) }
binding.restart.setOnClickListener { finishApp(true) }
show(dialog)
}
fun AppCompatActivity.isConnected(): Boolean {
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (ApiLevelHelper.isMarshmallow()) { if (isMarshmallow()) {
val activeNetwork = cm.activeNetwork ?: return false val activeNetwork = cm.activeNetwork ?: return false
val capabilities = cm.getNetworkCapabilities(activeNetwork) ?: return false val capabilities = cm.getNetworkCapabilities(activeNetwork) ?: return false
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
@ -136,6 +67,20 @@ fun AppCompatActivity.isConnected(): Boolean {
} }
} }
fun AppCompatActivity.showRestartDialog(
startForResult: ActivityResultLauncher<Intent>,
isRestart: Boolean = true
) {
val message =
if (isRestart) getString(R.string.restart) else getString(R.string.no_space)
val intent = Intent(this, RestartDialog::class.java)
intent.putExtra("message", message)
startForResult.launch(intent)
}
fun Activity.hasHardKeyboard() =
resources.configuration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO
// Other extensions // Other extensions
fun File.copyInputStreamToFile(inputStream: InputStream) = fun File.copyInputStreamToFile(inputStream: InputStream) =
outputStream().use { fileOut -> inputStream.copyTo(fileOut, 8192) } outputStream().use { fileOut -> inputStream.copyTo(fileOut, 8192) }

View File

@ -1,7 +1,7 @@
/* /*
MultiCraft MultiCraft
Copyright (C) 2014-2022 MoNTE48, Maksim Gamarnik <Maksym48@pm.me> Copyright (C) 2014-2023 MoNTE48, Maksim Gamarnik <Maksym48@pm.me>
Copyright (C) 2014-2022 ubulem, Bektur Mambetov <berkut87@gmail.com> Copyright (C) 2014-2023 ubulem, Bektur Mambetov <berkut87@gmail.com>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by
@ -26,6 +26,7 @@ import android.content.Context
import android.content.Context.NOTIFICATION_SERVICE import android.content.Context.NOTIFICATION_SERVICE
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.work.* import androidx.work.*
import com.multicraft.game.MainActivity.Companion.NO_SPACE_LEFT
import com.multicraft.game.R import com.multicraft.game.R
import com.multicraft.game.helpers.ApiLevelHelper.isOreo import com.multicraft.game.helpers.ApiLevelHelper.isOreo
import com.multicraft.game.helpers.copyInputStreamToFile import com.multicraft.game.helpers.copyInputStreamToFile
@ -83,7 +84,7 @@ class UnzipWorker(private val appContext: Context, workerParams: WorkerParameter
} }
Result.success() Result.success()
} catch (e: IOException) { } catch (e: IOException) {
val isNotEnoughSpace = e.localizedMessage!!.contains("ENOSPC") val isNotEnoughSpace = e.localizedMessage!!.contains(NO_SPACE_LEFT)
val out = Data.Builder() val out = Data.Builder()
.putBoolean("restart", !isNotEnoughSpace) .putBoolean("restart", !isNotEnoughSpace)
.build() .build()

View File

@ -1,7 +1,7 @@
/* /*
MultiCraft MultiCraft
Copyright (C) 2014-2022 MoNTE48, Maksim Gamarnik <Maksym48@pm.me> Copyright (C) 2014-2023 MoNTE48, Maksim Gamarnik <Maksym48@pm.me>
Copyright (C) 2014-2022 ubulem, Bektur Mambetov <berkut87@gmail.com> Copyright (C) 2014-2023 ubulem, Bektur Mambetov <berkut87@gmail.com>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by

View File

@ -1,7 +1,7 @@
/* /*
MultiCraft MultiCraft
Copyright (C) 2014-2022 MoNTE48, Maksim Gamarnik <Maksym48@pm.me> Copyright (C) 2014-2023 MoNTE48, Maksim Gamarnik <Maksym48@pm.me>
Copyright (C) 2014-2022 ubulem, Bektur Mambetov <berkut87@gmail.com> Copyright (C) 2014-2023 ubulem, Bektur Mambetov <berkut87@gmail.com>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_mediumAnimTime"
android:fromYDelta="100%p"
android:toYDelta="0%p" />

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_mediumAnimTime"
android:fromYDelta="-100%p"
android:toYDelta="0%p" />

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_mediumAnimTime"
android:fromYDelta="0%p"
android:toYDelta="100%p" />

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_mediumAnimTime"
android:fromYDelta="0%p"
android:toYDelta="-100%p" />

View File

@ -2,4 +2,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">
<solid android:color="@color/dark" /> <solid android:color="@color/dark" />
<corners
android:topLeftRadius="5dp"
android:topRightRadius="5dp" />
</shape> </shape>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/green_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/green" />
</selector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/red_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/red" />
</selector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/yellow_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/yellow" />
</selector>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@android:id/background"
android:drawable="@drawable/progress_bar_bg" />
<item
android:id="@android:id/progress"
android:drawable="@drawable/progress_bar_fg" />
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

View File

@ -6,6 +6,6 @@
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path <path
android:fillColor="#008C80" android:fillColor="@color/green_mc"
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z" /> android:pathData="M3.4,20.4l17.45,-7.48c0.81,-0.35 0.81,-1.49 0,-1.84L3.4,3.6c-0.66,-0.29 -1.39,0.2 -1.39,0.91L2,9.12c0,0.5 0.37,0.93 0.87,0.99L17,12 2.87,13.88c-0.5,0.07 -0.87,0.5 -0.87,1l0.01,4.61c0,0.71 0.73,1.2 1.39,0.91z" />
</vector> </vector>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item
android:drawable="@drawable/loading_anim1"
android:duration="125" />
<item
android:drawable="@drawable/loading_anim2"
android:duration="125" />
<item
android:drawable="@drawable/loading_anim3"
android:duration="125" />
<item
android:drawable="@drawable/loading_anim4"
android:duration="125" />
<item
android:drawable="@drawable/loading_anim5"
android:duration="125" />
<item
android:drawable="@drawable/loading_anim6"
android:duration="125" />
<item
android:drawable="@drawable/loading_anim7"
android:duration="125" />
<item
android:drawable="@drawable/loading_anim8"
android:duration="125" />
</animation-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1023 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1015 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1016 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 B

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/custom_progress_bar" />
<item android:drawable="@drawable/progress_bar" />
</layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

View File

@ -1,34 +1,22 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<ProgressBar <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/progress_bar" android:id="@+id/loading_anim"
style="@style/Widget.MaterialComponents.LinearProgressIndicator" android:layout_width="wrap_content"
android:layout_width="512dp" android:layout_height="wrap_content"
android:layout_height="64dp" app:srcCompat="@drawable/loading" />
android:layout_centerInParent="true"
android:indeterminate="false"
android:max="100"
android:progressDrawable="@drawable/progress"
android:visibility="gone" />
<ProgressBar
android:id="@+id/progress_circle"
style="@style/Widget.AppCompat.ProgressBar"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_centerInParent="true"
android:indeterminate="true" />
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_progress" android:id="@+id/tv_progress"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/progress_circle" android:layout_marginTop="8dp"
android:layout_centerInParent="true" android:text="@string/preparing"
android:text="@string/loading"
android:textColor="@color/light" android:textColor="@color/light"
android:textSize="14sp" /> android:textSize="16sp" />
</LinearLayout>
</RelativeLayout>

View File

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingLeft="16dp"
android:paddingTop="24dp"
android:paddingRight="16dp"
android:text="@string/conn_message"
android:textColor="@color/grey_900" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp">
<com.google.android.material.button.MaterialButton
android:id="@+id/ignore"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="0.3"
android:text="@string/ignore"
android:textAllCaps="false"
android:textColor="@android:color/white"
app:backgroundTint="@color/red" />
<com.google.android.material.button.MaterialButton
android:id="@+id/mobile"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="0.4"
android:text="@string/conn_mobile"
android:textAllCaps="false"
android:textColor="@android:color/white"
app:backgroundTint="@color/green_mc" />
<com.google.android.material.button.MaterialButton
android:id="@+id/wifi"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="0.4"
android:text="@string/conn_wifi"
android:textAllCaps="false"
android:textColor="@android:color/white"
app:backgroundTint="@color/green_mc" />
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@ -0,0 +1,78 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:gravity="center"
android:weightSum="1">
<LinearLayout
android:id="@+id/conn_root"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.7"
android:background="@drawable/bg_common"
android:orientation="vertical"
android:padding="16dp"
tools:ignore="UselessParent">
<androidx.appcompat.widget.AppCompatTextView
style="?android:attr/textAppearanceLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:drawableStart="@mipmap/ic_dialog"
android:drawablePadding="8dp"
android:gravity="center"
android:text="@string/conn_title"
android:textColor="@color/grey_900" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="8dp"
android:text="@string/conn_message"
android:textColor="@color/grey_900"
android:textSize="16sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/ignore"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_margin="8dp"
android:layout_weight="0.33"
android:background="@drawable/btn_yellow"
android:text="@string/ignore"
android:textAllCaps="false"
android:textColor="@android:color/white" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/mobile"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_margin="8dp"
android:layout_weight="0.33"
android:background="@drawable/btn_green"
android:text="@string/conn_mobile"
android:textAllCaps="false"
android:textColor="@android:color/white"
android:visibility="gone" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/wifi"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_margin="8dp"
android:layout_weight="0.33"
android:background="@drawable/btn_green"
android:text="@string/conn_wifi"
android:textAllCaps="false"
android:textColor="@android:color/white" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -6,16 +6,17 @@
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/input" android:id="@+id/input"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" style="@style/TextInputLayoutStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:background="@drawable/bg_input" android:background="@drawable/bg_input"
android:hint="@string/input_text" android:hint="@string/input_text"
android:padding="5dp" android:padding="4dp"
app:endIconDrawable="@drawable/ic_baseline_send" app:endIconDrawable="@drawable/ic_baseline_send"
app:endIconMode="custom" app:endIconMode="custom"
app:endIconTint="@null"> app:endIconTint="@null"
app:hintTextColor="@color/green_mc">
<com.multicraft.game.CustomEditText <com.multicraft.game.CustomEditText
android:id="@+id/editText" android:id="@+id/editText"

View File

@ -6,16 +6,17 @@
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/multiInput" android:id="@+id/multiInput"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" style="@style/TextInputLayoutStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:background="@drawable/bg_input" android:background="@drawable/bg_input"
android:hint="@string/input_text" android:hint="@string/input_text"
android:padding="5dp" android:padding="4dp"
app:endIconDrawable="@drawable/ic_baseline_send" app:endIconDrawable="@drawable/ic_baseline_send"
app:endIconMode="custom" app:endIconMode="custom"
app:endIconTint="@null"> app:endIconTint="@null"
app:hintTextColor="@color/green_mc">
<com.multicraft.game.CustomEditText <com.multicraft.game.CustomEditText
android:id="@+id/multiEditText" android:id="@+id/multiEditText"

View File

@ -1,34 +1,39 @@
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content" xmlns:tools="http://schemas.android.com/tools"
android:layout_height="wrap_content"> android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:gravity="center"
android:weightSum="1">
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:id="@+id/restart_root"
android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_weight="0.7"
android:background="@drawable/bg_common"
android:orientation="vertical" android:orientation="vertical"
android:paddingHorizontal="10dp" android:padding="16dp"
android:paddingTop="10dp"> tools:ignore="UselessParent">
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent" style="?android:attr/textAppearanceLarge"
android:layout_height="match_parent" android:layout_width="wrap_content"
android:layout_marginTop="8dp" android:layout_height="wrap_content"
android:layout_marginBottom="8dp" android:layout_gravity="center"
android:drawableStart="@mipmap/ic_dialog"
android:drawablePadding="8dp"
android:gravity="center" android:gravity="center"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:text="@string/sorry" android:text="@string/sorry"
android:textSize="22sp" /> android:textColor="@color/grey_900" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:orientation="horizontal"> android:padding="8dp">
<ImageView <androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/restart" android:contentDescription="@string/restart"
@ -42,46 +47,40 @@
android:id="@+id/error_desc" android:id="@+id/error_desc"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center"
android:minHeight="128dp" android:minHeight="128dp"
android:paddingStart="4dp" android:padding="4dp"
android:paddingTop="4dp"
android:paddingEnd="4dp"
android:paddingBottom="4dp"
android:text="@string/restart" android:text="@string/restart"
android:textSize="15sp" /> android:textColor="@color/grey_900"
android:textSize="16sp" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp">
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton <androidx.appcompat.widget.AppCompatButton
android:id="@+id/close" android:id="@+id/close"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="48dp"
android:layout_gravity="center" android:layout_margin="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="4dp"
android:layout_weight="0.5" android:layout_weight="0.5"
android:background="@drawable/btn_red"
android:text="@string/close_game" android:text="@string/close_game"
android:textStyle="bold" /> android:textAllCaps="false"
android:textColor="@android:color/white" />
<com.google.android.material.button.MaterialButton <androidx.appcompat.widget.AppCompatButton
android:id="@+id/restart" android:id="@+id/restart"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="48dp"
android:layout_gravity="center" android:layout_margin="8dp"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:layout_weight="0.5" android:layout_weight="0.5"
android:background="@drawable/btn_green"
android:text="@string/restart_game" android:text="@string/restart_game"
android:textStyle="bold" /> android:textAllCaps="false"
android:textColor="@android:color/white" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</ScrollView> </LinearLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- подготовка к запуску -->
<string name="preparing">Подготовка к запуску&#8230;</string> <string name="preparing">Подготовка к запуску&#8230;</string>
<string name="loading">Загрузка&#8230;</string> <string name="loading">Загрузка&#8230;</string>
<string name="notification_title">Загрузка MultiCraft</string> <string name="notification_title">Загрузка MultiCraft</string>
@ -9,9 +10,8 @@
<!-- диалог отсутствия подключения --> <!-- диалог отсутствия подключения -->
<string name="conn_title">Нет Интернет Подключения!</string> <string name="conn_title">Нет Интернет Подключения!</string>
<string name="conn_message">Для полноценной игры, MultiCraft требует подключение к Интернету.\nВ противном случае вам будет недоступно Обновление игры и режим Мультиплеера!</string> <string name="conn_message">Для полноценной игры, MultiCraft требует подключение к Интернету.\nВ противном случае Обновление игры и режим Мультиплеера будут недоступны!</string>
<string name="conn_mobile">3G/4G</string> <string name="ignore">Пропустить</string>
<string name="ignore">Игнорировать</string>
<!-- Crash --> <!-- Crash -->
<string name="sorry">Нам очень жаль!</string> <string name="sorry">Нам очень жаль!</string>

View File

@ -1,3 +0,0 @@
<resources>
<bool name="isTablet">true</bool>
</resources>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="CustomDialog" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="windowActionBar">false</item>
<item name="android:windowBackground">@drawable/bg</item>
<item name="android:windowFullscreen">true</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="p">shortEdges</item>
<item name="fontFamily">@font/multicraftfont</item>
</style>
</resources>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="CustomDialog" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="windowActionBar">false</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFullscreen">true</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="p">shortEdges</item>
<item name="fontFamily">@font/multicraftfont</item>
</style>
</resources>

View File

@ -1,3 +0,0 @@
<resources>
<bool name="isTablet">false</bool>
</resources>

View File

@ -1,8 +1,6 @@
<resources> <resources>
<color name="green">#008C80</color>
<color name="light">#FAFAFA</color> <color name="light">#FAFAFA</color>
<color name="dark">#121212</color> <color name="dark">#121212</color>
<color name="red">#FF1744</color>
<color name="green_mc">#32783C</color> <color name="green_mc">#32783C</color>
<color name="grey_900">#212121</color> <color name="grey_900">#212121</color>
</resources> </resources>

View File

@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name" translatable="false">MultiCraft</string> <string name="app_name" translatable="false">MultiCraft</string>
<!-- preparation for start -->
<string name="preparing">Preparing to launch&#8230;</string> <string name="preparing">Preparing to launch&#8230;</string>
<string name="loading">Loading&#8230;</string> <string name="loading">Loading&#8230;</string>
<string name="notification_title">Loading MultiCraft</string> <string name="notification_title">Loading MultiCraft</string>
<string name="notification_description">Less than 1 minute&#8230;</string> <string name="notification_description">Less than 1 minute&#8230;</string>
<string name="input_text">Enter text</string> <string name="input_text">Enter text</string>
<string name="input_password">Enter password</string> <string name="input_password">Enter password</string>
@ -13,7 +14,7 @@
<string name="conn_title">No Internet Connection!</string> <string name="conn_title">No Internet Connection!</string>
<string name="conn_message">MultiCraft requires an Internet connection to use all game features.\nOtherwise, you will not get Updates and Multiplayer mode will be not available!</string> <string name="conn_message">MultiCraft requires an Internet connection to use all game features.\nOtherwise, you will not get Updates and Multiplayer mode will be not available!</string>
<string name="conn_wifi" translatable="false">Wi-Fi</string> <string name="conn_wifi" translatable="false">Wi-Fi</string>
<string name="conn_mobile">Mobile Data</string> <string name="conn_mobile" translatable="false">LTE</string>
<string name="ignore">Ignore</string> <string name="ignore">Ignore</string>
<!-- Crash --> <!-- Crash -->

View File

@ -1,27 +1,25 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="windowActionBar">false</item> <item name="windowActionBar">false</item>
<item name="android:windowBackground">@drawable/bg</item> <item name="android:windowBackground">@drawable/bg</item>
<item name="android:windowFullscreen">true</item> <item name="android:windowFullscreen">true</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="p">shortEdges</item> <item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="p">shortEdges</item>
<item name="fontFamily">@font/multicraftfont</item> <item name="fontFamily">@font/multicraftfont</item>
<item name="colorPrimary">@color/green</item>
</style> </style>
<style name="LightTheme" parent="Theme.MaterialComponents.Light.Dialog"> <style name="CustomDialog" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="android:windowBackground">@drawable/bg_common</item> <item name="windowActionBar">false</item>
<item name="background">@android:color/transparent</item> <item name="android:windowIsTranslucent">true</item>
<item name="windowMinWidthMajor">0%</item> <item name="android:windowBackground">@android:color/transparent</item>
<item name="windowMinWidthMinor">0%</item> <item name="android:windowFullscreen">true</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="p">shortEdges</item>
<item name="fontFamily">@font/multicraftfont</item>
</style> </style>
<style name="CustomDialog" parent="Theme.MaterialComponents.Light.Dialog.Alert"> <style name="FullScreenDialogStyle" parent="Theme.MaterialComponents.Light.Dialog">
<item name="android:windowBackground">@drawable/bg_common</item>
<item name="background">@android:color/transparent</item>
</style>
<style name="FullScreenDialogStyle" parent="Theme.MaterialComponents.DayNight.Dialog">
<item name="android:windowFullscreen">true</item> <item name="android:windowFullscreen">true</item>
<item name="android:windowIsFloating">false</item> <item name="android:windowIsFloating">false</item>
<item name="android:backgroundDimEnabled">false</item> <item name="android:backgroundDimEnabled">false</item>
@ -29,4 +27,7 @@
<item name="android:windowEnterAnimation">@null</item> <item name="android:windowEnterAnimation">@null</item>
</style> </style>
<style name="TextInputLayoutStyle" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<item name="boxStrokeColor">@color/green_mc</item>
</style>
</resources> </resources>

View File

@ -2,12 +2,12 @@ apply plugin: 'com.android.library'
apply plugin: 'de.undercouch.download' apply plugin: 'de.undercouch.download'
android { android {
compileSdkVersion 33 compileSdkVersion 34
buildToolsVersion '33.0.2' buildToolsVersion '34.0.0'
ndkVersion '25.2.9519653' ndkVersion '25.2.9519653'
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 33 targetSdkVersion 34
externalNativeBuild { externalNativeBuild {
ndkBuild { ndkBuild {
arguments '-j' + Runtime.getRuntime().availableProcessors(), arguments '-j' + Runtime.getRuntime().availableProcessors(),