如何在ExoPlayer设置上一个和下一个控件的动作?



我正在制作一个音频播放器应用程序。我创建了一个音频播放器和播放通知服务。我面临的问题与播放器中的上一个/下一个按钮以及播放通知。

  1. 音频播放通知中的上一键/下一键只是重新开始播放,不改变歌曲/音频文件。
  2. 音频播放器中的上一/下一按钮(使用exoplayer)改变并播放下一个/上一个文件,但播放器artwork(音频文件的图像)不改变。此外,播放/暂停按钮保持暂停状态,当按下时,它播放不同的文件。下面是AudioActivity和AudioService的代码AudioActivity.java
package com.example.videoplayer.audio;
import static com.example.videoplayer.RecyclerViewClasses.MediaFilesActivity.FOLDER_NAME_KEY;
import static com.example.videoplayer.RecyclerViewClasses.MediaFilesActivity.MY_PREF;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.example.videoplayer.MediaFiles;
import com.example.videoplayer.MediaPlayer.PlaylistDialog;
import com.example.videoplayer.R;
import com.example.videoplayer.RecyclerViewClasses.MediaFilesAdapter;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.util.Util;
import java.util.ArrayList;
public class AudioActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = AudioActivity.class.getSimpleName();
private static final int NOTIFICATION_ID = 1;
private static final String CHANNEL_ID = "channel_id";
PlayerView playerView;
SimpleExoPlayer player;
//public static SimpleExoPlayer player;
RelativeLayout root;
ImageView audioBack, audioList, menu_more;
ImageView nextButton, previousButton;
TextView playlistTitle, title;
ArrayList<MediaFiles> mAudioFilesArrayList;
int position;
MediaFilesAdapter mediaFilesAdapter;
String audioTitle;
String listTitle;
private AudioService mService;
private boolean mBound = false;
private Intent serviceIntent;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
AudioService.LocalBinder binder = (AudioService.LocalBinder) iBinder;
mService = binder.getService();
mBound = true;
Log.i(TAG + " ###", "in onServiceConnected: calling initializePlayer()");
initializePlayer();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mBound = false;
}
};
void initializePlayer() {
if (mBound) {
Log.i(TAG + " ###", "initializePlayer() called");
player = mService.getplayerInstance();
//            playerView.setVisibility(View.VISIBLE);
//            player.setPlayWhenReady(true);
playerView.setPlayer(player);
//            player.play();
//            player.seekTo(position, C.TIME_UNSET);
playError();
}
}
@SuppressLint("UseCompatLoadingForDrawables")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
Log.i(TAG + " ###", "onCreate() called");
super.onCreate(savedInstanceState);
setFullScreen();
setContentView(R.layout.activity_audio_player);
try {
getSupportActionBar().hide();
} catch (NullPointerException e) {
Log.e(TAG + " ###", "in VideoPlayerActivity: " + e);
}
playerView = findViewById(R.id.exoplayer_view_audio);
Log.i(TAG + " ###", "default artwork set in onCreate()");

root = findViewById(R.id.root_layout_audio);
audioBack = findViewById(R.id.audio_back_audio);
audioList = findViewById(R.id.audio_list);
nextButton = findViewById(R.id.exo_next);
previousButton = findViewById(R.id.exo_prev);
playlistTitle = findViewById(R.id.playlistTitle);
title = findViewById(R.id.audiofile_title);
menu_more = findViewById(R.id.audio_more);
SharedPreferences preferences = this.getSharedPreferences(MY_PREF, Context.MODE_PRIVATE);
listTitle = preferences.getString(FOLDER_NAME_KEY, "DEFAULT_FOLDER_NAME");
position = getIntent().getIntExtra("position", 1);
audioTitle = getIntent().getStringExtra("media_title");
Bundle b = getIntent().getBundleExtra(this.getString(R.string.bundle));
mAudioFilesArrayList = b.getParcelableArrayList(this.getString(R.string.media_array_list));
Log.i(TAG + " ###", "position=" + position);
Log.i(TAG + " ###", "is mAudioFilesArrayList null " + (mAudioFilesArrayList == null));
if (mAudioFilesArrayList == null)
return;

audioList.setOnClickListener(this);
nextButton.setOnClickListener(this);
previousButton.setOnClickListener(this);
audioBack.setOnClickListener(this);
menu_more.setOnClickListener(this);

startServiceIntent();
}
void startServiceIntent() {
Log.i(TAG + " ###", "entered startServiceIntent");
serviceIntent = new Intent(this, AudioService.class);
Log.i(TAG + " ###", "position=" + position);
serviceIntent.putExtra("position", position);
Bundle bundle = new Bundle();
Log.i(TAG + " ###", "is mediaArrayList null " + (mAudioFilesArrayList == null));
bundle.putParcelableArrayList(this.getString(R.string.media_array_list), mAudioFilesArrayList);
serviceIntent.putExtra("bundle", bundle);
Util.startForegroundService(this, serviceIntent);
playerView.setControllerHideOnTouch(false);
playerView.setUseController(true);
playerView.setControllerShowTimeoutMs(0);
playerView.showController();
playerView.setControllerAutoShow(true);
setUI();

}
private void playError() {
Log.i(TAG + " ###", "entered the playError() method()");
//Player.EventListener is deprecated
player.addListener(new Player.Listener() {
@Override
public void onTracksInfoChanged(@NonNull TracksInfo tracksInfo) {
Player.Listener.super.onTracksInfoChanged(tracksInfo);
Toast.makeText(AudioActivity.this, "TrackInfoChanged", Toast.LENGTH_SHORT).show();
}
@Override
public void onPlayerError(@NonNull PlaybackException error) {
Toast.makeText(AudioActivity.this, "Audio Playing Error", Toast.LENGTH_SHORT).show();
}
});
player.setPlayWhenReady(true);
}
private void setFullScreen() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG + " ###", "entered onStart()");
getApplicationContext().bindService(serviceIntent, mServiceConnection, 0);
initializePlayer();
setUI();
}
void setUI() {
Log.i(TAG + " ###", "entered setUI()");
title.setText(audioTitle);
playlistTitle.setText(listTitle);
Log.i(TAG + " ###", "text set in setUI()");
//playerView.setDefaultArtwork(AppCompatResources.getDrawable(this,R.drawable.ic_sharp_music_note_24));
//playerView.setUseArtwork(true);

}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG + " ###", "onResume() called");
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onStop() {
Log.i(TAG + " ###", "onStop() called, unbinding service!");
getApplicationContext().unbindService(mServiceConnection);
mBound = false;
finish();
super.onStop();
}
@Override
public void onClick(View view) {
Log.i(TAG + " ###", "entered onClick() method");
switch (view.getId()) {
case R.id.exo_play:
player.play();
break;
case R.id.exo_pause:
player.pause();
break;
case R.id.exo_next:
try {
player.stop();
stopService(serviceIntent);
position++;
audioTitle = mAudioFilesArrayList.get(position).getTitle();
title.setText(audioTitle);
startServiceIntent();
initializePlayer();
player = mService.getplayerInstance();
//playerView.setPlayer(null);
playerView.setPlayer(player);

playError();
} catch (Exception e) {
Toast.makeText(this, "No next audio file", Toast.LENGTH_SHORT).show();
position--;
}
break;
case R.id.exo_prev:
Log.i(TAG + " ###", "previous button clicked!");
try {
player.stop();
Log.i(TAG+" ###","player stopped!");
stopService(serviceIntent);
position--;
audioTitle = mAudioFilesArrayList.get(position).getTitle();
title.setText(audioTitle);
startServiceIntent();
//initializePlayer();
player=mService.getplayerInstance();
//playerView.setPlayer(null);
playerView.setPlayer(player);

playError();

} catch (Exception e) {
Toast.makeText(this, "No previous Video", Toast.LENGTH_SHORT).show();
position++;
}
break;
case R.id.audio_back_audio:
if (player != null)
//player.release();
finish();
break;
case R.id.audio_list:
PlaylistDialog playlistDialog = new PlaylistDialog(mAudioFilesArrayList, mediaFilesAdapter);
playlistDialog.show(getSupportFragmentManager(), playlistDialog.getTag());
break;
case R.id.audio_more:
PopupMenu popupMenu = new PopupMenu(this, menu_more);
MenuInflater inflater = popupMenu.getMenuInflater();
inflater.inflate(R.menu.actions_video, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
int id = menuItem.getItemId();
switch (id) {
case R.id.share_file:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
String filepath = mAudioFilesArrayList.get(position).getPath();
Uri uri = Uri.parse(filepath);
shareIntent.setType("/");
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(shareIntent, "Share File using"));
break;
}
return false;
}
});
popupMenu.show();
break;
}
}
}

AudioSerivce.java

package com.example.videoplayer.audio;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
import com.example.videoplayer.MediaFiles;
import com.example.videoplayer.R;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.ui.PlayerNotificationManager;
import com.google.android.exoplayer2.upstream.DefaultDataSource;
import java.io.File;
import java.util.ArrayList;
public class AudioService extends Service {
private static final String TAG = AudioService.class.getSimpleName();
private final IBinder mBinder = new LocalBinder();
private SimpleExoPlayer player;
private int position;
PlaybackParameters parameters;
private ArrayList<MediaFiles> mAudioFilesArrayList;
private PlayerNotificationManager.Builder playerNotificationManagerBuilder;
private PlayerNotificationManager playerNotificationManager;
ConcatenatingMediaSource concatenatingMediaSource;
private static final int NOTIFICATION_ID = 1;
private static final String CHANNEL_ID = "channel_id";
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
Log.i(TAG+" ###","onDestroy() called");
releasePlayer();
super.onDestroy();
}
private void releasePlayer() {
if (player != null) {
Log.i(TAG+" ###","Player!=null and releasePlayer called");
playerNotificationManager.setPlayer(null);
player.release();
player = null;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public SimpleExoPlayer getplayerInstance() {
Log.i(TAG+" ###","getplayerInstance() called: "+(player==null));
if (player == null) {
startPlayer();
}
return player;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//        try {
Bundle b = intent.getBundleExtra(this.getString(R.string.bundle));
String name=this.getString( R.string.media_array_list);
mAudioFilesArrayList = b.getParcelableArrayList(this.getString( R.string.media_array_list));
//        }
//        catch(Exception e)
//        {
//            Log.e(AudioService.class.getSimpleName()+" ###",e.toString());
//            stopSelf();
//        }
position = intent.getIntExtra("position", 1);
Log.i(TAG+"###"," in onStartCommand()");
Log.i(TAG+" ###","is mediaArrayList null"+(mAudioFilesArrayList==null));
Log.i(TAG+" ###","position="+position);
if (player == null) {
Log.i(TAG+" ###","Player is null, in onStartCommand calling startPlayer()");
Log.i(TAG+" ###","is mediaArrayList null"+(mAudioFilesArrayList==null));
Log.i(TAG+" ###","position="+position);
startPlayer();
}
return START_STICKY;
}
private void startPlayer() {
Log.i(TAG+" ###","entered startPlayer()");
Log.i(TAG+" ###","is mediaArrayList null"+(mAudioFilesArrayList==null));
Log.i(TAG+" ###","position="+position);
final Context context = this;
createNotificationChannel();
playerNotificationManagerBuilder = new PlayerNotificationManager.Builder(context, NOTIFICATION_ID, CHANNEL_ID)
.setRewindActionIconResourceId(R.drawable.ic_rewind)
.setNextActionIconResourceId(R.drawable.ic_next)
.setPreviousActionIconResourceId(R.drawable.ic_previous)
.setSmallIconResourceId(R.drawable.ic_sharp_music_note_24);
playerNotificationManagerBuilder.setPlayActionIconResourceId(R.drawable.ic_play);
playerNotificationManagerBuilder.setPauseActionIconResourceId(R.drawable.ic_pause);
playerNotificationManagerBuilder.setFastForwardActionIconResourceId(R.drawable.ic_fast_forward);
playerNotificationManagerBuilder.setMediaDescriptionAdapter(new PlayerNotificationManager.MediaDescriptionAdapter() {
@Override
public CharSequence getCurrentContentTitle(Player player) {
return mAudioFilesArrayList.get(position).getTitle();
}
@Nullable
@Override
public PendingIntent createCurrentContentIntent(Player player) {
Intent intent = new Intent(context, AudioActivity.class);
intent.putExtra("position", position);
Bundle bundle = new Bundle();
bundle.putParcelableArrayList(context.getString( R.string.media_array_list), mAudioFilesArrayList);
intent.putExtra("bundle",bundle);
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_IMMUTABLE);
}
@Nullable
@Override
public CharSequence getCurrentContentText(Player player) {
return "Summary";
}
@Nullable
@Override
public Bitmap getCurrentLargeIcon(Player player, PlayerNotificationManager.BitmapCallback callback) {
int window=player.getCurrentMediaItemIndex();
Log.i(TAG+"###","in getCurrentLargeIcon: window="+window);
return null;
//                return getCurrentLargeIcon(player,callback);
}
});
playerNotificationManagerBuilder.setNotificationListener(new PlayerNotificationManager.NotificationListener() {
@Override
public void onNotificationCancelled(int notificationId, boolean dismissedByUser) {
Log.i(TAG+" ###","onNotificationCancelled called!");
stopSelf();
}
@Override
public void onNotificationPosted(int notificationId, Notification notification, boolean ongoing) {
startForeground(notificationId, notification);
Log.i(TAG+" ###","startForeground() in onNotificationPosted!");
}
});
playerNotificationManager=playerNotificationManagerBuilder.build();
Log.i(TAG+" ###","startPlayer() called");
String path = mAudioFilesArrayList.get(position).getPath();
Uri uri = Uri.parse(path);
//        PlayerView.Builder builder = new ExoPlayer.Builder(this);
//        builder.setSeekForwardIncrementMs(5000);
//        builder.setSeekBackIncrementMs(5000);
//        player = builder.build();
SimpleExoPlayer.Builder builder = new SimpleExoPlayer.Builder(this);
builder.setSeekForwardIncrementMs(10000);
builder.setSeekBackIncrementMs(10000);
player = builder.build();

DefaultDataSource.Factory dataSourceFactory = new DefaultDataSource.Factory(this);
concatenatingMediaSource = new ConcatenatingMediaSource();
for (int i = 0; i < mAudioFilesArrayList.size(); i++) {
new File(String.valueOf(mAudioFilesArrayList.get(i)));
MediaSource mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(Uri.parse(String.valueOf(uri))));
concatenatingMediaSource.addMediaSource(mediaSource);
}
player.setMediaSource(concatenatingMediaSource);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(C.USAGE_MEDIA)
.setContentType(C.CONTENT_TYPE_MUSIC)
.build();
player.setAudioAttributes(audioAttributes, true);
player.setPlaybackParameters(parameters);
player.prepare();
player.play();
player.seekTo(position,C.TIME_UNSET);
//player.setPlayWhenReady(true);
playerNotificationManager.setPlayer(player);
playerNotificationManager.setUseNextAction(true);
playerNotificationManager.setSmallIcon(R.drawable.ic_sharp_music_note_24);
playerNotificationManager.setColorized(true);
playerNotificationManager.setUseChronometer(true);
playerNotificationManager.setColor(R.color.teal_200);
playerNotificationManager.setUseChronometer(true);
playerNotificationManager.setUseRewindAction(true);
playerNotificationManager.setUseFastForwardAction(true);
playerNotificationManager.setUsePlayPauseActions(true);
Log.i(TAG+" ###","returning from startPlayer()");
}
private void createNotificationChannel() {
Log.i(TAG+" ###","createNotificationChannel()");
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
public class LocalBinder extends Binder {
public AudioService getService() {
return AudioService.this;
}
}
}

请帮助我找到问题并解决它。

在我看来,使用MediaSessionCompat对于音频应用程序是必不可少的。一个非常好的说明可以在这里找到。我希望这对你有帮助。

GGK

最新更新