From 635c8e69c71f2d358f40909207c3dd704878fa06 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 9 Jun 2022 14:02:03 +0200 Subject: [PATCH] Started changes for Android 13 --- .gitlab-ci-files/job-android.yml | 2 +- app/build.gradle | 8 +-- app/src/main/AndroidManifest.xml | 13 +++- .../EchoCancellerCalibrationViewModel.kt | 3 + .../viewmodels/RemoteProvisioningViewModel.kt | 1 + .../main/chat/adapters/ImdnAdapter.kt | 1 + .../main/chat/data/ChatMessageContentData.kt | 1 + .../chat/fragments/DetailChatRoomFragment.kt | 5 +- .../viewmodels/ChatMessageSendingViewModel.kt | 1 + .../main/dialer/fragments/DialerFragment.kt | 22 ++++--- .../main/recordings/data/RecordingData.kt | 1 + .../activities/voip/fragments/ChatFragment.kt | 5 +- .../compatibility/Api33Compatibility.kt | 42 +++++++++++++ .../linphone/compatibility/Compatibility.kt | 12 ++++ .../notifications/NotificationsManager.kt | 5 ++ .../telecom/TelecomConnectionService.kt | 1 + .../org/linphone/utils/PermissionHelper.kt | 4 ++ build.gradle | 2 +- docker-files/bc-dev-android-33 | 62 +++++++++++++++++++ gradle/wrapper/gradle-wrapper.properties | 2 +- 20 files changed, 170 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/org/linphone/compatibility/Api33Compatibility.kt create mode 100644 docker-files/bc-dev-android-33 diff --git a/.gitlab-ci-files/job-android.yml b/.gitlab-ci-files/job-android.yml index 98fae62c7..3bb32bbf5 100644 --- a/.gitlab-ci-files/job-android.yml +++ b/.gitlab-ci-files/job-android.yml @@ -2,7 +2,7 @@ job-android: stage: build tags: [ "docker-android" ] - image: gitlab.linphone.org:4567/bc/public/linphone-android/bc-dev-android:20210903_java11_android31 + image: gitlab.linphone.org:4567/bc/public/linphone-android/bc-dev-android:20220609_android_33 before_script: - if ! [ -z ${SCP_PRIVATE_KEY+x} ]; then eval $(ssh-agent -s); fi diff --git a/app/build.gradle b/app/build.gradle index 85e4627ec..d5b91e29d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -84,11 +84,11 @@ project.tasks['preBuild'].dependsOn 'getGitVersion' project.tasks['preBuild'].dependsOn 'linphoneSdkSource' android { - compileSdkVersion 31 - buildToolsVersion '31.0.0' + compileSdkVersion 33 + buildToolsVersion '33.0.0' defaultConfig { minSdkVersion 23 - targetSdkVersion 31 + targetSdkVersion 33 versionCode appVersionCode versionName "${project.version}" applicationId getPackageName() @@ -228,7 +228,7 @@ dependencies { implementation 'androidx.emoji:emoji-bundled:1.1.0' // https://github.com/material-components/material-components-android/blob/master/LICENSE Apache v2.0 - implementation 'com.google.android.material:material:1.6.0' + implementation 'com.google.android.material:material:1.6.1' // https://github.com/google/flexbox-layout/blob/main/LICENSE Apache v2.0 implementation 'com.google.android.flexbox:flexbox:3.0.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bc9f0a53b..1351e4792 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,9 @@ + + @@ -10,17 +12,22 @@ + + + - + - + + - + diff --git a/app/src/main/java/org/linphone/activities/assistant/viewmodels/EchoCancellerCalibrationViewModel.kt b/app/src/main/java/org/linphone/activities/assistant/viewmodels/EchoCancellerCalibrationViewModel.kt index fe2c9ddce..9b5c54df8 100644 --- a/app/src/main/java/org/linphone/activities/assistant/viewmodels/EchoCancellerCalibrationViewModel.kt +++ b/app/src/main/java/org/linphone/activities/assistant/viewmodels/EchoCancellerCalibrationViewModel.kt @@ -59,6 +59,9 @@ class EchoCancellerCalibrationViewModel : ViewModel() { EcCalibratorStatus.Failed -> { Log.w("[Echo Canceller Calibration] Failed") } + EcCalibratorStatus.InProgress -> { + Log.i("[Echo Canceller Calibration] In progress") + } } echoCalibrationTerminated.value = Event(true) } diff --git a/app/src/main/java/org/linphone/activities/assistant/viewmodels/RemoteProvisioningViewModel.kt b/app/src/main/java/org/linphone/activities/assistant/viewmodels/RemoteProvisioningViewModel.kt index 6a09416e3..b4ec77e13 100644 --- a/app/src/main/java/org/linphone/activities/assistant/viewmodels/RemoteProvisioningViewModel.kt +++ b/app/src/main/java/org/linphone/activities/assistant/viewmodels/RemoteProvisioningViewModel.kt @@ -47,6 +47,7 @@ class RemoteProvisioningViewModel : ViewModel() { ConfiguringState.Failed -> { fetchSuccessfulEvent.value = Event(false) } + else -> {} } } } diff --git a/app/src/main/java/org/linphone/activities/main/chat/adapters/ImdnAdapter.kt b/app/src/main/java/org/linphone/activities/main/chat/adapters/ImdnAdapter.kt index 63c44d25e..f05a833ef 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/adapters/ImdnAdapter.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/adapters/ImdnAdapter.kt @@ -100,6 +100,7 @@ class ImdnAdapter( binding.textColor = R.color.red_color binding.icon = R.drawable.chat_error } + else -> {} } binding.executePendingBindings() return binding.root diff --git a/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageContentData.kt b/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageContentData.kt index 4ad57b5a5..8a1d67403 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageContentData.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageContentData.kt @@ -412,6 +412,7 @@ class ChatMessageContentData( AudioDevice.Type.Headphones, AudioDevice.Type.Headset -> { headphonesCard = device.id } + else -> {} } } } diff --git a/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt b/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt index 0cc300f3d..6e23ce50c 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt @@ -19,6 +19,7 @@ */ package org.linphone.activities.main.chat.fragments +import android.Manifest import android.app.Activity import android.app.Dialog import android.content.Intent @@ -572,8 +573,8 @@ class DetailChatRoomFragment : MasterFragment { headphonesCard = device.id } + else -> {} } } } diff --git a/app/src/main/java/org/linphone/activities/main/dialer/fragments/DialerFragment.kt b/app/src/main/java/org/linphone/activities/main/dialer/fragments/DialerFragment.kt index aee2b87b6..beb57f1d4 100644 --- a/app/src/main/java/org/linphone/activities/main/dialer/fragments/DialerFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/dialer/fragments/DialerFragment.kt @@ -224,7 +224,7 @@ class DialerFragment : SecureFragment() { Log.i("[Dialer] READ_PHONE_STATE permission has been granted") coreContext.initPhoneStateListener() } - checkTelecomManagerPermissions() + checkPermissions() } else if (requestCode == 1) { var allGranted = true for (result in grantResults) { @@ -238,22 +238,26 @@ class DialerFragment : SecureFragment() { } else { Log.w("[Dialer] Telecom Manager permission have been denied (at least one of them)") } + } else if (requestCode == 2) { + if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + Log.i("[Dialer] POST_NOTIFICATIONS permission has been granted") + } + checkTelecomManagerPermissions() } super.onRequestPermissionsResult(requestCode, permissions, grantResults) } private fun checkPermissions() { - checkReadPhoneStatePermission() - if (Version.sdkAboveOrEqual(Version.API26_O_80) && PermissionHelper.get().hasReadPhoneStatePermission()) { - // Don't check the following the previous permission is being asked - checkTelecomManagerPermissions() - } - } - - private fun checkReadPhoneStatePermission() { if (!PermissionHelper.get().hasReadPhoneStatePermission()) { Log.i("[Dialer] Asking for READ_PHONE_STATE permission") requestPermissions(arrayOf(Manifest.permission.READ_PHONE_STATE), 0) + } else if (!PermissionHelper.get().hasPostNotificationsPermission()) { + // Don't check the following the previous permission is being asked + Log.i("[Dialer] Asking for POST_NOTIFICATIONS permission") + Compatibility.requestPostNotificationsPermission(this, 2) + } else if (Version.sdkAboveOrEqual(Version.API26_O_80)) { + // Don't check the following the previous permissions are being asked + checkTelecomManagerPermissions() } } diff --git a/app/src/main/java/org/linphone/activities/main/recordings/data/RecordingData.kt b/app/src/main/java/org/linphone/activities/main/recordings/data/RecordingData.kt index 1f6203580..8bf57253c 100644 --- a/app/src/main/java/org/linphone/activities/main/recordings/data/RecordingData.kt +++ b/app/src/main/java/org/linphone/activities/main/recordings/data/RecordingData.kt @@ -181,6 +181,7 @@ class RecordingData(val path: String, private val recordingListener: RecordingLi AudioDevice.Type.Headphones, AudioDevice.Type.Headset -> { headphonesCard = device.id } + else -> {} } } } diff --git a/app/src/main/java/org/linphone/activities/voip/fragments/ChatFragment.kt b/app/src/main/java/org/linphone/activities/voip/fragments/ChatFragment.kt index 0d953d058..9ed173928 100644 --- a/app/src/main/java/org/linphone/activities/voip/fragments/ChatFragment.kt +++ b/app/src/main/java/org/linphone/activities/voip/fragments/ChatFragment.kt @@ -19,6 +19,7 @@ */ package org.linphone.activities.voip.fragments +import android.Manifest import android.app.Activity import android.content.Intent import android.content.pm.PackageManager @@ -88,8 +89,8 @@ class ChatFragment : GenericFragment() { Log.i("[Chat] Asking for READ_EXTERNAL_STORAGE and CAMERA permissions") requestPermissions( arrayOf( - android.Manifest.permission.READ_EXTERNAL_STORAGE, - android.Manifest.permission.CAMERA + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.CAMERA ), 0 ) diff --git a/app/src/main/java/org/linphone/compatibility/Api33Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Api33Compatibility.kt new file mode 100644 index 000000000..5bbb6e9f0 --- /dev/null +++ b/app/src/main/java/org/linphone/compatibility/Api33Compatibility.kt @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010-2022 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.annotation.TargetApi +import android.content.Context +import androidx.fragment.app.Fragment + +@TargetApi(33) +class Api33Compatibility { + companion object { + fun requestPostNotificationsPermission(fragment: Fragment, code: Int) { + fragment.requestPermissions( + arrayOf( + "android.permission.POST_NOTIFICATIONS" + ), + code + ) + } + + fun hasPostNotificationsPermission(context: Context): Boolean { + return Compatibility.hasPermission(context, "android.permission.POST_NOTIFICATIONS") + } + } +} diff --git a/app/src/main/java/org/linphone/compatibility/Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Compatibility.kt index d948565ac..20458fa88 100644 --- a/app/src/main/java/org/linphone/compatibility/Compatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/Compatibility.kt @@ -95,6 +95,18 @@ class Compatibility { } } + fun requestPostNotificationsPermission(fragment: Fragment, code: Int) { + if (Version.sdkAboveOrEqual(Version.API33_ANDROID_13_TIRAMISU)) { + Api33Compatibility.requestPostNotificationsPermission(fragment, code) + } + } + + fun hasPostNotificationsPermission(context: Context): Boolean { + return if (Version.sdkAboveOrEqual(Version.API33_ANDROID_13_TIRAMISU)) { + Api33Compatibility.hasPostNotificationsPermission(context) + } else true + } + fun getDeviceName(context: Context): String { return when (Version.sdkAboveOrEqual(Version.API25_NOUGAT_71)) { true -> Api25Compatibility.getDeviceName(context) diff --git a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt index e84998b31..03ea2f9f2 100644 --- a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt +++ b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt @@ -281,6 +281,11 @@ class NotificationsManager(private val context: Context) { } private fun notify(id: Int, notification: Notification, tag: String? = null) { + if (!PermissionHelper.get().hasPostNotificationsPermission()) { + Log.w("[Notifications Manager] Can't notify [$id] with tag [$tag], POST_NOTIFICATIONS permission isn't granted!") + return + } + Log.i("[Notifications Manager] Notifying [$id] with tag [$tag]") notificationManager.notify(tag, id, notification) } diff --git a/app/src/main/java/org/linphone/telecom/TelecomConnectionService.kt b/app/src/main/java/org/linphone/telecom/TelecomConnectionService.kt index 1e646ebc4..01717e429 100644 --- a/app/src/main/java/org/linphone/telecom/TelecomConnectionService.kt +++ b/app/src/main/java/org/linphone/telecom/TelecomConnectionService.kt @@ -52,6 +52,7 @@ class TelecomConnectionService : ConnectionService() { Call.State.Error -> onCallError(call) Call.State.End, Call.State.Released -> onCallEnded(call) Call.State.Connected -> onCallConnected(call) + else -> {} } } diff --git a/app/src/main/java/org/linphone/utils/PermissionHelper.kt b/app/src/main/java/org/linphone/utils/PermissionHelper.kt index 3d3069dce..c52a3c31f 100644 --- a/app/src/main/java/org/linphone/utils/PermissionHelper.kt +++ b/app/src/main/java/org/linphone/utils/PermissionHelper.kt @@ -79,4 +79,8 @@ class PermissionHelper private constructor(private val context: Context) { fun hasBluetoothConnectPermission(): Boolean { return Compatibility.hasBluetoothConnectPermission(context) } + + fun hasPostNotificationsPermission(): Boolean { + return Compatibility.hasPostNotificationsPermission(context) + } } diff --git a/build.gradle b/build.gradle index 565eb3866..5f355f8c5 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:7.2.1' classpath 'com.google.gms:google-services:4.3.10' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.0" classpath "org.jlleitschuh.gradle:ktlint-gradle:10.1.0" classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.0' } diff --git a/docker-files/bc-dev-android-33 b/docker-files/bc-dev-android-33 new file mode 100644 index 000000000..2a15406b3 --- /dev/null +++ b/docker-files/bc-dev-android-33 @@ -0,0 +1,62 @@ +FROM debian:stretch + +MAINTAINER Sylvain BERFINI + +# Configure locale +RUN apt-get update && \ + apt-get install -y locales && \ + apt-get clean && \ + echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \ + locale-gen +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8' + +ENV SHELL=/bin/bash + +# Define environment +ENV ANDROID_SDK 25.2.5 +ENV ANDROID_HOME /opt/android-sdk-linux +ENV ANDROID_NDK_HOME /opt/android-sdk-linux/ndk + +# Backports required for JDK 11 +RUN echo "deb http://deb.debian.org/debian stretch-backports main" > /etc/apt/sources.list.d/backports.list + +# Install common general tools +RUN apt-get update && \ + apt-get install -y curl nano sudo unzip vim wget rsync ssh git openjdk-8-jdk-headless && \ + apt-get -t stretch-backports install -y openjdk-11-jdk-headless && \ + apt-get clean + +# Get the Android tools +RUN wget https://dl.google.com/android/repository/tools_r$ANDROID_SDK-linux.zip && \ + unzip tools_r$ANDROID_SDK-linux.zip -d $ANDROID_HOME && \ + rm -f tools_r$ANDROID_SDK-linux.zip + +# Get latest Android command line tools, otherwise won't work with JDK 11 +RUN mkdir -p $ANDROID_HOME/cmdline-tools/latest +RUN wget https://dl.google.com/android/repository/commandlinetools-linux-7583922_latest.zip && \ + unzip commandlinetools-linux-7583922_latest.zip && \ + cp -R ./cmdline-tools/* $ANDROID_HOME/cmdline-tools/latest/ && \ + rm -rf ./cmdline-tools && \ + rm -rf commandlinetools-linux-7583922_latest.zip + +# Update path to include all Android SDK tools +ENV PATH $ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools:ANDROID_NDK_HOME:$PATH + +# Test +RUN $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --list --verbose --sdk_root=$ANDROID_HOME + +# Get the Android SDK +RUN echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "platforms;android-33" "build-tools;33.0.0" "extras;android;m2repository" "extras;google;m2repository" "platform-tools" "tools" "ndk;21.3.6528147" --sdk_root=$ANDROID_HOME + +# Accept Android SDK licenses +RUN yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses --sdk_root=$ANDROID_HOME + +# Configure user bc +RUN useradd -ms /bin/bash bc && \ + echo 'bc:cotcot' | chpasswd && \ + echo 'bc ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +USER bc +WORKDIR /home/bc +ENV PS1='\[\e[34m\]\u@bc-dev-android>\[\e[0m\] ' +CMD bash diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 18f770b7f..7273d0f6b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Thu Feb 03 11:43:32 CET 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME