diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 57a572b..9d8d4b0 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -557,11 +557,18 @@ android {
}
//noinspection GrDeprecatedAPIUsage
buildToolsVersion = "34.0.0"
+ kotlinOptions {
+ jvmTarget = "17"
+ }
@Suppress("DEPRECATION") packagingOptions {
jniLibs {
useLegacyPackaging = true
}
}
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
}
java {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 26b0fe4..0f7f432 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,9 +1,4 @@
-
-
-
-
-
+
-
+ android:required="false" />
-
+ android:required="true" />
@@ -51,28 +43,35 @@
+
+
+
+
+
-
+ android:theme="@style/Theme.MagiskModuleManager.NoActionBar">
+
-
-->
-
-
-
+
+ android:theme="@style/Theme.MagiskModuleManager.NoActionBar">
@@ -148,18 +144,16 @@
-
-
+ android:theme="@style/Theme.MagiskModuleManager.NoActionBar">
-
@@ -184,7 +177,6 @@
android:name="androidx.work.WorkManagerInitializer"
tools:node="remove" />
-
-
-
-
+ android:value="https://e199c2a54a1f49b1b5beb3244f2c2358@sentry.androidacy.com/77" />
+
-
+ android:value="0.2" />
-
+ android:value="true" />
-
+ android:value="true" />
-
+ android:value="true" />
-
+
\ No newline at end of file
diff --git a/app/src/main/kotlin/com/fox2code/mmm/ExpiredActivity.kt b/app/src/main/kotlin/com/fox2code/mmm/ExpiredActivity.kt
new file mode 100644
index 0000000..ec2951d
--- /dev/null
+++ b/app/src/main/kotlin/com/fox2code/mmm/ExpiredActivity.kt
@@ -0,0 +1,35 @@
+package com.fox2code.mmm
+
+import android.annotation.SuppressLint
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import com.fox2code.foxcompat.app.FoxActivity
+import com.google.android.material.button.MaterialButton
+
+class ExpiredActivity : FoxActivity() {
+ @SuppressLint("RestrictedApi")
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_expired)
+ // download_button leads to the download page and uninstall_button leads to the uninstall dialog
+ val downloadBtn = findViewById(R.id.download_button)
+ val uninstallBtn = findViewById(R.id.uninstall_button)
+ downloadBtn.setOnClickListener {
+ // open https://www.androidacy.com/downloads/?view=FoxMMM
+ startActivity(
+ Intent(
+ Intent.ACTION_VIEW,
+ Uri.parse("https://www.androidacy.com/downloads/?view=FoxMMM")
+ )
+ )
+ }
+ uninstallBtn.setOnClickListener {
+ // open system uninstall dialog
+ val intent = Intent(Intent.ACTION_DELETE)
+ // discover our package name
+ intent.data = Uri.parse("package:$packageName")
+ startActivity(intent)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt b/app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt
index 2dfffd7..6a14c73 100644
--- a/app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt
+++ b/app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt
@@ -135,20 +135,28 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis
}
}.start()
val ts = Timestamp(System.currentTimeMillis() - 30L * 24 * 60 * 60 * 1000)
- // check if this build has expired
val buildTime = Timestamp(BuildConfig.BUILD_TIME)
- // if the build time is more than 30 days ago, throw an exception
if (BuildConfig.DEBUG) {
- check(ts.time < buildTime.time) { getString(R.string.build_expired) }
+ if (ts.time > buildTime.time) {
+ val pm = packageManager
+ val intent = Intent(this, ExpiredActivity::class.java)
+ @Suppress("DEPRECATION") val resolveInfo = pm.queryIntentActivities(intent, 0)
+ if (resolveInfo.size > 0) {
+ startActivity(intent)
+ finish()
+ return
+ } else {
+ throw IllegalAccessError("This build has expired")
+ }
+ }
} else {
- // non-debug builds expire after 1 year but only show a toast
val ts2 = Timestamp(System.currentTimeMillis() - 365L * 24 * 60 * 60 * 1000)
if (ts2.time > buildTime.time) {
Toast.makeText(this, R.string.build_expired, Toast.LENGTH_LONG).show()
}
}
setContentView(R.layout.activity_main)
- this.setTitle(R.string.app_name)
+ this.setTitle(R.string.app_name_v2)
// set window flags to ignore status bar
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// ignore status bar space
@@ -342,6 +350,14 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis
}
true
}
+ // parse intent. if action is SHOW_ONLINE, show online modules
+ val action = intent.action
+ if (action == "android.intent.action.SHOW_ONLINE") {
+ // select online modules
+ bottomNavigationView.selectedItemId = R.id.online_menu_item
+ } else {
+ bottomNavigationView.selectedItemId = R.id.installed_menu_item
+ }
// update the padding of blur_frame to match the new bottom nav height
val blurFrame = findViewById(R.id.blur_frame)
blurFrame.post {
diff --git a/app/src/main/kotlin/com/fox2code/mmm/SetupActivity.kt b/app/src/main/kotlin/com/fox2code/mmm/SetupActivity.kt
index a574319..8982420 100644
--- a/app/src/main/kotlin/com/fox2code/mmm/SetupActivity.kt
+++ b/app/src/main/kotlin/com/fox2code/mmm/SetupActivity.kt
@@ -39,6 +39,7 @@ import org.apache.commons.io.FileUtils
import timber.log.Timber
import java.io.File
import java.io.IOException
+import java.sql.Timestamp
import java.util.Objects
class SetupActivity : FoxActivity(), LanguageActivity {
@@ -62,6 +63,27 @@ class SetupActivity : FoxActivity(), LanguageActivity {
}
val binding = ActivitySetupBinding.inflate(layoutInflater)
setContentView(binding.root)
+ val ts = Timestamp(System.currentTimeMillis() - 30L * 24 * 60 * 60 * 1000)
+ val buildTime = Timestamp(BuildConfig.BUILD_TIME)
+ if (BuildConfig.DEBUG) {
+ if (ts.time > buildTime.time) {
+ val pm = packageManager
+ val intent = Intent(this, ExpiredActivity::class.java)
+ @Suppress("DEPRECATION") val resolveInfo = pm.queryIntentActivities(intent, 0)
+ if (resolveInfo.size > 0) {
+ startActivity(intent)
+ finish()
+ return
+ } else {
+ throw IllegalAccessError("This build has expired")
+ }
+ }
+ } else {
+ val ts2 = Timestamp(System.currentTimeMillis() - 365L * 24 * 60 * 60 * 1000)
+ if (ts2.time > buildTime.time) {
+ Toast.makeText(this, R.string.build_expired, Toast.LENGTH_LONG).show()
+ }
+ }
val view: View = binding.root
(Objects.requireNonNull(view.findViewById(R.id.setup_background_update_check)) as MaterialSwitch).isChecked =
BuildConfig.ENABLE_AUTO_UPDATER
diff --git a/app/src/main/kotlin/com/fox2code/mmm/UpdateActivity.kt b/app/src/main/kotlin/com/fox2code/mmm/UpdateActivity.kt
index c262411..970d026 100644
--- a/app/src/main/kotlin/com/fox2code/mmm/UpdateActivity.kt
+++ b/app/src/main/kotlin/com/fox2code/mmm/UpdateActivity.kt
@@ -12,6 +12,7 @@ import android.view.View
import android.webkit.CookieManager
import android.webkit.WebSettings
import android.webkit.WebView
+import android.widget.Toast
import androidx.core.content.FileProvider
import androidx.webkit.WebSettingsCompat
import androidx.webkit.WebViewFeature
@@ -28,6 +29,7 @@ import timber.log.Timber
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
+import java.sql.Timestamp
import java.util.Objects
class UpdateActivity : FoxActivity() {
@@ -38,6 +40,27 @@ class UpdateActivity : FoxActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_update)
+ val ts = Timestamp(System.currentTimeMillis() - 30L * 24 * 60 * 60 * 1000)
+ val buildTime = Timestamp(BuildConfig.BUILD_TIME)
+ if (BuildConfig.DEBUG) {
+ if (ts.time > buildTime.time) {
+ val pm = packageManager
+ val intent = Intent(this, ExpiredActivity::class.java)
+ @Suppress("DEPRECATION") val resolveInfo = pm.queryIntentActivities(intent, 0)
+ if (resolveInfo.size > 0) {
+ startActivity(intent)
+ finish()
+ return
+ } else {
+ throw IllegalAccessError("This build has expired")
+ }
+ }
+ } else {
+ val ts2 = Timestamp(System.currentTimeMillis() - 365L * 24 * 60 * 60 * 1000)
+ if (ts2.time > buildTime.time) {
+ Toast.makeText(this, R.string.build_expired, Toast.LENGTH_LONG).show()
+ }
+ }
chgWv = findViewById(R.id.changelog_webview)
if (MainApplication.isMatomoAllowed()) {
TrackHelper.track().screen(this).with(MainApplication.INSTANCE!!.tracker)
diff --git a/app/src/main/kotlin/com/fox2code/mmm/settings/SettingsActivity.kt b/app/src/main/kotlin/com/fox2code/mmm/settings/SettingsActivity.kt
index 93635e8..d4e5fc5 100644
--- a/app/src/main/kotlin/com/fox2code/mmm/settings/SettingsActivity.kt
+++ b/app/src/main/kotlin/com/fox2code/mmm/settings/SettingsActivity.kt
@@ -51,6 +51,7 @@ import com.fox2code.foxcompat.view.FoxViewCompat
import com.fox2code.mmm.AppUpdateManager.Companion.appUpdateManager
import com.fox2code.mmm.BuildConfig
import com.fox2code.mmm.Constants
+import com.fox2code.mmm.ExpiredActivity
import com.fox2code.mmm.MainActivity
import com.fox2code.mmm.MainApplication
import com.fox2code.mmm.MainApplication.Companion.INSTANCE
@@ -101,6 +102,7 @@ import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStreamReader
+import java.sql.Timestamp
import java.util.Objects
import java.util.Random
import kotlin.system.exitProcess
@@ -110,18 +112,26 @@ class SettingsActivity : FoxActivity(), LanguageActivity {
@SuppressLint("RestrictedApi")
private val onItemSelectedListener =
NavigationBarView.OnItemSelectedListener { item: MenuItem ->
- val itemId = item.itemId
- if (itemId == R.id.back) {
- TrackHelper.track().event("view_list", "main_modules")
- .with(INSTANCE!!.getTracker())
- startActivity(Intent(this, MainActivity::class.java))
- overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
- finish()
- return@OnItemSelectedListener true
- } else if (itemId == R.id.settings_menu_item) {
- return@OnItemSelectedListener true
+ when (item.itemId) {
+ R.id.installed_menu_item -> {
+ // go back to main modules by opening main activity with installed action
+ val intent = Intent(this, MainActivity::class.java)
+ intent.action = "android.intent.action.SHOW_INSTALLED"
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ startActivity(intent)
+ return@OnItemSelectedListener true
+ }
+ R.id.online_menu_item -> {
+ val intent = Intent(this, MainActivity::class.java)
+ intent.action = "android.intent.action.SHOW_ONLINE"
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ startActivity(intent)
+ return@OnItemSelectedListener true
+ }
+ else -> {
+ return@OnItemSelectedListener false
+ }
}
- false
}
@SuppressLint("RestrictedApi")
@@ -130,7 +140,28 @@ class SettingsActivity : FoxActivity(), LanguageActivity {
super.onCreate(savedInstanceState)
TrackHelper.track().screen(this).with(INSTANCE!!.getTracker())
setContentView(R.layout.settings_activity)
- setTitle(R.string.app_name)
+ setTitle(R.string.app_name_v2)
+ val ts = Timestamp(System.currentTimeMillis() - 30L * 24 * 60 * 60 * 1000)
+ val buildTime = Timestamp(BuildConfig.BUILD_TIME)
+ if (BuildConfig.DEBUG) {
+ if (ts.time > buildTime.time) {
+ val pm = packageManager
+ val intent = Intent(this, ExpiredActivity::class.java)
+ @Suppress("DEPRECATION") val resolveInfo = pm.queryIntentActivities(intent, 0)
+ if (resolveInfo.size > 0) {
+ startActivity(intent)
+ finish()
+ return
+ } else {
+ throw IllegalAccessError("This build has expired")
+ }
+ }
+ } else {
+ val ts2 = Timestamp(System.currentTimeMillis() - 365L * 24 * 60 * 60 * 1000)
+ if (ts2.time > buildTime.time) {
+ Toast.makeText(this, R.string.build_expired, Toast.LENGTH_LONG).show()
+ }
+ }
//hideActionBar();
val bottomNavigationView = findViewById(R.id.bottom_navigation)
bottomNavigationView.setOnItemSelectedListener(onItemSelectedListener)
@@ -1237,7 +1268,7 @@ class SettingsActivity : FoxActivity(), LanguageActivity {
}
override fun onBackPressed(compatActivity: FoxActivity): Boolean {
- compatActivity.setTitle(R.string.app_name)
+ compatActivity.setTitle(R.string.app_name_v2)
compatActivity.supportFragmentManager.beginTransaction().replace(R.id.settings, this)
.setTransition(
FragmentTransaction.TRANSIT_FRAGMENT_FADE
@@ -1884,7 +1915,7 @@ class SettingsActivity : FoxActivity(), LanguageActivity {
true
}
} else {
- findPreference(preferenceName + "_support")!!.isVisible =
+ findPreference("${preferenceName}_support")!!.isVisible =
false
}
if (repoData.getSubmitModule() != null) {
diff --git a/app/src/main/kotlin/com/fox2code/mmm/utils/RuntimeUtils.kt b/app/src/main/kotlin/com/fox2code/mmm/utils/RuntimeUtils.kt
index c848851..81aa5b8 100644
--- a/app/src/main/kotlin/com/fox2code/mmm/utils/RuntimeUtils.kt
+++ b/app/src/main/kotlin/com/fox2code/mmm/utils/RuntimeUtils.kt
@@ -280,39 +280,49 @@ class RuntimeUtils {
// reboot based on the reboot cmd from the enum we were passed
when (reboot) {
RebootMode.REBOOT -> {
- showRebootDialog(mainActivity) {
+ showRebootDialog(mainActivity, false) {
Shell.cmd("/system/bin/svc power reboot || /system/bin/reboot").submit()
}
}
+
RebootMode.RECOVERY -> {
// KEYCODE_POWER = 26, hide incorrect "Factory data reset" message
- showRebootDialog(mainActivity) {
+ showRebootDialog(mainActivity, false) {
Shell.cmd("/system/bin/input keyevent 26").submit()
}
}
+
RebootMode.BOOTLOADER -> {
- showRebootDialog(mainActivity) {
+ showRebootDialog(mainActivity, false) {
Shell.cmd("/system/bin/svc power reboot bootloader || /system/bin/reboot bootloader")
.submit()
}
}
+
RebootMode.EDL -> {
- showRebootDialog(mainActivity) {
+ showRebootDialog(mainActivity, true) {
Shell.cmd("/system/bin/reboot edl").submit()
}
}
}
}
- private fun showRebootDialog(mainActivity: FoxActivity, function: () -> Unit) {
+ private fun showRebootDialog(
+ mainActivity: FoxActivity,
+ showExtraWarning: Boolean,
+ function: () -> Unit
+ ) {
+ val message =
+ if (showExtraWarning) R.string.reboot_extra_warning else R.string.install_terminal_reboot_now_message
val dialog = MaterialAlertDialogBuilder(mainActivity)
- .setTitle(R.string.reboot)
- .setMessage(R.string.install_terminal_reboot_now_message)
- .setPositiveButton(R.string.reboot) { _, _ ->
- function()
- }
- .setNegativeButton(R.string.cancel) { _, _ -> }
- .create()
+ dialog.setTitle(R.string.reboot)
+ dialog.setCancelable(false)
+ dialog.setMessage(message)
+ dialog.setPositiveButton(R.string.reboot) { _, _ ->
+ function()
+ }
+ dialog.setNegativeButton(R.string.cancel) { _, _ -> }
+ dialog.create()
dialog.show()
}
}
diff --git a/app/src/main/res/layout/activity_expired.xml b/app/src/main/res/layout/activity_expired.xml
new file mode 100644
index 0000000..9b9c3b7
--- /dev/null
+++ b/app/src/main/res/layout/activity_expired.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 78df2b5..3332187 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -76,7 +76,6 @@
android:contentDescription="@string/reboot"
android:src="@drawable/baseline_restart_alt_24"
android:visibility="visible"
- app:fabSize="mini"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/search_bar"
app:layout_constraintStart_toStartOf="parent"
@@ -89,6 +88,7 @@
android:layout_height="56dp"
android:visibility="visible"
app:cardElevation="6dp"
+ android:alpha="1"
android:layout_marginBottom="2dp"
app:cardPreventCornerOverlap="true"
app:shapeAppearanceOverlay="@style/ShapeAppearance.Material3.Corner.Medium"
diff --git a/app/src/main/res/layout/settings_activity.xml b/app/src/main/res/layout/settings_activity.xml
index aede7e2..b0550c5 100644
--- a/app/src/main/res/layout/settings_activity.xml
+++ b/app/src/main/res/layout/settings_activity.xml
@@ -28,5 +28,5 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:menu="@menu/bottom_nav_menu_settings" />
+ app:menu="@menu/bottom_nav_menu" />
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 32c8bfd..99fbee6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -375,4 +375,12 @@
Reboot to EDL mode
Reboot is disabled in app settings
Error while communicating with API: %d
+ You are about to reboot to EDL mode, a special mode intended for OEMs to flash and fix low level problems. Unless you are sure you want to do this and have the necessary tools to get out of this mode or use it, we strongly encourage you to use the other reboot options.
+ ExpiredActivity
+ Home
+ Dashboard
+ Notifications
+ This build has expired!
+ The build you are using is expired and will no longer run. Please update to the latest stable build.
+ Download latest