Skip to content

Commit

Permalink
Update to Android 15 (#21599)
Browse files Browse the repository at this point in the history
* Changed compileSdkVersion to 35

* Fixed bitmap.config nullability issues

* Fixed signing nullabiliy issues

* Marked onLowMemory as deprecated

* Temporarily commented out deprecated status/navbar code

* Changed targetSdkVersion to 35

* Added detectNonSdkApiUsage to StrictMode

* Re-enabled StrictMode

* Temporarily disabled StrictMode disk read/write

* Re-enabled StrictMode disk read/write

* Added Android 15+ version of setWindowStatusBarColor

* Added Android 15+ version of setWindowNavigationBarColor

* Minor formatting changes

* Replaced deprecated removeLast

* Don't remove quick link if empty

* Fixed test

* Fixed failing test due to unsupported removeLast

* Don't shadow resource references

* Removed unused deprecated window extension functions

* Revert to targetSdkVersion to prevent system bar overlap

* Use WindowExtensions.setWindowNavigationBarColor

* Perform version check when setting crop activity status bar color

* Suppress DEPRECATION in WidgetUtils.kt

* Added strict mode comment

* Rename .java to .kt

* Convert WordPressDebug to Kotlin

* Comment out enableStrictMode

* Set uCrop status bar color based on SDK version

* Use fun setWindowBarColor to set either status or navBar colors

* Added recommended changes to SignatureUtils

* Added detectUnsafeIntentLaunch() to strict mode
  • Loading branch information
nbradbury authored Jan 21, 2025
1 parent 94fd5f6 commit 9912e09
Show file tree
Hide file tree
Showing 16 changed files with 136 additions and 155 deletions.
47 changes: 0 additions & 47 deletions WordPress/src/debug/java/org/wordpress/android/WordPressDebug.java

This file was deleted.

57 changes: 57 additions & 0 deletions WordPress/src/debug/java/org/wordpress/android/WordPressDebug.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.wordpress.android

import android.os.Build
import android.os.StrictMode
import android.os.StrictMode.ThreadPolicy
import android.os.StrictMode.VmPolicy
import dagger.hilt.android.HiltAndroidApp
import org.wordpress.android.util.AppLog

@HiltAndroidApp
class WordPressDebug : WordPressApp() {
override fun onCreate() {
super.onCreate()
// enableStrictMode()
}

/**
* enables "strict mode" for testing - should NEVER be used in release builds
*/
private fun enableStrictMode() {
// return if the build is not a debug build
if (!BuildConfig.DEBUG) {
AppLog.e(AppLog.T.UTILS, "You should not call enableStrictMode() on a non debug build")
return
}

StrictMode.setThreadPolicy(
ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.penaltyFlashScreen()
.build()
)

StrictMode.setVmPolicy(
VmPolicy.Builder()
.detectActivityLeaks()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.detectLeakedRegistrationObjects()
.penaltyLog()
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
detectNonSdkApiUsage()
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
detectUnsafeIntentLaunch()
}
}
.build()
)

AppLog.w(AppLog.T.UTILS, "Strict mode enabled")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,7 @@ class AppInitializer @Inject constructor(
// Do nothing
}

@Deprecated("Deprecated in Java")
override fun onLowMemory() {
// Do nothing
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import org.wordpress.android.ui.WPWebViewActivity
import org.wordpress.android.ui.accounts.HelpActivity
import org.wordpress.android.util.ToastUtils
import org.wordpress.android.util.extensions.getSerializableCompat
import org.wordpress.android.util.extensions.setWindowNavigationBarColor
import org.wordpress.android.widgets.WPSnackbar
import java.util.UUID
import javax.inject.Inject
Expand Down Expand Up @@ -55,7 +56,7 @@ class SupportWebViewActivity : WPWebViewActivity(), SupportWebViewClient.Support

supportActionBar?.title = getString(R.string.help)
supportActionBar?.subtitle = ""
window.navigationBarColor = getColor(R.color.docsbot_chat_container)
window.setWindowNavigationBarColor(getColor(R.color.docsbot_chat_container))

// Prevent AppBar scrolling away
val toolbar = findViewById<Toolbar>(R.id.toolbar)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,9 @@ class SignupEpilogueFragment : LoginBaseFormFragment<SignupEpilogueListener?>(),
if (newAvatarUploaded && resource is BitmapDrawable) {
var bitmap = resource.bitmap
// create a copy since the original bitmap may by automatically recycled
bitmap = bitmap.copy(bitmap.config, true)
bitmap.config?.let { config ->
bitmap = bitmap.copy(config, true)
}
getBitmapCache().put((avatarUrl), bitmap)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,9 @@ class MeFragment : Fragment(R.layout.me_fragment), OnScrollToTopListener {
if (newAvatarSelected && resource is BitmapDrawable) {
var bitmap = resource.bitmap
// create a copy since the original bitmap may by automatically recycled
bitmap = bitmap.copy(bitmap.config, true)
bitmap.config?.let { config ->
bitmap = bitmap.copy(config, true)
}
WordPress.getBitmapCache().put(
avatarUrl,
bitmap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,9 @@ class WPMainNavigationView @JvmOverloads constructor(
if (resource is BitmapDrawable) {
var bitmap = resource.bitmap
// create a copy since the original bitmap may by automatically recycled
bitmap = bitmap.copy(bitmap.config, true)
bitmap.config?.let { config ->
bitmap = bitmap.copy(config, true)
}
WordPress.getBitmapCache().put(
avatarUrl,
bitmap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,11 @@ class MySiteFragment : Fragment(R.layout.my_site_fragment),
val context = activity ?: return
val options = UCrop.Options()
options.setShowCropGrid(false)
options.setStatusBarColor(context.getColorFromAttribute(android.R.attr.statusBarColor))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
options.setStatusBarColor(com.google.android.material.R.attr.colorSurface)
} else {
options.setStatusBarColor(com.google.android.material.R.attr.colorOnSurface)
}
options.setToolbarColor(context.getColorFromAttribute(R.attr.wpColorAppBar))
options.setToolbarWidgetColor(context.getColorFromAttribute(com.google.android.material.R.attr.colorOnSurface))
options.setAllowedGestures(UCropActivity.SCALE, UCropActivity.NONE, UCropActivity.NONE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,9 @@ class QuickLinksItemViewModelSlice @Inject constructor(
this@QuickLinksItemViewModelSlice::onMoreClick
)
)
quickLinkItems.removeLast()
if (quickLinkItems.isNotEmpty()) {
quickLinkItems.removeAt(quickLinkItems.lastIndex)
}
quickLinkItems.add(lastItem)
quickLinks.copy(quickLinkItems = quickLinkItems, showMoreFocusPoint = true)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ class MySiteListItemViewHolder(
if (resource is BitmapDrawable) {
var bitmap = resource.bitmap
// create a copy since the original bitmap may by automatically recycled
bitmap = bitmap.copy(bitmap.config, true)
bitmap.config?.let { config ->
bitmap = bitmap.copy(config, true)
}
WordPress.getBitmapCache().put(
avatarUrl,
bitmap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class WidgetUtils
)
}

@Suppress("LongParameterList")
@Suppress("LongParameterList", "DEPRECATION")
fun showList(
appWidgetManager: AppWidgetManager,
views: RemoteViews,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.widget.ListView;

import androidx.annotation.NonNull;
Expand All @@ -25,7 +24,6 @@
import org.wordpress.android.R;
import org.wordpress.android.util.AppLog.T;
import org.wordpress.android.util.extensions.DialogExtensionsKt;
import org.wordpress.android.util.extensions.WindowExtensionsKt;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -182,30 +180,4 @@ public static void enableReaderDeeplinks(Context context) {
pm.setComponentEnabledSetting(new ComponentName(context, READER_DEEPLINK_ACTIVITY_ALIAS),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
}

/**
* @deprecated Use {@link WindowExtensionsKt} instead.
*/
@Deprecated
public static void setLightStatusBar(Window window, boolean showInLightMode) {
WindowExtensionsKt.setLightStatusBar(window, showInLightMode);
}

/**
* @deprecated Use {@link WindowExtensionsKt} instead.
*/
@Deprecated
public static void setLightNavigationBar(Window window, boolean showInLightMode) {
WindowExtensionsKt.setLightNavigationBar(window, showInLightMode, true);
}

/**
* @deprecated Use {@link WindowExtensionsKt} instead.
*/
@Deprecated
public static void showFullScreen(View decorView) {
int flags = decorView.getSystemUiVisibility();
flags = flags | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(flags);
}
}
Original file line number Diff line number Diff line change
@@ -1,78 +1,59 @@
package org.wordpress.android.util.extensions

import android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
import android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE
import android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
import android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
import android.os.Build
import android.view.Window
import androidx.core.content.ContextCompat
import android.view.WindowInsets
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat
import org.wordpress.android.util.ColorUtils
import android.R as AndroidR
import com.google.android.material.R as MaterialR

@Suppress("DEPRECATION")
fun Window.setLightStatusBar(showInLightMode: Boolean) {
if (isLightTheme()) {
decorView.systemUiVisibility = decorView.systemUiVisibility.let {
if (showInLightMode) {
it or SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else {
it and SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
}
}
}
}

@Suppress("DEPRECATION")
fun Window.setLightNavigationBar(showInLightMode: Boolean, applyDefaultColors: Boolean = false) {
if (isLightTheme()) {
decorView.systemUiVisibility = decorView.systemUiVisibility.let {
if (showInLightMode) {
it or SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
} else {
it and SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
}
}
if (applyDefaultColors) {
navigationBarColor = if (showInLightMode) {
context.getColorFromAttribute(MaterialR.attr.colorSurface)
} else {
ContextCompat.getColor(context, AndroidR.color.black)
}
}
}
}

fun Window.setEdgeToEdgeContentDisplay(isEnabled: Boolean) {
val decorFitsSystemWindows = !isEnabled
WindowCompat.setDecorFitsSystemWindows(this, decorFitsSystemWindows)
}

@Suppress("DEPRECATION")
fun Window.showFullScreen() {
decorView.systemUiVisibility = decorView.systemUiVisibility.let {
it or SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or SYSTEM_UI_FLAG_LAYOUT_STABLE
}
}

fun Window.setWindowStatusBarColor(color: Int) {
val windowInsetsController = WindowInsetsControllerCompat(this, decorView)

statusBarColor = color
windowInsetsController.isAppearanceLightStatusBars = ColorUtils.isColorLight(statusBarColor)

// we need to set the light navigation appearance here because, for some reason, changing the status bar also
// changes the navigation bar appearance but this method is supposed to only change the status bar
windowInsetsController.isAppearanceLightNavigationBars = ColorUtils.isColorLight(navigationBarColor)
setWindowBarColor(color, InsetsType.STATUS_BAR)
}

fun Window.setWindowNavigationBarColor(color: Int) {
val windowInsetsController = WindowInsetsControllerCompat(this, decorView)
setWindowBarColor(color, InsetsType.NAVIGATION_BAR)
}

navigationBarColor = color
windowInsetsController.isAppearanceLightNavigationBars = ColorUtils.isColorLight(navigationBarColor)
/**
* Sets the status bar or navigation bar color
* TODO Setting both the status bar color and navigation bar color causes the insets to be set twice
*/
@Suppress("DEPRECATION")
private fun Window.setWindowBarColor(color: Int, insetsType: InsetsType) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
// Android 15+
decorView.setOnApplyWindowInsetsListener { view, insets ->
view.setBackgroundColor(color)
val barInsets = insets.getInsets(
when (insetsType) {
InsetsType.STATUS_BAR -> WindowInsets.Type.statusBars()
InsetsType.NAVIGATION_BAR -> WindowInsets.Type.navigationBars()
}
)
// Adjust padding to avoid overlap
view.setPadding(0, barInsets.top, 0, 0)
insets
}
} else {
when(insetsType) {
InsetsType.STATUS_BAR -> statusBarColor = color
InsetsType.NAVIGATION_BAR -> navigationBarColor = color
}
val windowInsetsController = WindowInsetsControllerCompat(this, decorView)
if (insetsType == InsetsType.STATUS_BAR) {
windowInsetsController.isAppearanceLightStatusBars = ColorUtils.isColorLight(statusBarColor)
}
windowInsetsController.isAppearanceLightNavigationBars = ColorUtils.isColorLight(navigationBarColor)
}
}

private fun Window.isLightTheme() = !context.resources.configuration.isDarkTheme()
private enum class InsetsType {
STATUS_BAR,
NAVIGATION_BAR
}
Loading

0 comments on commit 9912e09

Please sign in to comment.