У меня есть мультимедийное приложение для подкастов, созданное с помощью форм xamarin, и я пытаюсь реализовать AudioFocus MediaManager, чтобы мое приложение могло хорошо работать с другими мультимедийными приложениями. Моя основная проблема заключается в возможности вызова RequestAudioFocus (), когда пользователь сначала нажимает кнопку воспроизведения, а затем заставить слушателя работать, если другое приложение начинает воспроизводить мультимедиа, когда мое приложение находится в фоновом режиме. Так что оба aud ios не играют одновременно.
Если я прикреплю этот код в MainActivity, то запрос будет работать нормально, но я также не хочу, чтобы этот запрос происходил, когда пользователь открывает приложение. Я хочу, чтобы это произошло, когда пользователь нажимает кнопку воспроизведения.
Некоторое время назад я создал уведомление, которое выскакивает уведомление, когда пользователь впервые загружает эпизод, в котором также есть кнопка воспроизведения / паузы, которая запускает действие для воспроизведения / приостановки эпизода. Если я вставлю этот код в это действие, то все будет работать очень хорошо, даже слушатель в отношении других приложений, создающих помехи. Но опять же, я не хочу запрашивать фокусировку звука только тогда, когда они нажимают на уведомление за пределами приложения, я хочу, чтобы оно запускалось, когда они также нажимали кнопку воспроизведения внутри приложения.
Итак, теперь я создал другое действие (отличное от уведомлений). Но я пока не совсем понимаю, как назвать это занятие. Если бы кто-то мог указать мне правильное направление, это было бы здорово. Я изучал документы и другие учебные пособия, но я мог использовать толчок в правильном направлении. Спасибо за ваше время.
Один из ресурсов, которые я использую, можно найти по адресу https://www.sitepoint.com/managing-multiple-sound-sources-in-android-with-audio-focus/
Каждый раз возвращается значение false. Не проходит инициализацию AudioManager.
public bool RequestAudioFocus()
{
AudioManager audioManager = (AudioManager)GetSystemService(AudioService);
AudioFocusRequest audioFocusRequest;
if (Build.VERSION.SdkInt > BuildVersionCodes.O)
{
audioFocusRequest = audioManager.RequestAudioFocus(new AudioFocusRequestClass.Builder(AudioFocus.Gain)
.SetAudioAttributes(new AudioAttributes.Builder().SetLegacyStreamType(Android.Media.Stream.Music).Build()).SetOnAudioFocusChangeListener(this)
.Build());
}
else
{
audioFocusRequest = audioManager.RequestAudioFocus(this, Android.Media.Stream.Music, AudioFocus.Gain);
}
if (audioFocusRequest == AudioFocusRequest.Granted)
{
return true;
}
return false;
}
public void Init(DabPlayer Player, bool IntegrateWithLockScreen)
{
dabplayer = Player;
var mSession = new MediaSessionCompat(Application.Context, "MusicService");
mSession.SetFlags(MediaSessionCompat.FlagHandlesMediaButtons | MediaSessionCompat.FlagHandlesTransportControls);
var controller = mSession.Controller;
var description = GlobalResources.playerPodcast;
if (IntegrateWithLockScreen)
{
/* SET UP LOCK SCREEN */
CreateNotificationChannel();
dabplayer.EpisodeDataChanged += (sender, e) =>
{
bool focus = RequestAudioFocus();
if (focus)
{
// Set up an intent so that tapping the notifications returns to this app:
Intent intent = new Intent(Application.Context, typeof(MainActivity));
Intent playPauseIntent = new Intent(Application.Context, typeof(SecondActivity));
//Intent audioFocusIntent = new Intent(Application.Context, typeof(AudioFocusActivity));
// Create a PendingIntent;
const int pendingIntentId = 0;
const int firstPendingIntentId = 1;
//const int audioFocusIntentId = 2;
//PendingIntent audioFocusPendingIntent =
// PendingIntent.GetActivity(Application.Context, audioFocusIntentId, audioFocusIntent, 0);
PendingIntent firstPendingIntent =
PendingIntent.GetActivity(Application.Context, firstPendingIntentId, intent, 0);
PendingIntent pendingIntent =
PendingIntent.GetActivity(Application.Context, pendingIntentId, playPauseIntent, 0);
// Build the notification:
var builder = new NotificationCompat.Builder(Application.Context, CHANNEL_ID)
.SetStyle(new Android.Support.V4.Media.App.NotificationCompat.MediaStyle()
.SetMediaSession(mSession.SessionToken)
.SetShowActionsInCompactView(0))
.SetVisibility(NotificationCompat.VisibilityPublic)
.SetContentIntent(firstPendingIntent) // Start up this activity when the user clicks the intent.
.SetDeleteIntent(MediaButtonReceiver.BuildMediaButtonPendingIntent(Application.Context, PlaybackState.ActionStop))
.SetSmallIcon(Resource.Drawable.app_icon) // This is the icon to display
.AddAction(Resource.Drawable.ic_media_play_pause, "Play", pendingIntent)
.SetContentText(GlobalResources.playerPodcast.EpisodeTitle)
.SetContentTitle(GlobalResources.playerPodcast.ChannelTitle);
// Finally, publish the notification:
var notificationManager = NotificationManagerCompat.From(Application.Context);
notificationManager.Notify(NOTIFICATION_ID, builder.Build());
//StartActivity(audioFocusIntent); causes trying to invoke virtual method on
//null object reference when code and code above is uncommented
}
};
dabplayer.EpisodeProgressChanged += (object sender, EventArgs e) =>
{
};
}
}
Это действие, которое первоначально должно было использоваться для области уведомлений
[Activity]
public class SecondActivity : Activity, AudioManager.IOnAudioFocusChangeListener
{
DabPlayer player = GlobalResources.playerPodcast;
EpisodeViewModel Episode;
public bool RequestAudioFocus()
{
AudioManager audioManager = (AudioManager)GetSystemService(AudioService);
AudioFocusRequest audioFocusRequest;
if (Build.VERSION.SdkInt > BuildVersionCodes.O)
{
audioFocusRequest = audioManager.RequestAudioFocus(new AudioFocusRequestClass.Builder(AudioFocus.Gain)
.SetAudioAttributes(new AudioAttributes.Builder().SetLegacyStreamType(Android.Media.Stream.Music).Build()).SetOnAudioFocusChangeListener(this)
.Build());
}
else
{
audioFocusRequest = audioManager.RequestAudioFocus(this, Android.Media.Stream.Music, AudioFocus.Gain);
}
if (audioFocusRequest == AudioFocusRequest.Granted)
{
return true;
}
return false;
}
public void OnAudioFocusChange([GeneratedEnum] AudioFocus focusChange)
{
switch (focusChange)
{
case AudioFocus.Gain:
player.Play();
//Gain when other Music Player app releases the audio service
break;
case AudioFocus.Loss:
//We have lost focus stop!
player.Stop();
break;
case AudioFocus.LossTransient:
//We have lost focus for a short time, but likely to resume so pause
player.Pause();
break;
case AudioFocus.LossTransientCanDuck:
//We have lost focus but should till play at a muted 10% volume
//player.SetVolume(.1);
break;
}
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
if (player.IsReady)
{
if (player.IsPlaying)
{
player.Pause();
}
else
{
if (RequestAudioFocus())
{
player.Play();
}
}
}
else
{
if (player.Load(Episode.Episode))
{
if (RequestAudioFocus())
{
player.Play();
}
}
else
{
//DisplayAlert("Episode Unavailable", "The episode you are attempting to play is currently unavailable. Please try again later.", "OK");
}
}
Finish();
}
}
Это новое действие, которое я построил и надеюсь использовать, когда пользователь взаимодействует с игрок, но я не уверен, как позвонить / реализовать его.
[Activity]
public class AudioFocusActivity : Activity, AudioManager.IOnAudioFocusChangeListener
{
DabPlayer player = GlobalResources.playerPodcast;
DroidDabNativePlayer droid = new DroidDabNativePlayer();
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
RequestAudioFocus();
}
public bool RequestAudioFocus()
{
AudioManager audioManager = (AudioManager)GetSystemService(AudioService);
AudioFocusRequest audioFocusRequest;
if (Build.VERSION.SdkInt > BuildVersionCodes.O)
{
audioFocusRequest = audioManager.RequestAudioFocus(new AudioFocusRequestClass.Builder(AudioFocus.Gain)
.SetAudioAttributes(new AudioAttributes.Builder().SetLegacyStreamType(Android.Media.Stream.Music).Build()).SetOnAudioFocusChangeListener(this)
.Build());
}
else
{
audioFocusRequest = audioManager.RequestAudioFocus(this, Android.Media.Stream.Music, AudioFocus.Gain);
}
if (audioFocusRequest == AudioFocusRequest.Granted)
{
return true;
}
return false;
}
public void OnAudioFocusChange([GeneratedEnum] AudioFocus focusChange)
{
switch (focusChange)
{
case AudioFocus.Gain:
player.Play();
//Gain when other Music Player app releases the audio service
break;
case AudioFocus.Loss:
//We have lost focus stop!
player.Stop();
break;
case AudioFocus.LossTransient:
//We have lost focus for a short time, but likely to resume so pause
player.Pause();
break;
case AudioFocus.LossTransientCanDuck:
//We have lost focus but should till play at a muted 10% volume
//player.SetVolume(.1);
break;
}
}
}
Это просто мой метод игры в моем классе androidplayer
/// Begin playback or resume if paused
public void Play()
{
if (player == null)
return;
if (IsPlaying)
{
//Go back to the beginning (don't start playing)... not sure what this is here for if if it ever gets hit.
Pause();
Seek(0);
}
else if (player.CurrentPosition >= player.Duration)
{
//Start over from the beginning if at the end of the file
player.Pause();
Seek(0);
}
else
{
//Play from where we're at
}
player.Start();
}