Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to Android 15 #21597

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.wordpress.android;

import android.os.Build;
import android.os.StrictMode;
import android.os.StrictMode.VmPolicy;

import org.wordpress.android.util.AppLog;
import org.wordpress.android.util.AppLog.T;
Expand All @@ -13,7 +15,7 @@ public class WordPressDebug extends WordPressApp {
public void onCreate() {
super.onCreate();

// enableStrictMode()
enableStrictMode();
}

/**
Expand All @@ -34,14 +36,16 @@ private void enableStrictMode() {
.penaltyFlashScreen()
.build());

StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder()
.detectActivityLeaks()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.detectLeakedRegistrationObjects() // <-- requires Jelly Bean
.penaltyLog()
.build());

.penaltyLog();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
builder.detectNonSdkApiUsage();
}
StrictMode.setVmPolicy(builder.build());
AppLog.w(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 @@ -55,7 +55,7 @@ class SupportWebViewActivity : WPWebViewActivity(), SupportWebViewClient.Support

supportActionBar?.title = getString(R.string.help)
supportActionBar?.subtitle = ""
window.navigationBarColor = getColor(R.color.docsbot_chat_container)
// TODO window.navigationBarColor = 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,7 @@ 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))
// TODO options.setStatusBarColor(context.getColorFromAttribute(android.R.attr.statusBarColor))
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 @@ -167,8 +167,8 @@ class WidgetUtils
listIntent.data = Uri.parse(
listIntent.toUri(Intent.URI_INTENT_SCHEME)
)
views.setRemoteAdapter(R.id.widget_content, listIntent)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_content)
// TODO views.setRemoteAdapter(R.id.widget_content, listIntent)
// TODO appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_content)
appWidgetManager.updateAppWidget(appWidgetId, views)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
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.os.Build
import android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
import android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
import android.view.Window
import android.view.WindowInsets
import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat
Expand Down Expand Up @@ -51,28 +51,45 @@ fun Window.setEdgeToEdgeContentDisplay(isEnabled: Boolean) {
}

@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)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
// Android 15+
decorView.setOnApplyWindowInsetsListener { view, insets ->
val statusBarInsets = insets.getInsets(WindowInsets.Type.statusBars())
view.setBackgroundColor(color)
// Adjust padding to avoid overlap
view.setPadding(0, statusBarInsets.top, 0, 0)
insets
}
} else {
// Android 14-
statusBarColor = color
val windowInsetsController = WindowInsetsControllerCompat(this, decorView)
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)
// 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)
}
}

@Suppress("DEPRECATION")
fun Window.setWindowNavigationBarColor(color: Int) {
val windowInsetsController = WindowInsetsControllerCompat(this, decorView)

navigationBarColor = color
windowInsetsController.isAppearanceLightNavigationBars = ColorUtils.isColorLight(navigationBarColor)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
// Android 15+
decorView.setOnApplyWindowInsetsListener { view, insets ->
view.setBackgroundColor(color)
// Adjust padding to avoid overlap
val navBarInsets = insets.getInsets(WindowInsets.Type.navigationBars())
view.setPadding(0, navBarInsets.top, 0, 0)
insets
}
} else {
// Android 14-
val windowInsetsController = WindowInsetsControllerCompat(this, decorView)
navigationBarColor = color
windowInsetsController.isAppearanceLightNavigationBars = ColorUtils.isColorLight(navigationBarColor)
}
}

private fun Window.isLightTheme() = !context.resources.configuration.isDarkTheme()
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ class SignatureUtils @Inject constructor(
PackageManager.GET_SIGNING_CERTIFICATES
)
).signingInfo
if (signingInfo.hasMultipleSigners()) {
if (signingInfo?.hasMultipleSigners() == true) {
throw SignatureNotFoundException()
}
val allSignaturesMatch = signingInfo.signingCertificateHistory.all {
val allSignaturesMatch = signingInfo?.signingCertificateHistory?.all {
toHexStringWithColons(messageDigest.digest(it.toByteArray())) == trustedSignatureHash
}
} ?: false
if (allSignaturesMatch) {
true
} else throw SignatureNotFoundException()
Expand All @@ -56,9 +56,9 @@ class SignatureUtils @Inject constructor(
try {
val signatures = contextProvider.getContext().packageManager
.getPackageInfo(trustedPackageId, PackageManager.GET_SIGNATURES).signatures
val allSignaturesMatch = signatures.all {
val allSignaturesMatch = signatures?.all {
toHexStringWithColons(messageDigest.digest(it.toByteArray())) == trustedSignatureHash
}
} ?: false
return if (allSignaturesMatch) {
true
} else throw SignatureNotFoundException()
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ plugins {

ext {
minSdkVersion = 26
compileSdkVersion = 34
targetSdkVersion = 34
compileSdkVersion = 35
targetSdkVersion = 35

secretProperties = loadSecrets(
logger,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ class CommentSqlUtilsTest {
val commentsInDb = generateCommentModels(60, ALL)
val remoteComments = generateCommentModels(30, ALL)

remoteComments.removeLast()
remoteComments.removeLast()
remoteComments.removeLast()
remoteComments.removeAt(remoteComments.lastIndex)
remoteComments.removeAt(remoteComments.lastIndex)
remoteComments.removeAt(remoteComments.lastIndex)

commentsInDb.forEach {
CommentSqlUtils.insertOrUpdateComment(it)
Expand Down Expand Up @@ -239,9 +239,9 @@ class CommentSqlUtilsTest {
val remoteComments = generateCommentModels(50, ALL)

// exclude first 3 comments
remoteComments.removeFirst()
remoteComments.removeFirst()
remoteComments.removeFirst()
remoteComments.removeAt(0)
remoteComments.removeAt(0)
remoteComments.removeAt(0)

commentsInDb.forEach {
CommentSqlUtils.insertOrUpdateComment(it)
Expand Down
Loading