From 7ba3b7d78eba7327191c40415f968520f9a4a516 Mon Sep 17 00:00:00 2001 From: Christophe Deschamps Date: Tue, 21 Oct 2025 11:52:25 +0200 Subject: [PATCH] API 35 update --- app/build.gradle | 4 +- .../java/org/linphone/LinphoneApplication.kt | 2 + .../linphone/activities/main/MainActivity.kt | 12 ++ .../compatibility/Api35Compatibility.kt | 91 ++++++++++ .../linphone/compatibility/Compatibility.kt | 10 ++ .../res/layout-land-v35/main_activity.xml | 74 ++++++++ .../layout-land-v35/main_activity_content.xml | 43 +++++ .../res/layout-land-v35/status_fragment.xml | 98 +++++++++++ .../res/layout-land-v35/tabs_fragment.xml | 152 +++++++++++++++++ .../main/res/layout-land/dialer_fragment.xml | 2 +- .../res/layout-v35/assistant_activity.xml | 32 ++++ app/src/main/res/layout-v35/main_activity.xml | 75 +++++++++ .../res/layout-v35/main_activity_content.xml | 49 ++++++ .../main/res/layout-v35/status_fragment.xml | 89 ++++++++++ app/src/main/res/layout-v35/tabs_fragment.xml | 159 ++++++++++++++++++ app/src/main/res/layout-v35/voip_activity.xml | 48 ++++++ .../res/layout-v35/voip_status_fragment.xml | 75 +++++++++ app/src/main/res/values-v35/dimen.xml | 92 ++++++++++ app/src/main/res/values/dimen.xml | 2 +- app/src/main/res/values/styles.xml | 2 +- 20 files changed, 1106 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/org/linphone/compatibility/Api35Compatibility.kt create mode 100644 app/src/main/res/layout-land-v35/main_activity.xml create mode 100644 app/src/main/res/layout-land-v35/main_activity_content.xml create mode 100644 app/src/main/res/layout-land-v35/status_fragment.xml create mode 100644 app/src/main/res/layout-land-v35/tabs_fragment.xml create mode 100644 app/src/main/res/layout-v35/assistant_activity.xml create mode 100644 app/src/main/res/layout-v35/main_activity.xml create mode 100644 app/src/main/res/layout-v35/main_activity_content.xml create mode 100644 app/src/main/res/layout-v35/status_fragment.xml create mode 100644 app/src/main/res/layout-v35/tabs_fragment.xml create mode 100644 app/src/main/res/layout-v35/voip_activity.xml create mode 100644 app/src/main/res/layout-v35/voip_status_fragment.xml create mode 100644 app/src/main/res/values-v35/dimen.xml diff --git a/app/build.gradle b/app/build.gradle index 45c600f4a..0f86eeb4b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -86,10 +86,10 @@ android { jvmTarget = '17' } - compileSdkVersion 34 + compileSdk 35 defaultConfig { minSdkVersion 23 - targetSdkVersion 34 + targetSdkVersion 35 versionCode appVersionCode versionName "${project.version}" applicationId packageName diff --git a/app/src/main/java/org/linphone/LinphoneApplication.kt b/app/src/main/java/org/linphone/LinphoneApplication.kt index 0fdc245e6..5a14b7e09 100644 --- a/app/src/main/java/org/linphone/LinphoneApplication.kt +++ b/app/src/main/java/org/linphone/LinphoneApplication.kt @@ -31,6 +31,7 @@ import coil.decode.SvgDecoder import coil.decode.VideoFrameDecoder import coil.disk.DiskCache import coil.memory.MemoryCache +import org.linphone.compatibility.Compatibility import org.linphone.core.* import org.linphone.core.tools.Log import org.linphone.mediastream.Version @@ -83,6 +84,7 @@ class LinphoneApplication : Application(), ImageLoaderFactory { Log.i("[Application] Core config & preferences created") wakeLock.release() + Compatibility.setupAppStartupListener(context) } fun ensureCoreExists( diff --git a/app/src/main/java/org/linphone/activities/main/MainActivity.kt b/app/src/main/java/org/linphone/activities/main/MainActivity.kt index 78798c4c0..049d2bd6b 100644 --- a/app/src/main/java/org/linphone/activities/main/MainActivity.kt +++ b/app/src/main/java/org/linphone/activities/main/MainActivity.kt @@ -32,8 +32,10 @@ import android.view.MotionEvent import android.view.View import android.view.inputmethod.InputMethodManager import androidx.annotation.StringRes +import androidx.appcompat.content.res.AppCompatResources import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.view.doOnAttach +import androidx.core.view.isVisible import androidx.databinding.DataBindingUtil import androidx.fragment.app.FragmentContainerView import androidx.lifecycle.MutableLiveData @@ -87,6 +89,7 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin private lateinit var tabsFragment: FragmentContainerView private lateinit var statusFragment: FragmentContainerView + private var api35filler: View? = null private var overlayX = 0f private var overlayY = 0f @@ -185,6 +188,7 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin tabsFragment = findViewById(R.id.tabs_fragment) statusFragment = findViewById(R.id.status_fragment) + api35filler = findViewById(R.id.api35filler) binding.root.doOnAttach { Log.i("[Main Activity] Report UI has been fully drawn (TTFD)") @@ -314,6 +318,14 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin private fun updateTabsFragmentVisibility() { tabsFragment.visibility = if (shouldTabsBeVisibleDependingOnDestination && shouldTabsBeVisibleDueToOrientationAndKeyboard) View.VISIBLE else View.GONE + api35filler?.background = if (tabsFragment.isVisible) { + AppCompatResources.getDrawable( + coreContext.context, + R.drawable.footer_button + ) + } else { + null + } } private fun handleIntentParams(intent: Intent) { diff --git a/app/src/main/java/org/linphone/compatibility/Api35Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Api35Compatibility.kt new file mode 100644 index 000000000..13a920869 --- /dev/null +++ b/app/src/main/java/org/linphone/compatibility/Api35Compatibility.kt @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2010-2024 Belledonne Communications SARL. + * + * This file is part of linphone-android + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.linphone.compatibility + +import android.app.ActivityManager +import android.app.ApplicationStartInfo +import android.content.Context +import android.os.Build +import androidx.annotation.RequiresApi +import java.util.concurrent.Executors +import org.linphone.core.tools.Log + +@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) +class Api35Compatibility { + companion object { + private const val TAG = "[API 35 Compatibility]" + + fun setupAppStartupListener(context: Context) { + try { + val activityManager = context.getSystemService(ActivityManager::class.java) + activityManager.addApplicationStartInfoCompletionListener( + Executors.newSingleThreadExecutor() + ) { info -> + Log.i("==== Current startup information dump ====") + Log.i("TYPE = ${startupTypeToString(info.startType)}") + Log.i("STATE = ${startupStateToString(info.startupState)}") + Log.i("REASON = ${startupReasonToString(info.reason)}") + Log.i("FORCE STOPPED = ${if (info.wasForceStopped()) "yes" else "no"}") + Log.i("PROCESS NAME = ${info.processName}") + Log.i("=========================================") + } + } catch (iae: IllegalArgumentException) { + Log.e("$TAG Can't add application start info completion listener: $iae") + } + } + + private fun startupTypeToString(type: Int): String { + return when (type) { + ApplicationStartInfo.START_TYPE_COLD -> "Cold" + ApplicationStartInfo.START_TYPE_HOT -> "Hot" + ApplicationStartInfo.START_TYPE_UNSET -> "Unset" + ApplicationStartInfo.START_TYPE_WARM -> "Warm" + else -> "Unexpected ($type)" + } + } + + private fun startupStateToString(state: Int): String { + return when (state) { + ApplicationStartInfo.STARTUP_STATE_STARTED -> "Started" + ApplicationStartInfo.STARTUP_STATE_ERROR -> "Error" + ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN -> "First frame drawn" + else -> "Unexpected ($state)" + } + } + + private fun startupReasonToString(reason: Int): String { + return when (reason) { + ApplicationStartInfo.START_REASON_ALARM -> "Alarm" + ApplicationStartInfo.START_REASON_BACKUP -> "Backup" + ApplicationStartInfo.START_REASON_BOOT_COMPLETE -> "Boot complete" + ApplicationStartInfo.START_REASON_BROADCAST -> "Broadcast" + ApplicationStartInfo.START_REASON_CONTENT_PROVIDER -> "Content provider" + ApplicationStartInfo.START_REASON_JOB -> "Job" + ApplicationStartInfo.START_REASON_LAUNCHER -> "Launcher" + ApplicationStartInfo.START_REASON_LAUNCHER_RECENTS -> "Launcher (recents)" + ApplicationStartInfo.START_REASON_OTHER -> "Other" + ApplicationStartInfo.START_REASON_PUSH -> "Push" + ApplicationStartInfo.START_REASON_SERVICE -> "Service" + ApplicationStartInfo.START_REASON_START_ACTIVITY -> "Start Activity" + else -> "Unexpected ($reason)" + } + } + } +} diff --git a/app/src/main/java/org/linphone/compatibility/Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Compatibility.kt index c0557bbcd..eb13fd36c 100644 --- a/app/src/main/java/org/linphone/compatibility/Compatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/Compatibility.kt @@ -19,6 +19,7 @@ */ package org.linphone.compatibility +import android.annotation.SuppressLint import android.app.Activity import android.app.Notification import android.app.PendingIntent @@ -48,8 +49,17 @@ import org.linphone.notifications.NotificationsManager import org.linphone.telecom.NativeCallWrapper @Suppress("DEPRECATION") +@SuppressLint("NewApi") class Compatibility { companion object { + const val BLUETOOTH_CONNECT = "android.permission.BLUETOOTH_CONNECT" + + fun setupAppStartupListener(context: Context) { + if (Version.sdkAboveOrEqual(Version.API35_ANDROID_15_VANILLA_ICE_CREAM)) { + Api35Compatibility.setupAppStartupListener(context) + } + } + fun hasPermission(context: Context, permission: String): Boolean { return Api23Compatibility.hasPermission(context, permission) } diff --git a/app/src/main/res/layout-land-v35/main_activity.xml b/app/src/main/res/layout-land-v35/main_activity.xml new file mode 100644 index 000000000..a8d1eae5d --- /dev/null +++ b/app/src/main/res/layout-land-v35/main_activity.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout-land-v35/main_activity_content.xml b/app/src/main/res/layout-land-v35/main_activity_content.xml new file mode 100644 index 000000000..38e54f784 --- /dev/null +++ b/app/src/main/res/layout-land-v35/main_activity_content.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land-v35/status_fragment.xml b/app/src/main/res/layout-land-v35/status_fragment.xml new file mode 100644 index 000000000..1a0ce111d --- /dev/null +++ b/app/src/main/res/layout-land-v35/status_fragment.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land-v35/tabs_fragment.xml b/app/src/main/res/layout-land-v35/tabs_fragment.xml new file mode 100644 index 000000000..72e54530a --- /dev/null +++ b/app/src/main/res/layout-land-v35/tabs_fragment.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land/dialer_fragment.xml b/app/src/main/res/layout-land/dialer_fragment.xml index a911071a9..a8af898fe 100644 --- a/app/src/main/res/layout-land/dialer_fragment.xml +++ b/app/src/main/res/layout-land/dialer_fragment.xml @@ -131,7 +131,7 @@ android:layout_height="match_parent" android:layout_below="@id/address_bar" android:layout_above="@id/controls" - android:padding="30dp" + android:padding="80dp" android:layout_centerHorizontal="true" android:contentDescription="@null" android:src="@drawable/dialer_background" /> diff --git a/app/src/main/res/layout-v35/assistant_activity.xml b/app/src/main/res/layout-v35/assistant_activity.xml new file mode 100644 index 000000000..12289a093 --- /dev/null +++ b/app/src/main/res/layout-v35/assistant_activity.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-v35/main_activity.xml b/app/src/main/res/layout-v35/main_activity.xml new file mode 100644 index 000000000..03c83c246 --- /dev/null +++ b/app/src/main/res/layout-v35/main_activity.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-v35/main_activity_content.xml b/app/src/main/res/layout-v35/main_activity_content.xml new file mode 100644 index 000000000..2f2b2fa2b --- /dev/null +++ b/app/src/main/res/layout-v35/main_activity_content.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout-v35/status_fragment.xml b/app/src/main/res/layout-v35/status_fragment.xml new file mode 100644 index 000000000..f1da6987a --- /dev/null +++ b/app/src/main/res/layout-v35/status_fragment.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-v35/tabs_fragment.xml b/app/src/main/res/layout-v35/tabs_fragment.xml new file mode 100644 index 000000000..851a0c22c --- /dev/null +++ b/app/src/main/res/layout-v35/tabs_fragment.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout-v35/voip_activity.xml b/app/src/main/res/layout-v35/voip_activity.xml new file mode 100644 index 000000000..531d0203e --- /dev/null +++ b/app/src/main/res/layout-v35/voip_activity.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-v35/voip_status_fragment.xml b/app/src/main/res/layout-v35/voip_status_fragment.xml new file mode 100644 index 000000000..92caf64b3 --- /dev/null +++ b/app/src/main/res/layout-v35/voip_status_fragment.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-v35/dimen.xml b/app/src/main/res/values-v35/dimen.xml new file mode 100644 index 000000000..d7e41a785 --- /dev/null +++ b/app/src/main/res/values-v35/dimen.xml @@ -0,0 +1,92 @@ + + + 10dp + 0dp + 45dp + 10dp + 3dp + 200dp + 100dp + 120dp + 50dp + 600dp + 200dp + 45dp + 60dp + 60dp + 60dp + 5dp + 5dp + 35dp + 21sp + 100dp + 60sp + 20dp + 3dp + 60dp + 250dp + 250dp + 50dp + 50dp + 6.7dp + 30dp + 40dp + 10dp + 10sp + 18sp + 8sp + 14sp + 1sp + 50dp + 55dp + 10dp + 60dp + 80dp + 50dp + 250dp + 60dp + 200dp + 210dp + 60dp + 50dp + 260dp + 350dp + 400dp + 390dp + 20dp + 5dp + 100dp + 10dp + 50dp + 30dp + 30dp + 30dp + 35dp + 137dp + 180dp + 80sp + 60dp + 80dp + 40dp + 1dp + 280dp + 5dp + 0dp + 50dp + 85dp + 30dp + 120dp + 5dp + 250dp + 5dp + 10dp + 35dp + 5dp + 12dp + 25dp + 1dp + 2dp + 290dp + 15sp + 45sp + \ No newline at end of file diff --git a/app/src/main/res/values/dimen.xml b/app/src/main/res/values/dimen.xml index 7c7b7fa34..e160b8303 100644 --- a/app/src/main/res/values/dimen.xml +++ b/app/src/main/res/values/dimen.xml @@ -14,7 +14,7 @@ 45dp 60dp 60dp - 40dp + 60dp 5dp 5dp 35dp diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 3de16f3fc..c244f9d64 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,5 +1,5 @@ - +