Add Proximity sensing back to voice note.
This commit is contained in:
parent
ec706e95cc
commit
8a2d20403e
3 changed files with 129 additions and 14 deletions
|
@ -1,7 +1,6 @@
|
||||||
package org.thoughtcrime.securesms.components.voice;
|
package org.thoughtcrime.securesms.components.voice;
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -11,19 +10,14 @@ import android.os.Bundle;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.support.v4.media.MediaBrowserCompat;
|
import android.support.v4.media.MediaBrowserCompat;
|
||||||
import android.support.v4.media.MediaDescriptionCompat;
|
|
||||||
import android.support.v4.media.MediaMetadataCompat;
|
|
||||||
import android.support.v4.media.session.MediaControllerCompat;
|
import android.support.v4.media.session.MediaControllerCompat;
|
||||||
import android.support.v4.media.session.MediaSessionCompat;
|
import android.support.v4.media.session.MediaSessionCompat;
|
||||||
import android.support.v4.media.session.PlaybackStateCompat;
|
import android.support.v4.media.session.PlaybackStateCompat;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationCompat;
|
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.media.MediaBrowserServiceCompat;
|
import androidx.media.MediaBrowserServiceCompat;
|
||||||
import androidx.media.session.MediaButtonReceiver;
|
|
||||||
|
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.DefaultLoadControl;
|
import com.google.android.exoplayer2.DefaultLoadControl;
|
||||||
|
@ -38,18 +32,10 @@ import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
|
||||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
||||||
import com.google.android.exoplayer2.ui.PlayerNotificationManager;
|
import com.google.android.exoplayer2.ui.PlayerNotificationManager;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
|
||||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
|
||||||
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationActivity;
|
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Android Service responsible for playback of voice notes.
|
* Android Service responsible for playback of voice notes.
|
||||||
|
@ -74,6 +60,7 @@ public class VoiceNotePlaybackService extends MediaBrowserServiceCompat {
|
||||||
private VoiceNoteNotificationManager voiceNoteNotificationManager;
|
private VoiceNoteNotificationManager voiceNoteNotificationManager;
|
||||||
private VoiceNoteQueueDataAdapter queueDataAdapter;
|
private VoiceNoteQueueDataAdapter queueDataAdapter;
|
||||||
private VoiceNotePlaybackPreparer voiceNotePlaybackPreparer;
|
private VoiceNotePlaybackPreparer voiceNotePlaybackPreparer;
|
||||||
|
private VoiceNoteProximityManager voiceNoteProximityManager;
|
||||||
private boolean isForegroundService;
|
private boolean isForegroundService;
|
||||||
|
|
||||||
private final LoadControl loadControl = new DefaultLoadControl.Builder()
|
private final LoadControl loadControl = new DefaultLoadControl.Builder()
|
||||||
|
@ -102,6 +89,7 @@ public class VoiceNotePlaybackService extends MediaBrowserServiceCompat {
|
||||||
VoiceNoteMediaSourceFactory mediaSourceFactory = new VoiceNoteMediaSourceFactory(this);
|
VoiceNoteMediaSourceFactory mediaSourceFactory = new VoiceNoteMediaSourceFactory(this);
|
||||||
|
|
||||||
voiceNotePlaybackPreparer = new VoiceNotePlaybackPreparer(this, player, queueDataAdapter, mediaSourceFactory);
|
voiceNotePlaybackPreparer = new VoiceNotePlaybackPreparer(this, player, queueDataAdapter, mediaSourceFactory);
|
||||||
|
voiceNoteProximityManager = new VoiceNoteProximityManager(this, player);
|
||||||
|
|
||||||
mediaSession.setPlaybackState(stateBuilder.build());
|
mediaSession.setPlaybackState(stateBuilder.build());
|
||||||
|
|
||||||
|
@ -155,6 +143,7 @@ public class VoiceNotePlaybackService extends MediaBrowserServiceCompat {
|
||||||
switch (playbackState) {
|
switch (playbackState) {
|
||||||
case Player.STATE_BUFFERING:
|
case Player.STATE_BUFFERING:
|
||||||
case Player.STATE_READY:
|
case Player.STATE_READY:
|
||||||
|
voiceNoteProximityManager.onPlayerReady();
|
||||||
voiceNoteNotificationManager.showNotification(player);
|
voiceNoteNotificationManager.showNotification(player);
|
||||||
|
|
||||||
if (!playWhenReady) {
|
if (!playWhenReady) {
|
||||||
|
@ -165,6 +154,7 @@ public class VoiceNotePlaybackService extends MediaBrowserServiceCompat {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
voiceNoteProximityManager.onPlayerEnded();
|
||||||
becomingNoisyReceiver.unregister();
|
becomingNoisyReceiver.unregister();
|
||||||
voiceNoteNotificationManager.hideNotification();
|
voiceNoteNotificationManager.hideNotification();
|
||||||
}
|
}
|
||||||
|
@ -184,6 +174,7 @@ public class VoiceNotePlaybackService extends MediaBrowserServiceCompat {
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerError(ExoPlaybackException error) {
|
public void onPlayerError(ExoPlaybackException error) {
|
||||||
Log.w(TAG, "ExoPlayer error occurred:", error);
|
Log.w(TAG, "ExoPlayer error occurred:", error);
|
||||||
|
voiceNoteProximityManager.onPlayerError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
package org.thoughtcrime.securesms.components.voice;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.hardware.Sensor;
|
||||||
|
import android.hardware.SensorEvent;
|
||||||
|
import android.hardware.SensorEventListener;
|
||||||
|
import android.hardware.SensorManager;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.Player;
|
||||||
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
|
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||||
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
|
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
class VoiceNoteProximityManager implements SensorEventListener {
|
||||||
|
|
||||||
|
private static final String TAG = Log.tag(VoiceNoteProximityManager.class);
|
||||||
|
|
||||||
|
private static final float PROXIMITY_THRESHOLD = 5f;
|
||||||
|
|
||||||
|
private final SimpleExoPlayer player;
|
||||||
|
private final AudioManager audioManager;
|
||||||
|
private final SensorManager sensorManager;
|
||||||
|
private final Sensor proximitySensor;
|
||||||
|
private final PowerManager.WakeLock wakeLock;
|
||||||
|
|
||||||
|
private long startTime;
|
||||||
|
|
||||||
|
VoiceNoteProximityManager(@NonNull Context context, @NonNull SimpleExoPlayer player) {
|
||||||
|
this.player = player;
|
||||||
|
this.audioManager = ServiceUtil.getAudioManager(context);
|
||||||
|
this.sensorManager = ServiceUtil.getSensorManager(context);
|
||||||
|
this.proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
this.wakeLock = ServiceUtil.getPowerManager(context).newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
|
||||||
|
} else {
|
||||||
|
this.wakeLock = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPlayerReady() {
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
sensorManager.registerListener(this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPlayerEnded() {
|
||||||
|
sensorManager.unregisterListener(this);
|
||||||
|
|
||||||
|
if (wakeLock != null && wakeLock.isHeld() && Build.VERSION.SDK_INT >= 21) {
|
||||||
|
wakeLock.release(PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPlayerError() {
|
||||||
|
onPlayerEnded();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSensorChanged(SensorEvent event) {
|
||||||
|
if (event.sensor.getType() != Sensor.TYPE_PROXIMITY || player.getPlaybackState() != Player.STATE_READY) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int desiredStreamType;
|
||||||
|
if (event.values[0] < PROXIMITY_THRESHOLD && event.values[0] != proximitySensor.getMaximumRange()) {
|
||||||
|
desiredStreamType = AudioManager.STREAM_VOICE_CALL;
|
||||||
|
} else {
|
||||||
|
desiredStreamType = AudioManager.STREAM_MUSIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int currentStreamType = Util.getStreamTypeForAudioUsage(player.getAudioAttributes().usage);
|
||||||
|
|
||||||
|
if (desiredStreamType == AudioManager.STREAM_VOICE_CALL &&
|
||||||
|
desiredStreamType != currentStreamType &&
|
||||||
|
!audioManager.isWiredHeadsetOn())
|
||||||
|
{
|
||||||
|
if (wakeLock != null) {
|
||||||
|
wakeLock.acquire(TimeUnit.MINUTES.toMillis(30));
|
||||||
|
}
|
||||||
|
|
||||||
|
player.setPlayWhenReady(false);
|
||||||
|
player.setAudioAttributes(new AudioAttributes.Builder()
|
||||||
|
.setContentType(C.CONTENT_TYPE_SPEECH)
|
||||||
|
.setUsage(C.USAGE_VOICE_COMMUNICATION)
|
||||||
|
.build());
|
||||||
|
player.setPlayWhenReady(true);
|
||||||
|
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
} else if (desiredStreamType == AudioManager.STREAM_MUSIC &&
|
||||||
|
desiredStreamType != currentStreamType &&
|
||||||
|
System.currentTimeMillis() - startTime > 500)
|
||||||
|
{
|
||||||
|
if (wakeLock != null) {
|
||||||
|
wakeLock.release();
|
||||||
|
player.setPlayWhenReady(false);
|
||||||
|
player.setAudioAttributes(new AudioAttributes.Builder()
|
||||||
|
.setContentType(C.CONTENT_TYPE_MUSIC)
|
||||||
|
.setUsage(C.USAGE_MEDIA)
|
||||||
|
.build(),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import android.app.NotificationManager;
|
||||||
import android.app.job.JobScheduler;
|
import android.app.job.JobScheduler;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.hardware.SensorManager;
|
||||||
import android.hardware.display.DisplayManager;
|
import android.hardware.display.DisplayManager;
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
@ -49,6 +50,10 @@ public class ServiceUtil {
|
||||||
return (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
|
return (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static SensorManager getSensorManager(Context context) {
|
||||||
|
return (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
public static PowerManager getPowerManager(Context context) {
|
public static PowerManager getPowerManager(Context context) {
|
||||||
return (PowerManager)context.getSystemService(Context.POWER_SERVICE);
|
return (PowerManager)context.getSystemService(Context.POWER_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue