update
This commit is contained in:
parent
4e453392e7
commit
7704be296d
@ -25,7 +25,7 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||||
implementation 'androidx.work:work-runtime:2.4.0'
|
implementation 'androidx.work:work-runtime:2.4.0'
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
|
@ -25,6 +25,11 @@
|
|||||||
<action android:name="android.media.browse.MediaBrowserService" />
|
<action android:name="android.media.browse.MediaBrowserService" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
<receiver android:name="androidx.media.session.MediaButtonReceiver" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
@ -4,9 +4,16 @@ import android.content.ComponentName;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
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.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.PlaybackStateCompat;
|
||||||
|
|
||||||
import com.yutou.nas_music_player.services.MusicService;
|
import com.yutou.nas_music_player.services.MusicService;
|
||||||
|
import com.yutou.nas_music_player.views.MainActivity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class MediaBrowserHelper {
|
public class MediaBrowserHelper {
|
||||||
private MediaControllerCompat controllerCompat;
|
private MediaControllerCompat controllerCompat;
|
||||||
@ -36,6 +43,10 @@ public class MediaBrowserHelper {
|
|||||||
public MediaControllerCompat.TransportControls getTransportControls() {
|
public MediaControllerCompat.TransportControls getTransportControls() {
|
||||||
return controllerCompat.getTransportControls();
|
return controllerCompat.getTransportControls();
|
||||||
}
|
}
|
||||||
|
private List<MediaControllerCompat.Callback> callbacks=new ArrayList<>();
|
||||||
|
public void regPlayListener(MediaControllerCompat.Callback playListener) {
|
||||||
|
callbacks.add(playListener);
|
||||||
|
}
|
||||||
|
|
||||||
private class MediaBrowserConnectionCallback extends MediaBrowserCompat.ConnectionCallback {
|
private class MediaBrowserConnectionCallback extends MediaBrowserCompat.ConnectionCallback {
|
||||||
@Override
|
@Override
|
||||||
@ -57,7 +68,37 @@ public class MediaBrowserHelper {
|
|||||||
|
|
||||||
|
|
||||||
private class MediaControllerCallback extends MediaControllerCompat.Callback {
|
private class MediaControllerCallback extends MediaControllerCompat.Callback {
|
||||||
|
@Override
|
||||||
|
public void onPlaybackStateChanged(PlaybackStateCompat state) {
|
||||||
|
super.onPlaybackStateChanged(state);
|
||||||
|
for (MediaControllerCompat.Callback callback : callbacks) {
|
||||||
|
callback.onPlaybackStateChanged(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMetadataChanged(MediaMetadataCompat metadata) {
|
||||||
|
super.onMetadataChanged(metadata);
|
||||||
|
for (MediaControllerCompat.Callback callback : callbacks) {
|
||||||
|
callback.onMetadataChanged(metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSessionDestroyed() {
|
||||||
|
super.onSessionDestroyed();
|
||||||
|
for (MediaControllerCompat.Callback callback : callbacks) {
|
||||||
|
callback.onSessionDestroyed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onQueueChanged(List<MediaSessionCompat.QueueItem> queue) {
|
||||||
|
super.onQueueChanged(queue);
|
||||||
|
for (MediaControllerCompat.Callback callback : callbacks) {
|
||||||
|
callback.onQueueChanged(queue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public class MediaBrowserSubscriptionCallback extends MediaBrowserCompat.SubscriptionCallback {
|
public class MediaBrowserSubscriptionCallback extends MediaBrowserCompat.SubscriptionCallback {
|
||||||
|
|
||||||
|
@ -1,4 +1,154 @@
|
|||||||
package com.yutou.nas_music_player.containers;
|
package com.yutou.nas_music_player.containers;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationChannel;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
|
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.graphics.drawable.IconCompat;
|
||||||
|
import androidx.media.session.MediaButtonReceiver;
|
||||||
|
|
||||||
|
import com.yutou.nas_music_player.MyApplication;
|
||||||
|
import com.yutou.nas_music_player.R;
|
||||||
|
import com.yutou.nas_music_player.services.MusicService;
|
||||||
|
import com.yutou.nas_music_player.views.MainActivity;
|
||||||
|
|
||||||
public class MediaNotificationManager {
|
public class MediaNotificationManager {
|
||||||
|
public static final int NOTIFICATION_ID = 412;
|
||||||
|
private static final String CHANNEL_ID = MyApplication.application.getPackageName() + ".music_channel";
|
||||||
|
private MusicService mService;
|
||||||
|
private NotificationCompat.Action mPlayAction;
|
||||||
|
private NotificationCompat.Action mPauseAction;
|
||||||
|
private NotificationCompat.Action mNextAction;
|
||||||
|
private NotificationCompat.Action mPrevAction;
|
||||||
|
private NotificationManager mNotificationManager;
|
||||||
|
|
||||||
|
public MediaNotificationManager(MusicService musicService) {
|
||||||
|
this.mService = musicService;
|
||||||
|
mNotificationManager =
|
||||||
|
(NotificationManager) mService.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
|
mPlayAction =
|
||||||
|
new NotificationCompat.Action(
|
||||||
|
android.R.drawable.ic_media_play,
|
||||||
|
"播放",
|
||||||
|
MediaButtonReceiver.buildMediaButtonPendingIntent(
|
||||||
|
mService,
|
||||||
|
PlaybackStateCompat.ACTION_PLAY));
|
||||||
|
mPauseAction =
|
||||||
|
new NotificationCompat.Action(
|
||||||
|
android.R.drawable.ic_media_pause,
|
||||||
|
"暂停",
|
||||||
|
MediaButtonReceiver.buildMediaButtonPendingIntent(
|
||||||
|
mService,
|
||||||
|
PlaybackStateCompat.ACTION_PAUSE));
|
||||||
|
mNextAction =
|
||||||
|
new NotificationCompat.Action(
|
||||||
|
android.R.drawable.ic_media_next,
|
||||||
|
"下一首",
|
||||||
|
MediaButtonReceiver.buildMediaButtonPendingIntent(
|
||||||
|
mService,
|
||||||
|
PlaybackStateCompat.ACTION_SKIP_TO_NEXT));
|
||||||
|
mPrevAction =
|
||||||
|
new NotificationCompat.Action(
|
||||||
|
android.R.drawable.ic_media_previous,
|
||||||
|
"上一首",
|
||||||
|
MediaButtonReceiver.buildMediaButtonPendingIntent(
|
||||||
|
mService,
|
||||||
|
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS));
|
||||||
|
|
||||||
|
// Cancel all notifications to handle the case where the Service was killed and
|
||||||
|
// restarted by the system.
|
||||||
|
mNotificationManager.cancelAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotificationManager getManager() {
|
||||||
|
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, metadata);
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private NotificationCompat.Builder buildNotification(@NonNull PlaybackStateCompat state,
|
||||||
|
MediaSessionCompat.Token token,
|
||||||
|
boolean isPlaying,
|
||||||
|
MediaMetadataCompat metadata) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
createChannel();
|
||||||
|
}
|
||||||
|
MediaDescriptionCompat description = metadata.getDescription();
|
||||||
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(mService, CHANNEL_ID);
|
||||||
|
builder.setStyle(new androidx.media.app.NotificationCompat.MediaStyle()
|
||||||
|
.setMediaSession(token)
|
||||||
|
.setShowActionsInCompactView(0,1,2)
|
||||||
|
.setShowCancelButton(true)
|
||||||
|
.setCancelButtonIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(mService,PlaybackStateCompat.ACTION_STOP))
|
||||||
|
);
|
||||||
|
builder.setColor(Color.BLUE);
|
||||||
|
if(metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON)!=null){
|
||||||
|
builder.setLargeIcon(metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON));
|
||||||
|
}
|
||||||
|
builder.setSmallIcon(R.mipmap.ic_launcher);
|
||||||
|
builder.setContentIntent(mService.mediaSession.getController().getSessionActivity());
|
||||||
|
builder.setContentTitle(description.getTitle());
|
||||||
|
builder.setContentText(description.getSubtitle());
|
||||||
|
builder.setDeleteIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(
|
||||||
|
mService, PlaybackStateCompat.ACTION_STOP));
|
||||||
|
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
||||||
|
if ((state.getActions() & PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS) != 0) {
|
||||||
|
builder.addAction(mPrevAction);
|
||||||
|
}
|
||||||
|
builder.addAction(isPlaying ? mPauseAction : mPlayAction);
|
||||||
|
if ((state.getActions() & PlaybackStateCompat.ACTION_SKIP_TO_NEXT) != 0) {
|
||||||
|
builder.addAction(mNextAction);
|
||||||
|
}
|
||||||
|
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 = "NAS音乐播放器";
|
||||||
|
// The user-visible description of the channel.
|
||||||
|
String description = "NAS音乐播放器通知栏";
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private PendingIntent createContentIntent() {
|
||||||
|
Intent openUI = new Intent(mService, MainActivity.class);
|
||||||
|
openUI.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
|
return PendingIntent.getActivity(
|
||||||
|
mService, 233, openUI, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import static android.media.MediaMetadata.METADATA_KEY_DISPLAY_ICON;
|
||||||
|
|
||||||
|
|
||||||
public class MusicContainer {
|
public class MusicContainer {
|
||||||
private static MusicContainer container;
|
private static MusicContainer container;
|
||||||
@ -24,8 +26,23 @@ public class MusicContainer {
|
|||||||
|
|
||||||
private MusicContainer() {
|
private MusicContainer() {
|
||||||
mediaPlayer = new MediaPlayer();
|
mediaPlayer = new MediaPlayer();
|
||||||
|
initMediaPlayer();
|
||||||
libs = new MusicLibs();
|
libs = new MusicLibs();
|
||||||
}
|
}
|
||||||
|
private void initMediaPlayer(){
|
||||||
|
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
||||||
|
@Override
|
||||||
|
public void onCompletion(MediaPlayer mp) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public MediaPlayer getMediaPlayer(){
|
||||||
|
return mediaPlayer;
|
||||||
|
}
|
||||||
|
public MusicData getNowPlayData(){
|
||||||
|
return nowPlayData;
|
||||||
|
}
|
||||||
|
|
||||||
public static MusicContainer getInstance() {
|
public static MusicContainer getInstance() {
|
||||||
if (container == null) {
|
if (container == null) {
|
||||||
@ -44,8 +61,7 @@ public class MusicContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void play(MusicData data) {
|
public void play(MusicData data) {
|
||||||
String url = NetworkTool.NetworkAPI.HOME + NetworkTool.NetworkAPI.MUSIC_PLAY
|
String url =data.getPlayUrl();
|
||||||
+ "?random=false&token=" + NetworkTool.NetworkAPI.HTTP_KEY + "&filePath=" + data.getPlayFile();
|
|
||||||
try {
|
try {
|
||||||
if (mediaPlayer.isPlaying()) {
|
if (mediaPlayer.isPlaying()) {
|
||||||
mediaPlayer.stop();
|
mediaPlayer.stop();
|
||||||
@ -76,6 +92,10 @@ public class MusicContainer {
|
|||||||
builder.putLong(MediaMetadataCompat.METADATA_KEY_YEAR, Long.parseLong(data.getYear()));
|
builder.putLong(MediaMetadataCompat.METADATA_KEY_YEAR, Long.parseLong(data.getYear()));
|
||||||
builder.putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, Long.parseLong(data.getTrack()));
|
builder.putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, Long.parseLong(data.getTrack()));
|
||||||
builder.putLong(MediaMetadataCompat.METADATA_KEY_DISC_NUMBER, Long.parseLong(data.getDisc_no()));
|
builder.putLong(MediaMetadataCompat.METADATA_KEY_DISC_NUMBER, Long.parseLong(data.getDisc_no()));
|
||||||
|
builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION,3*60*1000);
|
||||||
|
if(data.getImg()!=null){
|
||||||
|
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON,data.getImg());
|
||||||
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
package com.yutou.nas_music_player.containers;
|
package com.yutou.nas_music_player.containers;
|
||||||
|
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.yutou.nas_music_player.Interfaces.NetworkInterface;
|
||||||
|
import com.yutou.nas_music_player.tools.NetworkTool;
|
||||||
import com.yutou.nas_music_player.tools.StringUtil;
|
import com.yutou.nas_music_player.tools.StringUtil;
|
||||||
|
|
||||||
public class MusicData {
|
public class MusicData {
|
||||||
@ -18,6 +23,7 @@ public class MusicData {
|
|||||||
private String lastDir;//上一个文件夹
|
private String lastDir;//上一个文件夹
|
||||||
private String file;
|
private String file;
|
||||||
private boolean isDir = false;
|
private boolean isDir = false;
|
||||||
|
private Bitmap img;
|
||||||
|
|
||||||
public MusicData() {
|
public MusicData() {
|
||||||
}
|
}
|
||||||
@ -55,8 +61,8 @@ public class MusicData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getYear() {
|
public String getYear() {
|
||||||
if(StringUtil.isEmpty(year)){
|
if (StringUtil.isEmpty(year)) {
|
||||||
year="8888";
|
year = "8888";
|
||||||
}
|
}
|
||||||
return year;
|
return year;
|
||||||
}
|
}
|
||||||
@ -66,7 +72,7 @@ public class MusicData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getTrack() {
|
public String getTrack() {
|
||||||
if(StringUtil.isEmpty(track)){
|
if (StringUtil.isEmpty(track)) {
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
return track;
|
return track;
|
||||||
@ -77,7 +83,7 @@ public class MusicData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getDisc_no() {
|
public String getDisc_no() {
|
||||||
if(StringUtil.isEmpty(disc_no)){
|
if (StringUtil.isEmpty(disc_no)) {
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
return disc_no;
|
return disc_no;
|
||||||
@ -123,10 +129,47 @@ public class MusicData {
|
|||||||
public String getFile() {
|
public String getFile() {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFile(String file) {
|
public void setFile(String file) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
public String getPlayFile(){
|
|
||||||
return new String(Base64.encode(file.getBytes(),Base64.DEFAULT));
|
public String getPlayFileBase64() {
|
||||||
|
return new String(Base64.encode(file.getBytes(), Base64.DEFAULT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlayUrl() {
|
||||||
|
return NetworkTool.NetworkAPI.HOME + NetworkTool.NetworkAPI.MUSIC_PLAY
|
||||||
|
+ "?random=false&token=" + NetworkTool.NetworkAPI.HTTP_KEY + "&filePath=" + getPlayFileBase64();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDownloadImg = false;
|
||||||
|
|
||||||
|
public Bitmap getImg() {
|
||||||
|
if (img != null) {
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
if (isDownloadImg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
isDownloadImg = true;
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
json.put("fileName", getPlayFileBase64());
|
||||||
|
NetworkTool.init().httpGet(NetworkTool.NetworkAPI.MUSIC_IMAGE, json, new NetworkInterface() {
|
||||||
|
@Override
|
||||||
|
public void httpGetData(Object data, int state) {
|
||||||
|
JSONObject json = JSONObject.parseObject(data.toString());
|
||||||
|
if (json.getInteger("code") == 0) {
|
||||||
|
byte[] bytes = json.getBytes("data");
|
||||||
|
img = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void httpError(Exception e) {
|
||||||
|
isDownloadImg = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return img;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package com.yutou.nas_music_player.services;
|
package com.yutou.nas_music_player.services;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.support.v4.media.MediaBrowserCompat;
|
import android.support.v4.media.MediaBrowserCompat;
|
||||||
import android.support.v4.media.MediaMetadataCompat;
|
import android.support.v4.media.MediaMetadataCompat;
|
||||||
import android.support.v4.media.session.MediaSessionCompat;
|
import android.support.v4.media.session.MediaSessionCompat;
|
||||||
@ -13,29 +15,41 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media.MediaBrowserServiceCompat;
|
import androidx.media.MediaBrowserServiceCompat;
|
||||||
|
|
||||||
|
import com.yutou.nas_music_player.containers.MediaNotificationManager;
|
||||||
import com.yutou.nas_music_player.containers.MusicContainer;
|
import com.yutou.nas_music_player.containers.MusicContainer;
|
||||||
import com.yutou.nas_music_player.containers.MusicData;
|
import com.yutou.nas_music_player.containers.MusicData;
|
||||||
import com.yutou.nas_music_player.tools.AppData;
|
import com.yutou.nas_music_player.tools.AppData;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
public class MusicService extends MediaBrowserServiceCompat {
|
public class MusicService extends MediaBrowserServiceCompat {
|
||||||
private MediaSessionCompat mediaSession;
|
public MediaSessionCompat mediaSession;
|
||||||
private PlaybackStateCompat.Builder stateBuilder;
|
private PlaybackStateCompat.Builder stateBuilder;
|
||||||
|
private MediaNotificationManager notificationManager;
|
||||||
|
private int mState = PlaybackStateCompat.STATE_PLAYING;
|
||||||
|
|
||||||
|
private static final long MEDIA_SESSION_ACTIONS = PlaybackStateCompat.ACTION_PLAY
|
||||||
|
| PlaybackStateCompat.ACTION_PAUSE
|
||||||
|
| PlaybackStateCompat.ACTION_PLAY_PAUSE
|
||||||
|
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT
|
||||||
|
| PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
|
||||||
|
| PlaybackStateCompat.ACTION_STOP
|
||||||
|
| PlaybackStateCompat.ACTION_SEEK_TO;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
notificationManager = new MediaNotificationManager(this);
|
||||||
mediaSession = new MediaSessionCompat(getApplicationContext(), "MEDIA_LOG");
|
mediaSession = new MediaSessionCompat(getApplicationContext(), "MEDIA_LOG");
|
||||||
mediaSession.setFlags(
|
mediaSession.setFlags(
|
||||||
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
|
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
|
||||||
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
|
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
|
||||||
|
|
||||||
stateBuilder = new PlaybackStateCompat.Builder()
|
stateBuilder = new PlaybackStateCompat.Builder()
|
||||||
.setActions(
|
.setActions(MEDIA_SESSION_ACTIONS);
|
||||||
PlaybackStateCompat.ACTION_PLAY |
|
|
||||||
PlaybackStateCompat.ACTION_PLAY_PAUSE);
|
|
||||||
mediaSession.setPlaybackState(stateBuilder.build());
|
mediaSession.setPlaybackState(stateBuilder.build());
|
||||||
mediaSession.setCallback(new MediaSessionCallback());
|
mediaSession.setCallback(new MediaSessionCallback());
|
||||||
setSessionToken(mediaSession.getSessionToken());
|
setSessionToken(mediaSession.getSessionToken());
|
||||||
@ -50,10 +64,10 @@ public class MusicService extends MediaBrowserServiceCompat {
|
|||||||
@Override
|
@Override
|
||||||
public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaBrowserCompat.MediaItem>> result) {
|
public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaBrowserCompat.MediaItem>> result) {
|
||||||
List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>();
|
List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>();
|
||||||
MediaMetadataCompat compat=MusicContainer.getInstance().getNowPlayMetadataCompat();
|
MediaMetadataCompat compat = MusicContainer.getInstance().getNowPlayMetadataCompat();
|
||||||
System.out.println(compat);
|
System.out.println(compat);
|
||||||
if(compat!=null){
|
if (compat != null) {
|
||||||
MediaBrowserCompat.MediaItem mediaItem=new MediaBrowserCompat.MediaItem(compat.getDescription(), MediaBrowserCompat.MediaItem.FLAG_PLAYABLE);
|
MediaBrowserCompat.MediaItem mediaItem = new MediaBrowserCompat.MediaItem(compat.getDescription(), MediaBrowserCompat.MediaItem.FLAG_PLAYABLE);
|
||||||
mediaItems.add(mediaItem);
|
mediaItems.add(mediaItem);
|
||||||
}
|
}
|
||||||
result.sendResult(mediaItems);
|
result.sendResult(mediaItems);
|
||||||
@ -64,15 +78,77 @@ public class MusicService extends MediaBrowserServiceCompat {
|
|||||||
public void onPlay() {
|
public void onPlay() {
|
||||||
super.onPlay();
|
super.onPlay();
|
||||||
System.out.println("接收到播放指令");
|
System.out.println("接收到播放指令");
|
||||||
MediaMetadataCompat metadataCompat=MusicContainer.getInstance().getNowPlayMetadataCompat();
|
MediaMetadataCompat metadataCompat = MusicContainer.getInstance().getNowPlayMetadataCompat();
|
||||||
mediaSession.setMetadata(metadataCompat);
|
mediaSession.setMetadata(metadataCompat);
|
||||||
mediaSession.setActive(true);
|
mediaSession.setActive(true);
|
||||||
|
|
||||||
|
Notification notification = notificationManager.getNotification(metadataCompat, builderState(0).build(), getSessionToken());
|
||||||
|
startForeground(MediaNotificationManager.NOTIFICATION_ID, notification);
|
||||||
|
new Timer().schedule(new TimerTask() {
|
||||||
|
long position = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
position += 1000;
|
||||||
|
MusicData data=MusicContainer.getInstance().getNowPlayData();
|
||||||
|
data.setTitle(position+"");
|
||||||
|
MediaMetadataCompat metadataCompat = MusicContainer.getInstance().getMetadataCompat(data);
|
||||||
|
Notification notification = notificationManager.getNotification(metadataCompat, builderState(position).build(), getSessionToken());
|
||||||
|
notificationManager.getManager()
|
||||||
|
.notify(MediaNotificationManager.NOTIFICATION_ID, notification);
|
||||||
|
mediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
|
||||||
|
.setActions(MEDIA_SESSION_ACTIONS)
|
||||||
|
.setState(PlaybackStateCompat.STATE_PLAYING,position,1.0f,SystemClock.elapsedRealtime()).build());
|
||||||
|
}
|
||||||
|
}, 0, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSeekTo(long pos) {
|
||||||
|
super.onSeekTo(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlaybackStateCompat.Builder builderState(long position) {
|
||||||
|
PlaybackStateCompat.Builder stateBuilder = new PlaybackStateCompat.Builder();
|
||||||
|
stateBuilder.setActions(getAvailableActions());
|
||||||
|
stateBuilder.setState(mState,
|
||||||
|
position,
|
||||||
|
1.0f,
|
||||||
|
SystemClock.elapsedRealtime());
|
||||||
|
return stateBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getAvailableActions() {
|
||||||
|
long actions = PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID
|
||||||
|
| PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH
|
||||||
|
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT
|
||||||
|
| PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
|
||||||
|
switch (mState) {
|
||||||
|
case PlaybackStateCompat.STATE_STOPPED:
|
||||||
|
actions |= PlaybackStateCompat.ACTION_PLAY
|
||||||
|
| PlaybackStateCompat.ACTION_PAUSE;
|
||||||
|
break;
|
||||||
|
case PlaybackStateCompat.STATE_PLAYING:
|
||||||
|
actions |= PlaybackStateCompat.ACTION_STOP
|
||||||
|
| PlaybackStateCompat.ACTION_PAUSE
|
||||||
|
| PlaybackStateCompat.ACTION_SEEK_TO;
|
||||||
|
break;
|
||||||
|
case PlaybackStateCompat.STATE_PAUSED:
|
||||||
|
actions |= PlaybackStateCompat.ACTION_PLAY
|
||||||
|
| PlaybackStateCompat.ACTION_STOP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
actions |= PlaybackStateCompat.ACTION_PLAY
|
||||||
|
| PlaybackStateCompat.ACTION_PLAY_PAUSE
|
||||||
|
| PlaybackStateCompat.ACTION_STOP
|
||||||
|
| PlaybackStateCompat.ACTION_PAUSE;
|
||||||
|
}
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,37 +3,80 @@ package com.yutou.nas_music_player.views;
|
|||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.media.MediaMetadataCompat;
|
||||||
|
import android.support.v4.media.session.MediaControllerCompat;
|
||||||
|
import android.support.v4.media.session.MediaSessionCompat;
|
||||||
|
import android.support.v4.media.session.PlaybackStateCompat;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.MediaController;
|
||||||
|
|
||||||
import com.yutou.nas_music_player.R;
|
import com.yutou.nas_music_player.R;
|
||||||
import com.yutou.nas_music_player.containers.MediaBrowserHelper;
|
import com.yutou.nas_music_player.containers.MediaBrowserHelper;
|
||||||
import com.yutou.nas_music_player.containers.MusicContainer;
|
import com.yutou.nas_music_player.containers.MusicContainer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
private ImageButton play,previous,next;
|
private ImageButton play, previous, next;
|
||||||
private MediaBrowserHelper browserHelper;
|
private MediaBrowserHelper browserHelper;
|
||||||
|
private ImageView imageView2;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
MusicContainer.getInstance();
|
MusicContainer.getInstance();
|
||||||
play=findViewById(R.id.play);
|
play = findViewById(R.id.play);
|
||||||
next=findViewById(R.id.next);
|
next = findViewById(R.id.next);
|
||||||
|
previous = findViewById(R.id.previous);
|
||||||
|
imageView2 = findViewById(R.id.imageView2);
|
||||||
play.setOnClickListener(new View.OnClickListener() {
|
play.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
browserHelper=new MediaBrowserHelper(MainActivity.this);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
next.setOnClickListener(new View.OnClickListener() {
|
next.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
browserHelper.getTransportControls().play();
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
previous.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// browserHelper=new MediaBrowserHelper(this);
|
browserHelper = new MediaBrowserHelper(this);
|
||||||
|
browserHelper.regPlayListener(new PlayListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PlayListener extends MediaControllerCompat.Callback {
|
||||||
|
@Override
|
||||||
|
public void onPlaybackStateChanged(PlaybackStateCompat state) {
|
||||||
|
super.onPlaybackStateChanged(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMetadataChanged(MediaMetadataCompat metadata) {
|
||||||
|
super.onMetadataChanged(metadata);
|
||||||
|
if(metadata!=null){
|
||||||
|
imageView2.setImageBitmap(metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSessionDestroyed() {
|
||||||
|
super.onSessionDestroyed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onQueueChanged(List<MediaSessionCompat.QueueItem> queue) {
|
||||||
|
super.onQueueChanged(queue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -31,10 +31,11 @@
|
|||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/linearLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:gravity="center"
|
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="20dp"
|
||||||
|
android:gravity="center"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
@ -63,4 +64,25 @@
|
|||||||
android:layout_marginStart="30dp"
|
android:layout_marginStart="30dp"
|
||||||
android:src="@android:drawable/ic_media_next" />
|
android:src="@android:drawable/ic_media_next" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/linearLayout">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="title" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/artist"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="artist-album" />
|
||||||
|
</LinearLayout>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
Reference in New Issue
Block a user