diff --git a/app/src/main/java/org/linphone/ui/assistant/fragment/PermissionsFragment.kt b/app/src/main/java/org/linphone/ui/assistant/fragment/PermissionsFragment.kt
new file mode 100644
index 000000000..f35a1f196
--- /dev/null
+++ b/app/src/main/java/org/linphone/ui/assistant/fragment/PermissionsFragment.kt
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2010-2023 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.ui.assistant.fragment
+
+import android.Manifest
+import android.content.pm.PackageManager
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.annotation.UiThread
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.findNavController
+import androidx.navigation.navGraphViewModels
+import org.linphone.R
+import org.linphone.core.tools.Log
+import org.linphone.databinding.AssistantPermissionsFragmentBinding
+import org.linphone.ui.assistant.viewmodel.PermissionsViewModel
+
+@UiThread
+class PermissionsFragment : Fragment() {
+ companion object {
+ private const val TAG = "[Permissions Fragment]"
+ }
+
+ private lateinit var binding: AssistantPermissionsFragmentBinding
+
+ private val viewModel: PermissionsViewModel by navGraphViewModels(
+ R.id.assistant_nav_graph
+ )
+
+ private val requestPermissionLauncher = registerForActivityResult(
+ ActivityResultContracts.RequestMultiplePermissions()
+ ) { permissions ->
+ permissions.entries.forEach() {
+ val permissionName = it.key
+ val isGranted = it.value
+
+ when (permissionName) {
+ "READ_CONTACTS" -> {
+ viewModel.readContacts.value = isGranted
+ }
+ "POST_NOTIFICATIONS" -> {
+ viewModel.postNotifications.value = isGranted
+ }
+ "RECORD_AUDIO" -> {
+ viewModel.recordAudio.value = isGranted
+ }
+ "CAMERA" -> {
+ viewModel.accessCamera.value = isGranted
+ }
+ else -> {}
+ }
+
+ if (isGranted) {
+ Log.i("Permission [$permissionName] is now granted")
+ } else {
+ Log.i("Permission [$permissionName] has been denied")
+ }
+ }
+
+ checkIfAllPermissionsHaveBeenGranted()
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ binding = AssistantPermissionsFragmentBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ binding.lifecycleOwner = viewLifecycleOwner
+ binding.viewModel = viewModel
+
+ binding.setBackClickListener {
+ findNavController().popBackStack()
+ }
+
+ binding.setGrantReadContactsClickListener {
+ Log.i("$TAG Requesting READ_CONTACTS permission")
+ requestPermissionLauncher.launch(arrayOf(Manifest.permission.READ_CONTACTS))
+ }
+
+ // TODO FIXME: use compat for older Androids
+ binding.setGrantPostNotificationsClickListener {
+ Log.i("$TAG Requesting POST_NOTIFICATIONS permission")
+ requestPermissionLauncher.launch(arrayOf(Manifest.permission.POST_NOTIFICATIONS))
+ }
+
+ binding.setGrantRecordAudioClickListener {
+ Log.i("$TAG Requesting RECORD_AUDIO permission")
+ requestPermissionLauncher.launch(arrayOf(Manifest.permission.RECORD_AUDIO))
+ }
+
+ binding.setGrantAccessCameraClickListener {
+ Log.i("$TAG Requesting CAMERA permission")
+ requestPermissionLauncher.launch(arrayOf(Manifest.permission.CAMERA))
+ }
+
+ binding.setSkipClickListener {
+ Log.i("$TAG User clicked skip...")
+ goToLoginFragment()
+ }
+
+ if (ContextCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.MANAGE_OWN_CALLS
+ ) != PackageManager.PERMISSION_GRANTED
+ ) {
+ requestPermissionLauncher.launch(arrayOf(Manifest.permission.MANAGE_OWN_CALLS))
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+
+ viewModel.readContacts.value = ContextCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.READ_CONTACTS
+ ) == PackageManager.PERMISSION_GRANTED
+
+ // TODO FIXME: use compat for older Androids
+ viewModel.postNotifications.value = ContextCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.POST_NOTIFICATIONS
+ ) == PackageManager.PERMISSION_GRANTED
+
+ viewModel.recordAudio.value = ContextCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.RECORD_AUDIO
+ ) == PackageManager.PERMISSION_GRANTED
+
+ viewModel.accessCamera.value = ContextCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.CAMERA
+ ) == PackageManager.PERMISSION_GRANTED
+
+ checkIfAllPermissionsHaveBeenGranted()
+ }
+
+ private fun goToLoginFragment() {
+ val action = PermissionsFragmentDirections.actionPermissionsFragmentToLoginFragment()
+ findNavController().navigate(action)
+ }
+
+ private fun checkIfAllPermissionsHaveBeenGranted() {
+ if (viewModel.readContacts.value == true && viewModel.postNotifications.value == true && viewModel.recordAudio.value == true && viewModel.accessCamera.value == true) {
+ Log.i("$TAG All permissions are granted, continuing to login fragment")
+ goToLoginFragment()
+ }
+ }
+}
diff --git a/app/src/main/java/org/linphone/ui/assistant/viewmodel/PermissionsViewModel.kt b/app/src/main/java/org/linphone/ui/assistant/viewmodel/PermissionsViewModel.kt
new file mode 100644
index 000000000..b2870f29d
--- /dev/null
+++ b/app/src/main/java/org/linphone/ui/assistant/viewmodel/PermissionsViewModel.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010-2023 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.ui.assistant.viewmodel
+
+import androidx.annotation.UiThread
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+
+class PermissionsViewModel @UiThread constructor() : ViewModel() {
+ val readContacts = MutableLiveData()
+
+ val postNotifications = MutableLiveData()
+
+ val recordAudio = MutableLiveData()
+
+ val accessCamera = MutableLiveData()
+}
diff --git a/app/src/main/java/org/linphone/ui/main/MainActivity.kt b/app/src/main/java/org/linphone/ui/main/MainActivity.kt
index b47cc6a11..85a8933a3 100644
--- a/app/src/main/java/org/linphone/ui/main/MainActivity.kt
+++ b/app/src/main/java/org/linphone/ui/main/MainActivity.kt
@@ -43,13 +43,6 @@ import org.linphone.utils.slideInToastFromTopForDuration
@UiThread
class MainActivity : AppCompatActivity() {
- companion object {
- private const val CONTACTS_PERMISSION_REQUEST = 0
- private const val CAMERA_PERMISSION_REQUEST = 1
- private const val RECORD_AUDIO_PERMISSION_REQUEST = 2
- private const val POST_NOTIFICATIONS_PERMISSION_REQUEST = 3
- private const val MANAGE_OWN_CALLS_PERMISSION_REQUEST = 4
- }
private lateinit var binding: MainActivityBinding
@@ -101,38 +94,6 @@ class MainActivity : AppCompatActivity() {
// TODO FIXME: uncomment
// startActivity(Intent(this, WelcomeActivity::class.java))
- if (checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
- requestPermissions(
- arrayOf(Manifest.permission.READ_CONTACTS),
- CONTACTS_PERMISSION_REQUEST
- )
- }
- if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
- requestPermissions(
- arrayOf(Manifest.permission.CAMERA),
- CAMERA_PERMISSION_REQUEST
- )
- }
- if (checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
- requestPermissions(
- arrayOf(Manifest.permission.RECORD_AUDIO),
- RECORD_AUDIO_PERMISSION_REQUEST
- )
- }
- if (checkSelfPermission(Manifest.permission.MANAGE_OWN_CALLS) != PackageManager.PERMISSION_GRANTED) {
- requestPermissions(
- arrayOf(Manifest.permission.MANAGE_OWN_CALLS),
- MANAGE_OWN_CALLS_PERMISSION_REQUEST
- )
- }
- // TODO FIXME : use compatibility
- if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
- requestPermissions(
- arrayOf(Manifest.permission.POST_NOTIFICATIONS),
- POST_NOTIFICATIONS_PERMISSION_REQUEST
- )
- }
-
coreContext.greenToastToShowEvent.observe(this) {
it.consume { pair ->
val message = pair.first
@@ -142,18 +103,6 @@ class MainActivity : AppCompatActivity() {
}
}
- override fun onRequestPermissionsResult(
- requestCode: Int,
- permissions: Array,
- grantResults: IntArray
- ) {
- if (requestCode == CONTACTS_PERMISSION_REQUEST && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- loadContacts()
- }
-
- super.onRequestPermissionsResult(requestCode, permissions, grantResults)
- }
-
@SuppressLint("RtlHardcoded")
fun toggleDrawerMenu() {
if (binding.drawerMenu.isDrawerOpen(Gravity.LEFT)) {
diff --git a/app/src/main/res/layout/assistant_permissions_fragment.xml b/app/src/main/res/layout/assistant_permissions_fragment.xml
new file mode 100644
index 000000000..57ccd0473
--- /dev/null
+++ b/app/src/main/res/layout/assistant_permissions_fragment.xml
@@ -0,0 +1,279 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/assistant_nav_graph.xml b/app/src/main/res/navigation/assistant_nav_graph.xml
index 46cb36fe3..50970ba87 100644
--- a/app/src/main/res/navigation/assistant_nav_graph.xml
+++ b/app/src/main/res/navigation/assistant_nav_graph.xml
@@ -3,7 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/assistant_nav_graph"
- app:startDestination="@id/loginFragment">
+ app:startDestination="@id/permissionsFragment">
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d48572d2a..a65505c44 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -151,6 +151,17 @@
Unexpected error occurred, please try again later
Wrong username or password
Failed to login: error code is %i
+ Grant permissions
+
+ To be able to work properly, we need you to grand the application the following permissions.\n\nIf you don\'t, some features won\'t be available, but you can grant them later.
+ Read contacts
+ This allows us to import your address-book in &appName;
+ Post notifications
+ To notify incoming calls & chat messages
+ Record audio
+ For audio calls, duh!
+ Access camera
+ For video calls & scan QR codes
Manage the profile
Connected