|
@@ -30,6 +30,7 @@ import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.content.IntentFilter;
|
|
|
|
+import android.content.pm.PackageManager;
|
|
import android.content.res.Configuration;
|
|
import android.content.res.Configuration;
|
|
import android.graphics.Color;
|
|
import android.graphics.Color;
|
|
import android.graphics.drawable.Icon;
|
|
import android.graphics.drawable.Icon;
|
|
@@ -94,7 +95,7 @@ import com.nextcloud.talk.utils.database.user.UserUtils;
|
|
import com.nextcloud.talk.utils.power.PowerManagerUtils;
|
|
import com.nextcloud.talk.utils.power.PowerManagerUtils;
|
|
import com.nextcloud.talk.utils.preferences.AppPreferences;
|
|
import com.nextcloud.talk.utils.preferences.AppPreferences;
|
|
import com.nextcloud.talk.utils.singletons.ApplicationWideCurrentRoomHolder;
|
|
import com.nextcloud.talk.utils.singletons.ApplicationWideCurrentRoomHolder;
|
|
-import com.nextcloud.talk.webrtc.MagicAudioManager;
|
|
|
|
|
|
+import com.nextcloud.talk.webrtc.WebRtcAudioManger;
|
|
import com.nextcloud.talk.webrtc.MagicWebRTCUtils;
|
|
import com.nextcloud.talk.webrtc.MagicWebRTCUtils;
|
|
import com.nextcloud.talk.webrtc.MagicWebSocketInstance;
|
|
import com.nextcloud.talk.webrtc.MagicWebSocketInstance;
|
|
import com.nextcloud.talk.webrtc.PeerConnectionWrapper;
|
|
import com.nextcloud.talk.webrtc.PeerConnectionWrapper;
|
|
@@ -139,12 +140,15 @@ import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
import javax.inject.Inject;
|
|
import javax.inject.Inject;
|
|
|
|
|
|
|
|
+import androidx.activity.result.ActivityResultLauncher;
|
|
|
|
+import androidx.activity.result.contract.ActivityResultContracts;
|
|
import androidx.annotation.DrawableRes;
|
|
import androidx.annotation.DrawableRes;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.RequiresApi;
|
|
import androidx.annotation.RequiresApi;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
import androidx.appcompat.content.res.AppCompatResources;
|
|
import androidx.appcompat.content.res.AppCompatResources;
|
|
|
|
+import androidx.core.content.ContextCompat;
|
|
import androidx.core.graphics.drawable.DrawableCompat;
|
|
import androidx.core.graphics.drawable.DrawableCompat;
|
|
import autodagger.AutoInjector;
|
|
import autodagger.AutoInjector;
|
|
import io.reactivex.Observable;
|
|
import io.reactivex.Observable;
|
|
@@ -158,6 +162,8 @@ import me.zhanghai.android.effortlesspermissions.OpenAppDetailsDialogFragment;
|
|
import okhttp3.Cache;
|
|
import okhttp3.Cache;
|
|
import pub.devrel.easypermissions.AfterPermissionGranted;
|
|
import pub.devrel.easypermissions.AfterPermissionGranted;
|
|
|
|
|
|
|
|
+import static android.app.PendingIntent.FLAG_MUTABLE;
|
|
|
|
+import static android.app.PendingIntent.FLAG_MUTABLE;
|
|
import static com.nextcloud.talk.webrtc.Globals.JOB_ID;
|
|
import static com.nextcloud.talk.webrtc.Globals.JOB_ID;
|
|
import static com.nextcloud.talk.webrtc.Globals.PARTICIPANTS_UPDATE;
|
|
import static com.nextcloud.talk.webrtc.Globals.PARTICIPANTS_UPDATE;
|
|
import static com.nextcloud.talk.webrtc.Globals.ROOM_TOKEN;
|
|
import static com.nextcloud.talk.webrtc.Globals.ROOM_TOKEN;
|
|
@@ -183,11 +189,11 @@ public class CallActivity extends CallBaseActivity {
|
|
|
|
|
|
public static final String TAG = "CallActivity";
|
|
public static final String TAG = "CallActivity";
|
|
|
|
|
|
- public MagicAudioManager audioManager;
|
|
|
|
|
|
+ public WebRtcAudioManger audioManager;
|
|
|
|
|
|
private static final String[] PERMISSIONS_CALL = {
|
|
private static final String[] PERMISSIONS_CALL = {
|
|
- android.Manifest.permission.CAMERA,
|
|
|
|
- android.Manifest.permission.RECORD_AUDIO,
|
|
|
|
|
|
+ Manifest.permission.CAMERA,
|
|
|
|
+ Manifest.permission.RECORD_AUDIO
|
|
};
|
|
};
|
|
|
|
|
|
private static final String[] PERMISSIONS_CAMERA = {
|
|
private static final String[] PERMISSIONS_CAMERA = {
|
|
@@ -269,6 +275,13 @@ public class CallActivity extends CallBaseActivity {
|
|
|
|
|
|
private AudioOutputDialog audioOutputDialog;
|
|
private AudioOutputDialog audioOutputDialog;
|
|
|
|
|
|
|
|
+ private final ActivityResultLauncher<String> requestBluetoothPermissionLauncher =
|
|
|
|
+ registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
|
|
|
|
+ if (isGranted) {
|
|
|
|
+ enableBluetoothManager();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
@SuppressLint("ClickableViewAccessibility")
|
|
@SuppressLint("ClickableViewAccessibility")
|
|
@Override
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
@@ -318,6 +331,9 @@ public class CallActivity extends CallBaseActivity {
|
|
.setRepeatCount(PulseAnimation.INFINITE)
|
|
.setRepeatCount(PulseAnimation.INFINITE)
|
|
.setRepeatMode(PulseAnimation.REVERSE);
|
|
.setRepeatMode(PulseAnimation.REVERSE);
|
|
|
|
|
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
|
|
+ requestBluetoothPermission();
|
|
|
|
+ }
|
|
basicInitialization();
|
|
basicInitialization();
|
|
participantDisplayItems = new HashMap<>();
|
|
participantDisplayItems = new HashMap<>();
|
|
initViews();
|
|
initViews();
|
|
@@ -327,6 +343,22 @@ public class CallActivity extends CallBaseActivity {
|
|
updateSelfVideoViewPosition();
|
|
updateSelfVideoViewPosition();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @SuppressLint("InlinedApi")
|
|
|
|
+ @RequiresApi(api = Build.VERSION_CODES.S)
|
|
|
|
+ private void requestBluetoothPermission() {
|
|
|
|
+ if (ContextCompat.checkSelfPermission(
|
|
|
|
+ getContext(), Manifest.permission.BLUETOOTH_CONNECT) ==
|
|
|
|
+ PackageManager.PERMISSION_DENIED) {
|
|
|
|
+ requestBluetoothPermissionLauncher.launch(Manifest.permission.BLUETOOTH_CONNECT);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void enableBluetoothManager() {
|
|
|
|
+ if (audioManager != null) {
|
|
|
|
+ audioManager.startBluetoothManager();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public void onStart() {
|
|
public void onStart() {
|
|
super.onStart();
|
|
super.onStart();
|
|
@@ -420,16 +452,16 @@ public class CallActivity extends CallBaseActivity {
|
|
|
|
|
|
// Create and audio manager that will take care of audio routing,
|
|
// Create and audio manager that will take care of audio routing,
|
|
// audio modes, audio device enumeration etc.
|
|
// audio modes, audio device enumeration etc.
|
|
- audioManager = MagicAudioManager.create(getApplicationContext(), isVoiceOnlyCall);
|
|
|
|
|
|
+ audioManager = WebRtcAudioManger.create(getApplicationContext(), isVoiceOnlyCall);
|
|
// Store existing audio settings and change audio mode to
|
|
// Store existing audio settings and change audio mode to
|
|
// MODE_IN_COMMUNICATION for best possible VoIP performance.
|
|
// MODE_IN_COMMUNICATION for best possible VoIP performance.
|
|
Log.d(TAG, "Starting the audio manager...");
|
|
Log.d(TAG, "Starting the audio manager...");
|
|
audioManager.start(this::onAudioManagerDevicesChanged);
|
|
audioManager.start(this::onAudioManagerDevicesChanged);
|
|
|
|
|
|
if (isVoiceOnlyCall) {
|
|
if (isVoiceOnlyCall) {
|
|
- setAudioOutputChannel(MagicAudioManager.AudioDevice.EARPIECE);
|
|
|
|
|
|
+ setAudioOutputChannel(WebRtcAudioManger.AudioDevice.EARPIECE);
|
|
} else {
|
|
} else {
|
|
- setAudioOutputChannel(MagicAudioManager.AudioDevice.SPEAKER_PHONE);
|
|
|
|
|
|
+ setAudioOutputChannel(WebRtcAudioManger.AudioDevice.SPEAKER_PHONE);
|
|
}
|
|
}
|
|
|
|
|
|
iceServers = new ArrayList<>();
|
|
iceServers = new ArrayList<>();
|
|
@@ -463,14 +495,14 @@ public class CallActivity extends CallBaseActivity {
|
|
microphoneInitialization();
|
|
microphoneInitialization();
|
|
}
|
|
}
|
|
|
|
|
|
- public void setAudioOutputChannel(MagicAudioManager.AudioDevice selectedAudioDevice) {
|
|
|
|
|
|
+ public void setAudioOutputChannel(WebRtcAudioManger.AudioDevice selectedAudioDevice) {
|
|
if (audioManager != null) {
|
|
if (audioManager != null) {
|
|
audioManager.selectAudioDevice(selectedAudioDevice);
|
|
audioManager.selectAudioDevice(selectedAudioDevice);
|
|
updateAudioOutputButton(audioManager.getCurrentAudioDevice());
|
|
updateAudioOutputButton(audioManager.getCurrentAudioDevice());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private void updateAudioOutputButton(MagicAudioManager.AudioDevice activeAudioDevice) {
|
|
|
|
|
|
+ private void updateAudioOutputButton(WebRtcAudioManger.AudioDevice activeAudioDevice) {
|
|
switch (activeAudioDevice) {
|
|
switch (activeAudioDevice) {
|
|
case BLUETOOTH:
|
|
case BLUETOOTH:
|
|
binding.audioOutputButton.getHierarchy().setPlaceholderImage(
|
|
binding.audioOutputButton.getHierarchy().setPlaceholderImage(
|
|
@@ -764,14 +796,14 @@ public class CallActivity extends CallBaseActivity {
|
|
}
|
|
}
|
|
|
|
|
|
private void onAudioManagerDevicesChanged(
|
|
private void onAudioManagerDevicesChanged(
|
|
- final MagicAudioManager.AudioDevice currentDevice,
|
|
|
|
- final Set<MagicAudioManager.AudioDevice> availableDevices) {
|
|
|
|
|
|
+ final WebRtcAudioManger.AudioDevice currentDevice,
|
|
|
|
+ final Set<WebRtcAudioManger.AudioDevice> availableDevices) {
|
|
Log.d(TAG, "onAudioManagerDevicesChanged: " + availableDevices + ", "
|
|
Log.d(TAG, "onAudioManagerDevicesChanged: " + availableDevices + ", "
|
|
+ "currentDevice: " + currentDevice);
|
|
+ "currentDevice: " + currentDevice);
|
|
|
|
|
|
- final boolean shouldDisableProximityLock = (currentDevice.equals(MagicAudioManager.AudioDevice.WIRED_HEADSET)
|
|
|
|
- || currentDevice.equals(MagicAudioManager.AudioDevice.SPEAKER_PHONE)
|
|
|
|
- || currentDevice.equals(MagicAudioManager.AudioDevice.BLUETOOTH));
|
|
|
|
|
|
+ final boolean shouldDisableProximityLock = (currentDevice.equals(WebRtcAudioManger.AudioDevice.WIRED_HEADSET)
|
|
|
|
+ || currentDevice.equals(WebRtcAudioManger.AudioDevice.SPEAKER_PHONE)
|
|
|
|
+ || currentDevice.equals(WebRtcAudioManger.AudioDevice.BLUETOOTH));
|
|
|
|
|
|
if (shouldDisableProximityLock) {
|
|
if (shouldDisableProximityLock) {
|
|
powerManagerUtils.updatePhoneState(PowerManagerUtils.PhoneState.WITHOUT_PROXIMITY_SENSOR_LOCK);
|
|
powerManagerUtils.updatePhoneState(PowerManagerUtils.PhoneState.WITHOUT_PROXIMITY_SENSOR_LOCK);
|
|
@@ -2579,12 +2611,19 @@ public class CallActivity extends CallBaseActivity {
|
|
final ArrayList<RemoteAction> actions = new ArrayList<>();
|
|
final ArrayList<RemoteAction> actions = new ArrayList<>();
|
|
|
|
|
|
final Icon icon = Icon.createWithResource(this, iconId);
|
|
final Icon icon = Icon.createWithResource(this, iconId);
|
|
|
|
+
|
|
|
|
+ int intentFlag;
|
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
|
|
+ intentFlag = FLAG_MUTABLE;
|
|
|
|
+ } else {
|
|
|
|
+ intentFlag = 0;
|
|
|
|
+ }
|
|
final PendingIntent intent =
|
|
final PendingIntent intent =
|
|
PendingIntent.getBroadcast(
|
|
PendingIntent.getBroadcast(
|
|
this,
|
|
this,
|
|
requestCode,
|
|
requestCode,
|
|
new Intent(MICROPHONE_PIP_INTENT_NAME).putExtra(MICROPHONE_PIP_INTENT_EXTRA_ACTION, requestCode),
|
|
new Intent(MICROPHONE_PIP_INTENT_NAME).putExtra(MICROPHONE_PIP_INTENT_EXTRA_ACTION, requestCode),
|
|
- 0);
|
|
|
|
|
|
+ intentFlag);
|
|
|
|
|
|
actions.add(new RemoteAction(icon, title, title, intent));
|
|
actions.add(new RemoteAction(icon, title, title, intent));
|
|
|
|
|