@ -0,0 +1,10 @@ |
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="108dp" |
||||||
|
android:height="108dp" |
||||||
|
android:viewportWidth="108" |
||||||
|
android:viewportHeight="108"> |
||||||
|
<path |
||||||
|
android:fillColor="#F7F07E" |
||||||
|
android:fillType="evenOdd" |
||||||
|
android:pathData="m0,0h108v108h-108z" /> |
||||||
|
</vector> |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 260 KiB |
@ -1,6 +1,22 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<!-- |
||||||
|
~ Copyright (c) 2023 New Vector Ltd |
||||||
|
~ |
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
~ you may not use this file except in compliance with the License. |
||||||
|
~ You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> |
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
<background android:drawable="@mipmap/ic_launcher_background"/> |
<background android:drawable="@drawable/ic_launcher_background"/> |
||||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/> |
<foreground android:drawable="@mipmap/ic_launcher_foreground"/> |
||||||
<!-- Waiting for design monochrome android:drawable="@mipmap/ic_launcher_monochrome" /--> |
<monochrome android:drawable="@mipmap/ic_launcher_monochrome"/> |
||||||
</adaptive-icon> |
</adaptive-icon> |
||||||
|
@ -1,6 +1,22 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<!-- |
||||||
|
~ Copyright (c) 2023 New Vector Ltd |
||||||
|
~ |
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
~ you may not use this file except in compliance with the License. |
||||||
|
~ You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> |
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
<background android:drawable="@mipmap/ic_launcher_background"/> |
<background android:drawable="@drawable/ic_launcher_background"/> |
||||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/> |
<foreground android:drawable="@mipmap/ic_launcher_foreground"/> |
||||||
<!-- Waiting for design monochrome android:drawable="@mipmap/ic_launcher_monochrome" /--> |
<monochrome android:drawable="@mipmap/ic_launcher_monochrome"/> |
||||||
</adaptive-icon> |
</adaptive-icon> |
||||||
|
Before Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 946 B |
Before Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 8.0 KiB |
After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 22 KiB |
@ -0,0 +1,10 @@ |
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="108dp" |
||||||
|
android:height="108dp" |
||||||
|
android:viewportWidth="108" |
||||||
|
android:viewportHeight="108"> |
||||||
|
<path |
||||||
|
android:fillColor="#07007E" |
||||||
|
android:fillType="evenOdd" |
||||||
|
android:pathData="m0,0h108v108h-108z" /> |
||||||
|
</vector> |
@ -0,0 +1,2 @@ |
|||||||
|
<bitmap xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:src="@mipmap/ic_launcher_background" /> |
@ -0,0 +1,69 @@ |
|||||||
|
# Continuous integration strategy |
||||||
|
|
||||||
|
<!--- TOC --> |
||||||
|
|
||||||
|
* [Introduction](#introduction) |
||||||
|
* [CI tools](#ci-tools) |
||||||
|
* [Rules](#rules) |
||||||
|
* [What is the CI checking](#what-is-the-ci-checking) |
||||||
|
* [What is the CI reporting](#what-is-the-ci-reporting) |
||||||
|
* [Current choices](#current-choices) |
||||||
|
* [R8 task](#r8-task) |
||||||
|
* [Android test (connected test)](#android-test-connected-test) |
||||||
|
|
||||||
|
<!--- END --> |
||||||
|
|
||||||
|
## Introduction |
||||||
|
|
||||||
|
This document gives some information about how we take advantage of the continuous integration (CI). |
||||||
|
|
||||||
|
## CI tools |
||||||
|
|
||||||
|
We use GitHub Actions to configure and perform the CI. |
||||||
|
|
||||||
|
## Rules |
||||||
|
|
||||||
|
We want: |
||||||
|
|
||||||
|
1. The CI to detect as soon as possible any issue in the code |
||||||
|
2. The CI to be fast - it's run on all the Pull Requests, and developers do not like to wait too long |
||||||
|
3. The CI to be reliable - it should not fail randomly |
||||||
|
4. The CI to generate artifacts which can be used by the team and the community |
||||||
|
5. The CI to generate useful logs and reports, not too verbose, not too short |
||||||
|
6. The developer to be able to run the CI locally - to help with this we have [a script](../tools/check/check_code_quality.sh) the can be run locally and which does more checks that just building and deploying the app. |
||||||
|
7. The CI to be used as a common environment for the team: generate the screenshots image for the screenshot test, build the release build (unsigned) |
||||||
|
8. The CI to run repeated tasks, like building the nightly builds, integrating data from external tools (translations, etc.) |
||||||
|
9. The CI to upgrade our dependencies (Renovate) |
||||||
|
10. The CI to do some issue triaging |
||||||
|
|
||||||
|
## What is the CI checking |
||||||
|
|
||||||
|
The CI checks that: |
||||||
|
|
||||||
|
1. The code is compiling, without any warnings, for all the app build types and variants and for the minimal app |
||||||
|
2. The tests are passing |
||||||
|
3. The code quality is good (detekt, ktlint, lint) |
||||||
|
4. The code is running and smoke tests are passing (maestro) |
||||||
|
5. The PullRequest itself is good (with danger) |
||||||
|
6. Files that must be added with git-lfs are added with git-lfs |
||||||
|
|
||||||
|
## What is the CI reporting |
||||||
|
|
||||||
|
The CI reports: |
||||||
|
|
||||||
|
1. Code coverage reports |
||||||
|
2. Sonar reports |
||||||
|
|
||||||
|
## Current choices |
||||||
|
|
||||||
|
### R8 task |
||||||
|
|
||||||
|
The CI does not run R8 because it's too slow, and it breaks rule 2. |
||||||
|
|
||||||
|
The drawback is that the nightly build can fail, as well as the release build. |
||||||
|
|
||||||
|
Since the nightly build is failing, the team can detect the failure quite fast and react to it. |
||||||
|
|
||||||
|
### Android test (connected test) |
||||||
|
|
||||||
|
We limit the number of connected tests (tests under folder `androidTest`), because it often break rule 2 and 3. |
@ -0,0 +1,2 @@ |
|||||||
|
Main changes in this version: Element Call, design update, bugfixes |
||||||
|
Full changelog: https://github.com/vector-im/element-x-android/releases |
@ -1,10 +1,10 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> |
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> |
||||||
<string name="screen_analytics_prompt_data_usage">"Wir werden keine personenbezogenen Daten aufzeichnen oder auswerten"</string> |
<string name="screen_analytics_prompt_data_usage">"Wir zeichnen keine persönlichen Daten auf und erstellen keine Profile."</string> |
||||||
<string name="screen_analytics_prompt_help_us_improve">"Teile anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen."</string> |
<string name="screen_analytics_prompt_help_us_improve">"Teile anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen."</string> |
||||||
<string name="screen_analytics_prompt_read_terms">"Du kannst alle unsere Nutzerbedingungen %1$s lesen."</string> |
<string name="screen_analytics_prompt_read_terms">"Du kannst alle unsere Bedingungen lesen %1$s."</string> |
||||||
<string name="screen_analytics_prompt_read_terms_content_link">"hier"</string> |
<string name="screen_analytics_prompt_read_terms_content_link">"hier"</string> |
||||||
<string name="screen_analytics_prompt_settings">"Du kannst dies jederzeit deaktivieren"</string> |
<string name="screen_analytics_prompt_settings">"Du kannst diese Funktion jederzeit deaktivieren"</string> |
||||||
<string name="screen_analytics_prompt_third_party_sharing">"Wir geben deine Daten nicht an Dritte weiter"</string> |
<string name="screen_analytics_prompt_third_party_sharing">"Wir geben Ihre Daten nicht an Dritte weiter"</string> |
||||||
<string name="screen_analytics_prompt_title">"Hilf uns, %1$s zu verbessern"</string> |
<string name="screen_analytics_prompt_title">"Hilf uns %1$s zu verbessern"</string> |
||||||
</resources> |
</resources> |
||||||
|
@ -1,10 +1,10 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> |
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> |
||||||
<string name="screen_analytics_prompt_data_usage">"Nous n\'enregistrerons ni ne traiterons aucune donnée personnelle"</string> |
<string name="screen_analytics_prompt_data_usage">"Nous n’enregistrerons ni ne profilerons aucune donnée personnelle"</string> |
||||||
<string name="screen_analytics_prompt_help_us_improve">"Partagez des données d\'utilisation anonymes pour nous aider à identifier les problèmes."</string> |
<string name="screen_analytics_prompt_help_us_improve">"Partagez des données d’utilisation anonymes pour nous aider à identifier les problèmes."</string> |
||||||
<string name="screen_analytics_prompt_read_terms">"Consultez nos conditions d\'utilisation %1$s."</string> |
<string name="screen_analytics_prompt_read_terms">"Vous pouvez lire toutes nos conditions %1$s."</string> |
||||||
<string name="screen_analytics_prompt_read_terms_content_link">"ici"</string> |
<string name="screen_analytics_prompt_read_terms_content_link">"ici"</string> |
||||||
<string name="screen_analytics_prompt_settings">"Vous pouvez désactiver cette fonction à tout moment"</string> |
<string name="screen_analytics_prompt_settings">"Vous pouvez le désactiver à tout moment"</string> |
||||||
<string name="screen_analytics_prompt_third_party_sharing">"Nous ne partagerons pas vos données avec des tiers"</string> |
<string name="screen_analytics_prompt_third_party_sharing">"Nous ne partagerons pas vos données avec des tiers"</string> |
||||||
<string name="screen_analytics_prompt_title">"Aidez-nous à améliorer %1$s"</string> |
<string name="screen_analytics_prompt_title">"Aidez à améliorer %1$s"</string> |
||||||
</resources> |
</resources> |
||||||
|
@ -1,5 +1,10 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> |
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> |
||||||
|
<string name="screen_analytics_prompt_data_usage">"我們不會紀錄或剖繪您的個人資料"</string> |
||||||
|
<string name="screen_analytics_prompt_help_us_improve">"分享匿名的使用數據以協助我們釐清問題"</string> |
||||||
|
<string name="screen_analytics_prompt_read_terms">"您可以到 %1$s 閱讀我們的條款。"</string> |
||||||
|
<string name="screen_analytics_prompt_read_terms_content_link">"這裡"</string> |
||||||
<string name="screen_analytics_prompt_settings">"您可以在任何時候關閉它"</string> |
<string name="screen_analytics_prompt_settings">"您可以在任何時候關閉它"</string> |
||||||
<string name="screen_analytics_prompt_third_party_sharing">"我們不會和第三方分享您的資料"</string> |
<string name="screen_analytics_prompt_third_party_sharing">"我們不會和第三方分享您的資料"</string> |
||||||
|
<string name="screen_analytics_prompt_title">"讓 %1$s 變得更好"</string> |
||||||
</resources> |
</resources> |
||||||
|
@ -0,0 +1,37 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2023 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
plugins { |
||||||
|
id("io.element.android-compose-library") |
||||||
|
alias(libs.plugins.anvil) |
||||||
|
alias(libs.plugins.ksp) |
||||||
|
} |
||||||
|
|
||||||
|
android { |
||||||
|
namespace = "io.element.android.features.call" |
||||||
|
} |
||||||
|
|
||||||
|
dependencies { |
||||||
|
implementation(projects.libraries.architecture) |
||||||
|
implementation(projects.libraries.designsystem) |
||||||
|
implementation(projects.libraries.network) |
||||||
|
implementation(libs.androidx.webkit) |
||||||
|
ksp(libs.showkase.processor) |
||||||
|
|
||||||
|
testImplementation(libs.test.junit) |
||||||
|
testImplementation(libs.test.truth) |
||||||
|
testImplementation(libs.test.robolectric) |
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
<!-- |
||||||
|
~ Copyright (c) 2023 New Vector Ltd |
||||||
|
~ |
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
~ you may not use this file except in compliance with the License. |
||||||
|
~ You may obtain a copy of the License at |
||||||
|
~ |
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
~ |
||||||
|
~ Unless required by applicable law or agreed to in writing, software |
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
~ See the License for the specific language governing permissions and |
||||||
|
~ limitations under the License. |
||||||
|
--> |
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
|
|
||||||
|
<uses-feature android:name="android.hardware.camera" android:required="false" /> |
||||||
|
<uses-feature android:name="android.hardware.microphone" android:required="false" /> |
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.RECORD_AUDIO" /> |
||||||
|
<uses-permission android:name="android.permission.CAMERA" /> |
||||||
|
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> |
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" /> |
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> |
||||||
|
|
||||||
|
<application> |
||||||
|
<activity |
||||||
|
android:name=".ElementCallActivity" |
||||||
|
android:label="@string/element_call" |
||||||
|
android:exported="true" |
||||||
|
android:taskAffinity="io.element.android.features.call" |
||||||
|
android:configChanges="screenSize|screenLayout|orientation|keyboardHidden|keyboard|navigation|uiMode" |
||||||
|
android:launchMode="singleTask"> |
||||||
|
|
||||||
|
<intent-filter android:autoVerify="true"> |
||||||
|
<action android:name="android.intent.action.VIEW" /> |
||||||
|
<category android:name="android.intent.category.DEFAULT" /> |
||||||
|
<category android:name="android.intent.category.BROWSABLE" /> |
||||||
|
|
||||||
|
<data android:scheme="http" /> |
||||||
|
<data android:scheme="https" /> |
||||||
|
|
||||||
|
<data android:host="call.element.io" /> |
||||||
|
</intent-filter> |
||||||
|
<!-- Custom scheme to handle urls from other domains in the format: element://call?url=https%3A%2F%2Felement.io --> |
||||||
|
<intent-filter> |
||||||
|
<action android:name="android.intent.action.VIEW" /> |
||||||
|
<category android:name="android.intent.category.DEFAULT" /> |
||||||
|
<category android:name="android.intent.category.BROWSABLE" /> |
||||||
|
|
||||||
|
<data android:scheme="element" /> |
||||||
|
<data android:host="call" /> |
||||||
|
</intent-filter> |
||||||
|
|
||||||
|
</activity> |
||||||
|
<service android:name=".CallForegroundService" android:enabled="true" android:foregroundServiceType="mediaPlayback" /> |
||||||
|
</application> |
||||||
|
|
||||||
|
</manifest> |
@ -0,0 +1,89 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2023 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.call |
||||||
|
|
||||||
|
import android.app.Service |
||||||
|
import android.content.Context |
||||||
|
import android.content.Intent |
||||||
|
import android.os.Build |
||||||
|
import android.os.IBinder |
||||||
|
import androidx.core.app.NotificationChannelCompat |
||||||
|
import androidx.core.app.NotificationCompat |
||||||
|
import androidx.core.app.NotificationManagerCompat |
||||||
|
import androidx.core.app.PendingIntentCompat |
||||||
|
import androidx.core.graphics.drawable.IconCompat |
||||||
|
import io.element.android.libraries.designsystem.utils.CommonDrawables |
||||||
|
|
||||||
|
class CallForegroundService : Service() { |
||||||
|
|
||||||
|
companion object { |
||||||
|
fun start(context: Context) { |
||||||
|
val intent = Intent(context, CallForegroundService::class.java) |
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { |
||||||
|
context.startForegroundService(intent) |
||||||
|
} else { |
||||||
|
context.startService(intent) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fun stop(context: Context) { |
||||||
|
val intent = Intent(context, CallForegroundService::class.java) |
||||||
|
context.stopService(intent) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private lateinit var notificationManagerCompat: NotificationManagerCompat |
||||||
|
|
||||||
|
override fun onCreate() { |
||||||
|
super.onCreate() |
||||||
|
|
||||||
|
notificationManagerCompat = NotificationManagerCompat.from(this) |
||||||
|
|
||||||
|
val foregroundServiceChannel = NotificationChannelCompat.Builder( |
||||||
|
"call_foreground_service_channel", |
||||||
|
NotificationManagerCompat.IMPORTANCE_LOW, |
||||||
|
).setName( |
||||||
|
getString(R.string.call_foreground_service_channel_title_android).ifEmpty { "Ongoing call" } |
||||||
|
).build() |
||||||
|
notificationManagerCompat.createNotificationChannel(foregroundServiceChannel) |
||||||
|
|
||||||
|
val callActivityIntent = Intent(this, ElementCallActivity::class.java) |
||||||
|
val pendingIntent = PendingIntentCompat.getActivity(this, 0, callActivityIntent, 0, false) |
||||||
|
val notification = NotificationCompat.Builder(this, foregroundServiceChannel.id) |
||||||
|
.setSmallIcon(IconCompat.createWithResource(this, CommonDrawables.ic_notification_small)) |
||||||
|
.setContentTitle(getString(R.string.call_foreground_service_title_android)) |
||||||
|
.setContentText(getString(R.string.call_foreground_service_message_android)) |
||||||
|
.setContentIntent(pendingIntent) |
||||||
|
.build() |
||||||
|
startForeground(1, notification) |
||||||
|
} |
||||||
|
|
||||||
|
@Suppress("DEPRECATION") |
||||||
|
override fun onDestroy() { |
||||||
|
super.onDestroy() |
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { |
||||||
|
stopForeground(STOP_FOREGROUND_REMOVE) |
||||||
|
} else { |
||||||
|
stopForeground(true) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onBind(intent: Intent?): IBinder? { |
||||||
|
return null |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2023 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.call |
||||||
|
|
||||||
|
import android.net.Uri |
||||||
|
import java.net.URLDecoder |
||||||
|
|
||||||
|
object CallIntentDataParser { |
||||||
|
|
||||||
|
private val validHttpSchemes = sequenceOf("http", "https") |
||||||
|
|
||||||
|
fun parse(data: String?): String? { |
||||||
|
val parsedUrl = data?.let { Uri.parse(data) } ?: return null |
||||||
|
val scheme = parsedUrl.scheme |
||||||
|
return when { |
||||||
|
scheme in validHttpSchemes && parsedUrl.host == "call.element.io" -> data |
||||||
|
scheme == "element" && parsedUrl.host == "call" -> { |
||||||
|
// We use this custom scheme to load arbitrary URLs for other instances of Element Call, |
||||||
|
// so we can only verify it's an HTTP/HTTPs URL with a non-empty host |
||||||
|
parsedUrl.getQueryParameter("url") |
||||||
|
?.let { URLDecoder.decode(it, "utf-8") } |
||||||
|
?.takeIf { |
||||||
|
val internalUri = Uri.parse(it) |
||||||
|
internalUri.scheme in validHttpSchemes && !internalUri.host.isNullOrBlank() |
||||||
|
} |
||||||
|
} |
||||||
|
// This should never be possible, but we still need to take into account the possibility |
||||||
|
else -> null |
||||||
|
} |
||||||
|
} |
||||||
|
} |