gpt4 book ai didi

Java Android 媒体播放器(通知)

转载 作者:行者123 更新时间:2023-12-01 14:20:36 27 4
gpt4 key购买 nike

所以我有以下代码,它工作正常,但是我想在用户通知区域中显示媒体控件,以便他们可以在应用程序处于后台时随意播放和停止音乐。
我想知道这是怎么做到的?
代码:

package com.radiomedia.a1liferadio;

import androidx.appcompat.app.AppCompatActivity;

import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

private ImageView imagePlayPause;
private TextView textCurrentTime, textTotalDuration;
private SeekBar playerSeekBar;
private MediaPlayer mediaPlayer;
private Handler handler = new Handler();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

imagePlayPause = findViewById(R.id.imagePlayPause);
textCurrentTime = findViewById(R.id.textCurrentTime);
textTotalDuration = findViewById(R.id.textTotalDuration);
playerSeekBar = findViewById(R.id.playerSeekBar);
mediaPlayer = new MediaPlayer();

playerSeekBar.setMax(100);

imagePlayPause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mediaPlayer.isPlaying())
{
handler.removeCallbacks(updater);
mediaPlayer.pause();
imagePlayPause.setImageResource(R.drawable.ic_play);
}else{
mediaPlayer.start();
imagePlayPause.setImageResource(R.drawable.ic_pause);
updateSeekBar();
}
}
});

prepareMediaPlayer();
}

private void prepareMediaPlayer() {
try {
mediaPlayer.setDataSource("http://stream.radiomedia.com.au:8003/stream"); //url of media
mediaPlayer.prepare();
textTotalDuration.setText(milliSecondsToTimer(mediaPlayer.getDuration()));
} catch (Exception exception){
Toast.makeText(this,exception.getMessage(), Toast.LENGTH_SHORT).show();
}
};

private Runnable updater = new Runnable() {
@Override
public void run() {
updateSeekBar();
long currentDuration = mediaPlayer.getCurrentPosition();
textCurrentTime.setText(milliSecondsToTimer(currentDuration));
}
};

private void updateSeekBar(){
if(mediaPlayer.isPlaying()) {
playerSeekBar.setProgress((int) (((float) mediaPlayer.getCurrentPosition() / mediaPlayer.getDuration()) * 100));
handler.postDelayed(updater, 1000);
}
};

private String milliSecondsToTimer(long milliSeconds) {
String timerString = "";
String secondsString;

int hours = (int)(milliSeconds / (1000 * 60 * 60));
int minutes = (int)(milliSeconds % (1000 * 60 * 60)) / (1000 *60);
int seconds = (int)((milliSeconds % (1000 * 60 *60)) % (1000 * 60) / 1000);

if(hours > 0)
{
timerString = hours + ":";
}

if(seconds < 10)
{
secondsString = "0" + seconds;
}else{
secondsString = "" + seconds;
}

timerString = timerString + minutes + ":" + secondsString;
return timerString;
}
}

最佳答案

你应该关注这个 old google mediaplayer sample (如果您想继续使用 MediaPlayer,请使用 commit 如果主版本崩溃)。
但是,如果您不介意使用 ExoPlayer,那么您应该遵循 new one ,因为 ExoPlayer 已经可以处理部分通知内容。
但是在这些示例项目中,您可以看到:

  • 它不仅仅是一个通知那么简单,它还与人们按下耳机上的播放按钮等有关。
  • 你真的需要一个服务来绑定(bind)通知,处理 action.MEDIA_BUTTON Intent 。

  • 使用 MediaSession 添加此类通知的最少代码和您使用的 MediaPlayer(所以不是 ExoPlayer)的服务看起来像这样:
    将媒体兼容库添加到您的应用程序的构建 gradle:
    dependencies {
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation "androidx.media:media:1.1.0"
    }
    然后创建一个用于创建通知的类:
    package com.radiomedia.a1liferadio;

    import android.app.Notification;
    import android.app.NotificationChannel;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.Intent;
    import android.graphics.Color;
    import android.os.Build;
    import android.support.v4.media.MediaDescriptionCompat;
    import android.support.v4.media.MediaMetadataCompat;
    import android.support.v4.media.session.MediaSessionCompat;
    import android.support.v4.media.session.PlaybackStateCompat;
    import android.util.Log;

    import androidx.annotation.NonNull;
    import androidx.annotation.RequiresApi;
    import androidx.core.app.NotificationCompat;
    import androidx.core.content.ContextCompat;
    import androidx.media.app.NotificationCompat.MediaStyle;
    import androidx.media.session.MediaButtonReceiver;


    /**
    * Keeps track of a notification and updates it automatically for a given MediaSession. This is
    * required so that the music service don't get killed during playback.
    */
    public class MediaNotificationManager {

    public static final int NOTIFICATION_ID = 412;

    private static final String TAG = MediaNotificationManager.class.getSimpleName();
    private static final String CHANNEL_ID = "com.example.android.musicplayer.channel";
    private static final int REQUEST_CODE = 501;

    private final MediaSessionService mService;

    private final NotificationCompat.Action mPlayAction;
    private final NotificationCompat.Action mPauseAction;
    private final NotificationManager mNotificationManager;

    public MediaNotificationManager(MediaSessionService musicContext) {
    mService = musicContext;

    mNotificationManager =
    (NotificationManager) mService.getSystemService(Service.NOTIFICATION_SERVICE);

    mPlayAction =
    new NotificationCompat.Action(
    R.drawable.ic_play,
    "play",
    MediaButtonReceiver.buildMediaButtonPendingIntent(
    mService,
    PlaybackStateCompat.ACTION_PLAY));
    mPauseAction =
    new NotificationCompat.Action(
    R.drawable.ic_pause,
    "pause",
    MediaButtonReceiver.buildMediaButtonPendingIntent(
    mService,
    PlaybackStateCompat.ACTION_PAUSE));
    // Cancel all notifications to handle the case where the Service was killed and
    // restarted by the system.
    mNotificationManager.cancelAll();
    }

    public void onDestroy() {
    Log.d(TAG, "onDestroy: ");
    }

    public NotificationManager getNotificationManager() {
    return mNotificationManager;
    }

    public Notification getNotification(MediaMetadataCompat metadata,
    @NonNull PlaybackStateCompat state,
    MediaSessionCompat.Token token) {
    boolean isPlaying = state.getState() == PlaybackStateCompat.STATE_PLAYING;
    MediaDescriptionCompat description = metadata.getDescription();
    NotificationCompat.Builder builder =
    buildNotification(state, token, isPlaying, description);
    return builder.build();
    }

    private NotificationCompat.Builder buildNotification(@NonNull PlaybackStateCompat state,
    MediaSessionCompat.Token token,
    boolean isPlaying,
    MediaDescriptionCompat description) {

    // Create the (mandatory) notification channel when running on Android Oreo.
    if (isAndroidOOrHigher()) {
    createChannel();
    }

    NotificationCompat.Builder builder = new NotificationCompat.Builder(mService, CHANNEL_ID);
    builder.setStyle(
    new MediaStyle()
    .setMediaSession(token)
    .setShowActionsInCompactView(0)
    // For backwards compatibility with Android L and earlier.
    .setShowCancelButton(true)
    .setCancelButtonIntent(
    MediaButtonReceiver.buildMediaButtonPendingIntent(
    mService,
    PlaybackStateCompat.ACTION_STOP)))
    .setColor(ContextCompat.getColor(mService, R.color.colorPrimary))
    .setSmallIcon(R.drawable.ic_play)
    // Pending intent that is fired when user clicks on notification.
    .setContentIntent(createContentIntent())
    // Title - Usually Song name.
    .setContentTitle(description.getTitle())
    // When notification is deleted (when playback is paused and notification can be
    // deleted) fire MediaButtonPendingIntent with ACTION_PAUSE.
    .setDeleteIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(
    mService, PlaybackStateCompat.ACTION_PAUSE));


    builder.addAction(isPlaying ? mPauseAction : mPlayAction);

    return builder;
    }

    // Does nothing on versions of Android earlier than O.
    @RequiresApi(Build.VERSION_CODES.O)
    private void createChannel() {
    if (mNotificationManager.getNotificationChannel(CHANNEL_ID) == null) {
    // The user-visible name of the channel.
    CharSequence name = "MediaSession";
    // The user-visible description of the channel.
    String description = "MediaSession and MediaPlayer";
    int importance = NotificationManager.IMPORTANCE_LOW;
    NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
    // Configure the notification channel.
    mChannel.setDescription(description);
    mChannel.enableLights(true);
    // Sets the notification light color for notifications posted to this
    // channel, if the device supports this feature.
    mChannel.setLightColor(Color.RED);
    mChannel.enableVibration(true);
    mChannel.setVibrationPattern(
    new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
    mNotificationManager.createNotificationChannel(mChannel);
    Log.d(TAG, "createChannel: New channel created");
    } else {
    Log.d(TAG, "createChannel: Existing channel reused");
    }
    }

    private boolean isAndroidOOrHigher() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
    }

    private PendingIntent createContentIntent() {
    Intent openUI = new Intent(mService, MainActivity.class);
    openUI.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
    return PendingIntent.getActivity(
    mService, REQUEST_CODE, openUI, PendingIntent.FLAG_CANCEL_CURRENT);
    }

    }
    然后创建一个处理播放和通知按钮按下的服务类:
    package com.radiomedia.a1liferadio;

    import android.app.Notification;
    import android.app.Service;
    import android.content.Intent;
    import android.media.MediaPlayer;
    import android.os.IBinder;
    import android.os.SystemClock;
    import android.support.v4.media.MediaMetadataCompat;
    import android.support.v4.media.session.MediaSessionCompat;
    import android.support.v4.media.session.PlaybackStateCompat;
    import android.view.KeyEvent;

    import androidx.annotation.Nullable;

    public class MediaSessionService extends Service {
    public MediaPlayer mediaPlayer;
    public static final String TAG = "MediaSessionService";
    public static final int NOTIFICATION_ID = 888;
    private MediaNotificationManager mMediaNotificationManager;
    private MediaSessionCompat mediaSession;

    @Override
    public void onCreate() {
    super.onCreate();
    mediaPlayer = new MediaPlayer();
    mMediaNotificationManager = new MediaNotificationManager(this);
    mediaSession = new MediaSessionCompat(this, "SOME_TAG");
    mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
    mediaSession.setCallback(new MediaSessionCompat.Callback() {
    @Override
    public void onPlay() {
    mediaPlayer.start();
    }

    @Override
    public void onPause() {
    mediaPlayer.pause();
    }
    });
    Notification notification =
    mMediaNotificationManager.getNotification(
    getMetadata(), getState(), mediaSession.getSessionToken());

    startForeground(NOTIFICATION_ID, notification);
    }

    public MediaMetadataCompat getMetadata() {
    MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();

    builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, "artist");
    builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, "title");
    builder.putLong(
    MediaMetadataCompat.METADATA_KEY_DURATION, mediaPlayer.getDuration()
    );
    return builder.build();
    }

    private PlaybackStateCompat getState() {
    long actions = mediaPlayer.isPlaying() ? PlaybackStateCompat.ACTION_PAUSE : PlaybackStateCompat.ACTION_PLAY;
    int state = mediaPlayer.isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED;

    final PlaybackStateCompat.Builder stateBuilder = new PlaybackStateCompat.Builder();
    stateBuilder.setActions(actions);
    stateBuilder.setState(state,
    mediaPlayer.getCurrentPosition(),
    1.0f,
    SystemClock.elapsedRealtime());
    return stateBuilder.build();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    if ("android.intent.action.MEDIA_BUTTON".equals(intent.getAction())) {
    KeyEvent keyEvent = (KeyEvent) intent.getExtras().get("android.intent.extra.KEY_EVENT");
    if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PAUSE) {
    mediaPlayer.pause();
    } else {
    mediaPlayer.start();
    }
    }
    return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
    return null;
    }

    }
    更新您的 list 以声明服务并向其发送 action.MEDIA_BUTTON Intent 。
    <service
    android:name=".MediaSessionService"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
    <action android:name="android.intent.action.MEDIA_BUTTON"/>
    </intent-filter>
    </service>
    <receiver android:name="androidx.media.session.MediaButtonReceiver">
    <intent-filter>
    <action android:name="android.intent.action.MEDIA_BUTTON"/>
    </intent-filter>
    </receiver>
    这个 MediaButtonReceiver以上对于 pre-OREO 设备是必需的,它会将事件转发到这些平台上的服务。
    然后从您的主要 Activity 启动服务。
    ContextCompat.startForegroundService(
    MainActivity.this.getApplicationContext(),
    new Intent(MainActivity.this.getApplicationContext(), MediaSessionService.class));
    这里仍然要做的事情是让您的主要 Activity 以某种方式向您的服务或服务中的玩家发送操作,更新通知和服务状态的更改,但您应该能够使用此代码得到一些东西并找出其余的来自谷歌示例代码。

    关于Java Android 媒体播放器(通知),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63501425/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com