有内存泄露
This commit is contained in:
yutou 2020-11-24 18:32:19 +08:00
parent c7c6a07e45
commit 26bdcffb68
21 changed files with 826 additions and 85 deletions

View File

@ -40,4 +40,8 @@ dependencies {
implementation 'androidx.palette:palette:1.0.0'
implementation 'com.github.zrunker:ZTextView:v1.0.2'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.5'
implementation 'com.kaopiz:kprogresshud:1.2.0'
implementation 'com.ogaclejapan.smarttablayout:library:2.0.0@aar'
}

View File

@ -15,7 +15,7 @@
android:usesCleartextTraffic="true">
<activity
android:name=".views.OpenActivity"
android:theme="@style/Theme.AppCompat.NoActionBar">
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -25,7 +25,11 @@
<activity
android:name=".views.MainActivity"
android:fitsSystemWindows="true"
android:theme="@style/Theme.AppCompat.NoActionBar" />
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
<activity
android:name=".views.PlayLibsActivity"
android:fitsSystemWindows="true"
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
<service
android:name=".services.MusicService"

View File

@ -1,14 +1,18 @@
package com.yutou.nas_music_player.containers;
package com.yutou.nas_music_player.Datas;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.util.Base64;
import com.alibaba.fastjson.JSONObject;
import com.yutou.nas_music_player.Interfaces.DownloadInterface;
import com.yutou.nas_music_player.Interfaces.NetworkInterface;
import com.yutou.nas_music_player.MyApplication;
import com.yutou.nas_music_player.R;
import com.yutou.nas_music_player.tools.AppTools;
import com.yutou.nas_music_player.tools.NetworkTool;
import com.yutou.nas_music_player.tools.StringUtil;
@ -149,7 +153,7 @@ public class MusicData {
}
public String getPlayFileBase64() {
return new String(Base64.encode(file.getBytes(), Base64.DEFAULT));
return new String(Base64.encode(file.replace("\r\n", "").getBytes(), Base64.DEFAULT));
}
public String getPlayUrl() {
@ -166,6 +170,11 @@ public class MusicData {
if (isDownloadImg) {
return null;
}
img = AppTools.getSaveBitmap(getPlayFileBase64());
if (img != null) {
return img;
}
img = null;
isDownloadImg = true;
JSONObject json = new JSONObject();
json.put("fileName", getPlayFileBase64());
@ -173,9 +182,15 @@ public class MusicData {
@Override
public void httpGetData(Object data, int state) {
JSONObject json = JSONObject.parseObject(data.toString());
try {
if (json.getInteger("code") == 0) {
byte[] bytes = json.getBytes("data");
img = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
AppTools.saveBitmap(img,getPlayFileBase64());
}
} catch (Exception e) {
e.printStackTrace();
img = BitmapFactory.decodeResource(MyApplication.application.getResources(), R.mipmap.ic_launcher);
}
}

View File

@ -0,0 +1,34 @@
package com.yutou.nas_music_player.Datas;
import java.util.ArrayList;
import java.util.List;
/**
* 播放记录
*/
public class PreviousPlayerList {
private static final int INDEX=10;//记录十条
private List<MusicData> list;
public PreviousPlayerList(){
list=new ArrayList<>();
}
public void add(MusicData musicData){
MusicData tmp = null;
for (MusicData data : list) {
if(data.getFile().equals(musicData.getFile())){
tmp=data;
}
}
if(tmp!=null){
list.remove(tmp);
}
list.add(musicData);
}
public MusicData getMusicData(){
if(list.size()>1){
list.remove(list.size()-1);
}
return list.get(list.size()-1);
}
}

View File

@ -53,7 +53,6 @@ public class MediaBrowserHelper {
public void regPlayListener(MediaControllerCompat.Callback playListener) {
callbacks.add(playListener);
}
private class MediaBrowserConnectionCallback extends MediaBrowserCompat.ConnectionCallback {
@Override
public void onConnected() {

View File

@ -1,11 +1,17 @@
package com.yutou.nas_music_player.containers;
import android.media.MediaPlayer;
import android.os.Build;
import android.support.v4.media.MediaMetadataCompat;
import android.widget.Toast;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yutou.nas_music_player.Datas.MusicData;
import com.yutou.nas_music_player.Datas.PreviousPlayerList;
import com.yutou.nas_music_player.Interfaces.NetworkInterface;
import com.yutou.nas_music_player.MyApplication;
import com.yutou.nas_music_player.tools.ConfigTools;
import com.yutou.nas_music_player.tools.NetworkTool;
import com.yutou.nas_music_player.tools.StringUtil;
@ -18,23 +24,26 @@ import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import static android.media.MediaPlayer.SEEK_PREVIOUS_SYNC;
public class MusicContainer {
public static final int PLAY_MODEL_RANDOM = 0;
public static final int PLAY_MODEL_LIST = 1;
public static final int PLAY_MODEL_TMP_LIST = 2;
public static final int PLAY_MODEL_ALBUM = 3;
public static final int PLAY_MODEL_RANDOM = 0;//随机
public static final int PLAY_MODEL_ORDER = 1;//顺序
public static final int PLAY_MODEL_ONE_LOOP = 2;//单曲循环
public static final int PLAY_MODEL_LOOP = 3;//列表循环
private static MusicContainer container;
private MusicLibs libs;
private MediaPlayer mediaPlayer;
private int playIndex = 0;
private MusicData nowPlayData = null;
private final MusicLibsInitInterface initInterface;
private MusicLibsInitInterface initInterface;
private List<MediaPlayer.OnCompletionListener> completionListener;
private MediaBrowserHelper browserHelper;
private List<MusicData> playList, tmpList;
private Map<String, List<MusicData>> albumMapList;
private int playModel = PLAY_MODEL_RANDOM;
private PreviousPlayerList previousPlayerList;
private MusicContainer(MusicLibsInitInterface initInterface) {
this.initInterface = initInterface;
@ -42,6 +51,8 @@ public class MusicContainer {
playList = new ArrayList<>();
tmpList = new ArrayList<>();
albumMapList = new HashMap<>();
previousPlayerList = new PreviousPlayerList();
playIndex = ConfigTools.getPreferences().getInt("playIndex", 0);
initMediaPlayer();
libs = new MusicLibs();
}
@ -52,13 +63,37 @@ public class MusicContainer {
private void initMediaPlayer() {
completionListener = new ArrayList<>();
mediaPlayer.setLooping(false);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
System.out.println(nowPlayData.getFile());
int tmp=((int)(nowPlayData.getDurationAsDouble()*1000)-mp.getCurrentPosition());
if(tmp>1000){
System.out.println("发生跳曲行为");
mp.start();
seekTo(mp.getCurrentPosition());
}else {
System.out.println("自动播放完成,进行下一曲");
playTimer.cancel();
playTimer = null;
browserHelper.getTransportControls().skipToNext();
}
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
System.out.println("播放错误: what="+what+" extra="+extra);
return false;
}
});
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
System.out.println("调用了onPrepared");
}
});
}
@ -110,13 +145,15 @@ public class MusicContainer {
isPause = false;
return;
}
ConfigTools.getPreferences().edit().putInt("playIndex", playIndex).apply();
nowPlayData = data;
String url = data.getPlayUrl();
previousPlayerList.add(data);
try {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.reset();
}
mediaPlayer.reset();
mediaPlayer.setDataSource(url);
mediaPlayer.prepare();
mediaPlayer.start();
@ -133,11 +170,23 @@ public class MusicContainer {
}
}, 0, 1000);
}
ConfigTools.getPreferences().edit().putString(ConfigTools.previous_music, JSONObject.toJSONString(data)).apply();
} catch (IOException e) {
e.printStackTrace();
}
}
public void seekTo(long pos) {
System.out.println("跳帧:" + pos);
if (mediaPlayer.isPlaying()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mediaPlayer.seekTo(pos, SEEK_PREVIOUS_SYNC);
} else {
mediaPlayer.seekTo((int) pos);
}
}
}
private Timer playTimer;
public MediaMetadataCompat getNowPlayMetadataCompat() {
@ -162,7 +211,13 @@ public class MusicContainer {
return 8888L;
}
private MediaMetadataCompat metadataCompat;
private String metaDataFile;
public MediaMetadataCompat getMetadataCompat(MusicData data) {
if (data.getFile().equals(metaDataFile)) {
return metadataCompat;
}
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
builder.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, data.getTitle());
builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, data.getArtist());
@ -172,12 +227,13 @@ public class MusicContainer {
builder.putLong(MediaMetadataCompat.METADATA_KEY_YEAR, getYear(data.getYear()));
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_DURATION, ((int) data.getDurationAsDouble()) * 1000);
builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, ((int) (data.getDurationAsDouble() * 1000)));
if (data.getImg() != null) {
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, data.getImg());
}
builder.putString("md5", data.getMd5());
return builder.build();
metadataCompat = builder.build();
return metadataCompat;
}
public static MusicLibs getLibs() {
@ -191,16 +247,20 @@ public class MusicContainer {
mediaPlayer.pause();
}
/**
* 播放下一曲
*/
public void playNext() {
System.out.println("播放模式:" + playModel);
switch (playModel) {
case PLAY_MODEL_LIST:
playList(true);
case PLAY_MODEL_ORDER:
playOrder(false);
break;
case PLAY_MODEL_TMP_LIST:
playTmpList(true);
case PLAY_MODEL_ONE_LOOP:
playOneLoop();
break;
case PLAY_MODEL_ALBUM:
playAlbumList(true);
case PLAY_MODEL_LOOP:
playOrder(true);
break;
case PLAY_MODEL_RANDOM:
default:
@ -208,18 +268,73 @@ public class MusicContainer {
}
}
private void playList(boolean isNext) {
/**
* 播放上一曲
*/
public void playPrevious() {
playIndex--;
MusicData data = previousPlayerList.getMusicData();
if (data != null) {
play(data);
} else {
Toast.makeText(MyApplication.application, "没有上一曲记录", Toast.LENGTH_LONG).show();
}
}
private void playTmpList(boolean isNext) {
/**
* 顺序播放
*
* @param isLoop 循环播放列表
*/
private void playOrder(boolean isLoop) {
if (tmpList.size() != 0) {//有插队列表优先播放
play(tmpList.get(0));//后插入先播放
tmpList.remove(0);
} else if (playList.size() == 0) {//播放列表为空以所有歌列表顺序播放
if (libs.mainData.size() > (playIndex + 1)) {
playIndex++;
} else {
playIndex = 0;
}
play(libs.mainData.get(playIndex));
} else {//播放列表中的歌单
if (playList.size() > (playIndex + 1)) {
playIndex++;
}
if (isLoop) {
playIndex = 0;
play(playList.get(playIndex));
} else {
playList.clear();//列表播放完了清空
playOfAllRandom();//暂时先设计成后续随机播放毕竟列表已经空了
}
}
}
/**
* 单曲循环
*/
private void playOneLoop() {
play(nowPlayData);
}
/**
* 专辑播放
*
* @param isNext 下一首
*/
private void playAlbumList(boolean isNext) {
}
public List<MusicData> getPlayList(){
if(!tmpList.isEmpty()){
return tmpList;
}
if(!playList.isEmpty()){
return playList;
}
return libs.mainData;
}
public class MusicLibs {
private List<MusicData> mainData;
@ -251,6 +366,7 @@ public class MusicContainer {
}
if (initInterface != null) {
initInterface.init();
initInterface = null;
}
}
}
@ -262,14 +378,30 @@ public class MusicContainer {
});
}
public MusicData findMusic(String md5) {
for (MusicData data : mainData) {
public MusicData findMusic(String md5,List<MusicData> list) {
for (MusicData data : list) {
if (data.getMd5() == null) {
continue;
}
if (md5.contains(data.getMd5())) {
return data;
}
}
return null;
}
public int findMusicIndex(String md5, List<MusicData> list) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getMd5() == null) {
continue;
}
if (md5.contains((list.get(i).getMd5()))) {
return i;
}
}
return 0;
}
}
public interface MusicLibsInitInterface {

View File

@ -1,12 +1,8 @@
package com.yutou.nas_music_player.services;
import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaMetadataCompat;
@ -19,15 +15,10 @@ 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.MusicData;
import com.yutou.nas_music_player.tools.AppData;
import com.yutou.nas_music_player.Datas.MusicData;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import static android.media.MediaPlayer.SEEK_PREVIOUS_SYNC;
public class MusicService extends MediaBrowserServiceCompat {
public MediaSessionCompat mediaSession;
@ -78,7 +69,7 @@ public class MusicService extends MediaBrowserServiceCompat {
result.sendResult(mediaItems);
}
public void onSeekTo(long pos) {
public void seekToNotification(long pos) {
MusicData data = MusicContainer.getInstance().getNowPlayData();
MediaMetadataCompat metadataCompat = MusicContainer.getInstance().getMetadataCompat(data);
Notification notification = notificationManager.getNotification(metadataCompat, builderState(pos).build(), getSessionToken());
@ -163,13 +154,9 @@ public class MusicService extends MediaBrowserServiceCompat {
@Override
public void onSeekTo(long pos) {
super.onSeekTo(pos);
System.out.println("SeeTo :"+pos);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
MusicContainer.getInstance().getMediaPlayer().seekTo(pos,SEEK_PREVIOUS_SYNC);
}else{
MusicContainer.getInstance().getMediaPlayer().seekTo((int) pos);
}
MusicService.this.onSeekTo(pos);
System.out.println("接收到跳帧指令~~~");
MusicContainer.getInstance().seekTo(pos);
MusicService.this.seekToNotification(pos);
}
@Override
@ -182,6 +169,8 @@ public class MusicService extends MediaBrowserServiceCompat {
@Override
public void onSkipToPrevious() {
super.onSkipToPrevious();
MusicContainer.getInstance().playPrevious();
updateNotification();
}
@Override
@ -196,7 +185,7 @@ public class MusicService extends MediaBrowserServiceCompat {
@Override
public void onCompletion(MediaPlayer mp) {
onSeekTo(mp.getCurrentPosition());
seekToNotification(mp.getCurrentPosition());
}
}
}

View File

@ -3,9 +3,14 @@ package com.yutou.nas_music_player.tools;
import android.os.Handler;
import android.os.Looper;
import com.yutou.nas_music_player.MyApplication;
import java.io.File;
public class AppData {
public static String download_dir="downloads";
public static String dir= MyApplication.application.getFilesDir() + File.separator;
public static boolean isDebug=true;
public static Handler handler=new Handler(Looper.getMainLooper());
}

View File

@ -0,0 +1,86 @@
package com.yutou.nas_music_player.tools;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import com.kaopiz.kprogresshud.KProgressHUD;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.security.MessageDigest;
public class AppTools {
public static KProgressHUD showLoading(Context context){
return KProgressHUD.create(context)
.setStyle(KProgressHUD.Style.SPIN_INDETERMINATE)
.setDetailsLabel("loading...")
.setCancellable(true)
.setAnimationSpeed(2)
.setDimAmount(0.5f)
.show();
}
public static void saveBitmap(final Bitmap bitmap, final String saveKey){
new Thread(new Runnable() {
@Override
public void run() {
String md5=getMD5(saveKey);
File path=new File(AppData.dir+"img_cache"+File.separator);
if(!path.exists()){
path.mkdirs();
}
File image=new File(AppData.dir+"img_cache"+File.separator+md5);
try {
if(!image.exists()){
image.createNewFile();
}
FileOutputStream outputStream=new FileOutputStream(image);
bitmap.compress(Bitmap.CompressFormat.PNG,100,outputStream);
outputStream.flush();
outputStream.close();
ConfigTools.getPreferences().edit().putString("img_"+md5,image.getAbsolutePath()).apply();
} catch (Exception e) {
e.printStackTrace();
System.out.println(image.getAbsolutePath());
}
}
}).start();
}
public static Bitmap getSaveBitmap(String saveKey){
String path=ConfigTools.getPreferences().getString(getMD5(saveKey),null);
if(path==null){
return null;
}
return BitmapFactory.decodeFile(path);
}
public static String getMD5(String data) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(data.getBytes());
return bytesToHexString(digest.digest());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (byte aSrc : src) {
int v = aSrc & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
}

View File

@ -47,7 +47,7 @@ public class NetworkTool {
private static final String TAG = NetworkTool.class.getName();
private static NetworkTool network;
public boolean isNet = true;
public static String donwloadPath = MyApplication.application.getFilesDir() + File.separator + AppData.download_dir + File.separator;
public static String donwloadPath = AppData.dir + AppData.download_dir + File.separator;
private NetworkTool() {
if (StringUtil.isEmpty(HOME)) {
@ -101,6 +101,10 @@ public class NetworkTool {
HttpURLConnection connection = (HttpURLConnection) new URL(url + "?" + toGetSplice(body)).openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
connection.connect();
if(connection.getResponseCode()!=200){
networkInterface.httpError(new RuntimeException("http code to :"+connection.getResponseCode()));
return;
}
String tmp;
StringBuilder str = new StringBuilder();
while ((tmp = reader.readLine()) != null) {

View File

@ -1,17 +1,23 @@
package com.yutou.nas_music_player.views;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.util.Pair;
import android.annotation.SuppressLint;
import android.app.ActivityOptions;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
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.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
@ -19,14 +25,18 @@ import android.widget.Toast;
import com.alibaba.fastjson.JSON;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.kaopiz.kprogresshud.KProgressHUD;
import com.yutou.nas_music_player.R;
import com.yutou.nas_music_player.containers.MediaBrowserHelper;
import com.yutou.nas_music_player.containers.MusicContainer;
import com.yutou.nas_music_player.containers.MusicData;
import com.yutou.nas_music_player.Datas.MusicData;
import com.yutou.nas_music_player.tools.AppData;
import com.yutou.nas_music_player.tools.AppTools;
import com.yutou.nas_music_player.tools.ConfigTools;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
@ -35,46 +45,94 @@ import jp.wasabeef.glide.transformations.BlurTransformation;
import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
public class MainActivity extends AppCompatActivity {
private ImageButton play, previous, next;
private ImageButton play, previous, next, playModel;
private MediaBrowserHelper browserHelper;
private ImageView album_image, background_image;
private MarqueeTextView title, album, artist;
private TextView positionTime, durationTime, bitRate;
private SeekBar seekBar;
private Handler handler;
private KProgressHUD hud;
@Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
super.onCreate(savedInstanceState);
setBarColor(android.R.color.transparent);
setContentView(R.layout.activity_main);
handler = new Handler();
initView();
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (hud != null) {
hud.dismiss();
hud = null;
}
hud = AppTools.showLoading(MainActivity.this);
handler.post(new Runnable() {
@Override
public void run() {
if (browserHelper.isPlayer()) {
browserHelper.getTransportControls().pause();
} else {
browserHelper.getTransportControls().play();
}
if (hud != null && hud.isShowing()) {
hud.dismiss();
hud = null;
}
}
});
}
});
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (hud != null) {
hud.dismiss();
hud = null;
}
hud = AppTools.showLoading(MainActivity.this);
handler.post(new Runnable() {
@Override
public void run() {
browserHelper.getTransportControls().skipToNext();
if (hud != null && hud.isShowing()) {
hud.dismiss();
hud = null;
}
}
});
}
});
previous.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (hud != null) {
hud.dismiss();
hud = null;
}
hud = AppTools.showLoading(MainActivity.this);
handler.post(new Runnable() {
@Override
public void run() {
browserHelper.getTransportControls().skipToPrevious();
if (hud != null && hud.isShowing()) {
hud.dismiss();
hud = null;
}
}
});
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (browserHelper.getTransportControls() != null)
browserHelper.getTransportControls().seekTo(progress);
}
@Override
@ -84,11 +142,70 @@ public class MainActivity extends AppCompatActivity {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (hud != null) {
hud.dismiss();
hud = null;
}
hud = AppTools.showLoading(MainActivity.this);
handler.post(new Runnable() {
@Override
public void run() {
if (browserHelper.getTransportControls() != null)
browserHelper.getTransportControls().seekTo(MainActivity.this.seekBar.getProgress());
if (hud != null && hud.isShowing()) {
hud.dismiss();
hud = null;
}
}
});
}
});
playModel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int model = (int) playModel.getTag();
if (model == MusicContainer.PLAY_MODEL_LOOP) {
setPlayModelButton(MusicContainer.PLAY_MODEL_RANDOM);
return;
}
setPlayModelButton(model + 1);
}
});
getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() {
float downPosition_x = 0, downPosition_y = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
downPosition_x = event.getRawX();
downPosition_y = event.getRawY();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if (Math.abs(downPosition_x - event.getRawX()) < 500 && downPosition_y - event.getRawY() > 500) {
Pair<View, String> pImage = Pair.create((View) album_image, "album_image");
Pair<View, String> pPrevious = Pair.create((View) previous, "previous");
Pair<View, String> pPlay = Pair.create((View) play, "play");
Pair<View, String> pNext = Pair.create((View) next, "next");
Pair<View, String> pTitle = Pair.create((View) title, "title");
Pair<View, String> pArtist = Pair.create((View) artist, "artist");
//ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this,list);
Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, pImage, pPrevious, pPlay, pNext, pTitle, pArtist).toBundle();
Intent intent = new Intent(
MainActivity.this, PlayLibsActivity.class);
if (bundle != null) {
startActivity(intent, bundle);
} else {
startActivity(intent);
}
}
}
return false;
}
});
browserHelper = new MediaBrowserHelper(this);
browserHelper.regPlayListener(new PlayListener());
initData();
}
@ -119,11 +236,13 @@ public class MainActivity extends AppCompatActivity {
artist.setText(data.getArtist());
album.setText(data.getAlbum());
bitRate.setText(data.getBitRate() + "kbps / " + data.getSampleRate() + "hz");
seekBar.setMax((int) data.getDurationAsDouble());
seekBar.setMax((int) (data.getDurationAsDouble() * 1000));
int minutes = (int) (data.getDurationAsDouble() / 60);
int seconds = (int) (data.getDurationAsDouble() % 60);
durationTime.setText(minutes + ":" + seconds);
durationTime.setText(String.format(Locale.CHINA, "%02d", minutes) + ":"
+ String.format(Locale.CHINA, "%02d", seconds));
int model = ConfigTools.getPreferences().getInt("playModel", MusicContainer.PLAY_MODEL_RANDOM);
setPlayModelButton(model);
if (data.getImg() != null) {
setImage(data);
} else {
@ -145,6 +264,26 @@ public class MainActivity extends AppCompatActivity {
}
private void setPlayModelButton(int model) {
playModel.setTag(model);
MusicContainer.getInstance().setPlayModel(model);
switch (model) {
case MusicContainer.PLAY_MODEL_RANDOM:
playModel.setImageResource(R.drawable.ic_play_random);
break;
case MusicContainer.PLAY_MODEL_ORDER:
playModel.setImageResource(R.drawable.ic_play_list);
break;
case MusicContainer.PLAY_MODEL_ONE_LOOP:
playModel.setImageResource(R.drawable.ic_play_one_loop);
break;
case MusicContainer.PLAY_MODEL_LOOP:
playModel.setImageResource(R.drawable.ic_play_loop);
break;
}
ConfigTools.getPreferences().edit().putInt("playModel", model).apply();
}
private void setImage(MusicData data) {
album_image.setImageBitmap(data.getImg());
background_image.setImageBitmap(data.getImg());
@ -170,6 +309,7 @@ public class MainActivity extends AppCompatActivity {
positionTime = findViewById(R.id.positionTime);
durationTime = findViewById(R.id.durationTime);
seekBar = findViewById(R.id.seekBar);
playModel = findViewById(R.id.playModel);
}
public void setBarColor(int color) {
@ -182,13 +322,14 @@ public class MainActivity extends AppCompatActivity {
@Override
public void onPlaybackStateChanged(PlaybackStateCompat state) {
super.onPlaybackStateChanged(state);
System.out.println("播放状态变化:" + state.getState());
System.out.println("播放状态变化:" + state.getPosition() + " " + seekBar.getMax());
if (state.getState() == PlaybackStateCompat.STATE_PLAYING) {
int duration = (int) (state.getPosition() / 1000);
int minutes = duration / 60;
int seconds = duration % 60;
positionTime.setText(minutes + ":" + seconds);
seekBar.setProgress((int) (state.getPosition() / 1000));
positionTime.setText(String.format(Locale.CHINA, "%02d", minutes) + ":"
+ String.format(Locale.CHINA, "%02d", seconds));
seekBar.setProgress((int) (state.getPosition()));
play.setImageResource(android.R.drawable.ic_media_pause);
} else {
play.setImageResource(android.R.drawable.ic_media_play);
@ -203,12 +344,11 @@ public class MainActivity extends AppCompatActivity {
try {
System.out.println("播放歌曲变换:" + metadata.getString("md5"));
md5 = metadata.getString("md5");
}catch (Exception e){
e.printStackTrace();
} catch (Exception ignored) {
}
if (md5 != null) {
setPlayData(MusicContainer.getLibs().findMusic(md5));
setPlayData(MusicContainer.getLibs().findMusic(md5, MusicContainer.getInstance().getPlayList()));
}
}

View File

@ -23,7 +23,7 @@ public class OpenActivity extends AppCompatActivity {
public void init() {
Intent intent=new Intent(OpenActivity.this,MainActivity.class);
startActivity(intent);
finish();
OpenActivity.this.finish();
}
});
}

View File

@ -0,0 +1,145 @@
package com.yutou.nas_music_player.views;
import android.annotation.SuppressLint;
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.Window;
import android.widget.ImageButton;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.yutou.nas_music_player.Datas.MusicData;
import com.yutou.nas_music_player.R;
import com.yutou.nas_music_player.containers.MediaBrowserHelper;
import com.yutou.nas_music_player.containers.MusicContainer;
import com.yutou.nas_music_player.tools.AppData;
import com.yutou.nas_music_player.tools.ConfigTools;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import cc.ibooker.ztextviewlib.MarqueeTextView;
import jp.wasabeef.glide.transformations.BlurTransformation;
import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
public class PlayLibsActivity extends AppCompatActivity {
private ImageButton play, previous, next;
private MediaBrowserHelper browserHelper;
private ImageView album_image;
private MarqueeTextView title, artist;
private PlayListener playListener;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play_list);
initView();
setPlayData(MusicContainer.getInstance().getNowPlayData());
browserHelper = new MediaBrowserHelper(this);
playListener=new PlayListener();
browserHelper.regPlayListener(playListener);
}
private void initView() {
play = findViewById(R.id.play);
next = findViewById(R.id.next);
previous = findViewById(R.id.previous);
album_image = findViewById(R.id.album_image);
title = findViewById(R.id.title);
artist = findViewById(R.id.artist);
}
private void setImage(MusicData data) {
album_image.setImageBitmap(data.getImg());
Glide.with(this).load(data.getImg())
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(25, 3)))
.into(album_image);
}
@SuppressLint("SetTextI18n")
private void setPlayData(final MusicData data) {
System.out.println("设置歌曲");
System.out.println(data);
if (data == null)
return;
title.setText(data.getTitle());
artist.setText(data.getArtist());
if (data.getImg() != null) {
setImage(data);
} else {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (data.getImg() != null) {
AppData.handler.post(new Runnable() {
@Override
public void run() {
setImage(data);
}
});
cancel();
}
}
}, 0, 100);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
browserHelper=null;
finish();
}
private class PlayListener extends MediaControllerCompat.Callback {
@SuppressLint("SetTextI18n")
@Override
public void onPlaybackStateChanged(PlaybackStateCompat state) {
super.onPlaybackStateChanged(state);
if (state.getState() == PlaybackStateCompat.STATE_PLAYING) {
play.setImageResource(android.R.drawable.ic_media_pause);
} else {
play.setImageResource(android.R.drawable.ic_media_play);
}
}
@Override
public void onMetadataChanged(MediaMetadataCompat metadata) {
super.onMetadataChanged(metadata);
String md5 = null;
try {
System.out.println("播放歌曲变换:" + metadata.getString("md5"));
md5 = metadata.getString("md5");
} catch (Exception ignored) {
}
if (md5 != null) {
setPlayData(MusicContainer.getLibs().findMusic(md5, MusicContainer.getInstance().getPlayList()));
}
}
@Override
public void onSessionDestroyed() {
super.onSessionDestroyed();
System.out.println("连接被销毁");
}
@Override
public void onQueueChanged(List<MediaSessionCompat.QueueItem> queue) {
super.onQueueChanged(queue);
System.out.println("不知道是啥变换了");
}
public void setImage() {
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -34,6 +34,7 @@
android:layout_marginTop="150dp"
android:contentDescription="专辑图"
android:src="@drawable/ic_launcher_foreground"
android:transitionName="album_image"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@ -43,13 +44,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="26dp"
android:shadowColor="@color/textColorGray"
android:shadowColor="@color/colorBlack"
android:shadowDx="5"
android:shadowDy="5"
android:shadowRadius="1"
android:text="title"
android:textColor="@color/musicTitle"
android:textSize="24sp"
android:transitionName="title"
app:layout_constraintBottom_toTopOf="@+id/album_image"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
@ -76,6 +78,10 @@
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:shadowColor="@color/colorBlack"
android:shadowDx="5"
android:shadowDy="5"
android:shadowRadius="1"
android:text="00:00"
android:textColor="@color/textColorWhite" />
@ -85,8 +91,12 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:textColor="@color/textColorWhite"
android:text="TextView" />
android:shadowColor="@color/colorBlack"
android:shadowDx="5"
android:shadowDy="5"
android:shadowRadius="1"
android:text="TextView"
android:textColor="@color/textColorWhite" />
<TextView
android:id="@+id/durationTime"
@ -95,6 +105,10 @@
android:layout_marginEnd="10dp"
android:layout_weight="1"
android:gravity="end"
android:shadowColor="@color/colorBlack"
android:shadowDx="5"
android:shadowDy="5"
android:shadowRadius="1"
android:text="00:00"
android:textColor="@color/textColorGray" />
</LinearLayout>
@ -125,20 +139,30 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageButton
android:id="@+id/playModel"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginEnd="30dp"
android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_play_random" />
<ImageButton
android:id="@+id/previous"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="30dp"
android:src="@android:drawable/ic_media_previous" />
android:src="@android:drawable/ic_media_previous"
android:transitionName="previous" />
<ImageButton
android:id="@+id/play"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@android:drawable/ic_media_play" />
android:src="@android:drawable/ic_media_play"
android:transitionName="play" />
<ImageButton
android:id="@+id/next"
@ -146,7 +170,9 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="30dp"
android:src="@android:drawable/ic_media_next" />
android:layout_marginEnd="80dp"
android:src="@android:drawable/ic_media_next"
android:transitionName="next" />
</LinearLayout>
<LinearLayout
@ -163,6 +189,9 @@
android:id="@+id/album"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:shadowColor="@color/colorBlack"
android:shadowDx="5"
android:shadowDy="5"
android:shadowRadius="1"
android:text="album"
android:textColor="@color/textColorWhite"
@ -172,9 +201,14 @@
android:id="@+id/artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:shadowColor="@color/colorBlack"
android:shadowDx="5"
android:shadowDy="5"
android:shadowRadius="1"
android:text="artist"
android:textColor="@color/textColorWhite"
android:textSize="20sp" />
android:textSize="20sp"
android:transitionName="artist" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="@+id/include"
layout="@layout/layout_play"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.ogaclejapan.smarttablayout.SmartTabLayout
android:id="@+id/viewpagertab"
android:layout_width="match_parent"
android:layout_height="48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/include"
app:stl_clickable="true"
app:stl_defaultTabBackground="?attr/selectableItemBackground"
app:stl_defaultTabTextAllCaps="true"
app:stl_defaultTabTextColor="#FC000000"
app:stl_defaultTabTextHorizontalPadding="16dp"
app:stl_defaultTabTextMinWidth="0dp"
app:stl_defaultTabTextSize="12sp"
app:stl_distributeEvenly="false"
app:stl_dividerColor="#4D000000"
app:stl_dividerThickness="1dp"
app:stl_drawDecorationAfterTab="false"
app:stl_indicatorAlwaysInCenter="false"
app:stl_indicatorColor="#40C4FF"
app:stl_indicatorCornerRadius="2dp"
app:stl_indicatorGravity="bottom"
app:stl_indicatorInFront="false"
app:stl_indicatorInterpolation="smart"
app:stl_indicatorThickness="4dp"
app:stl_indicatorWidth="auto"
app:stl_indicatorWithoutPadding="false"
app:stl_overlineColor="#4D000000"
app:stl_overlineThickness="0dp"
app:stl_titleOffset="24dp"
app:stl_underlineColor="#4D000000"
app:stl_underlineThickness="1dp" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_below="@id/viewpagertab"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/viewpagertab" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/album_image"
android:layout_width="64dp"
android:layout_height="64dp"
android:transitionName="album_image"
app:srcCompat="@mipmap/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="120dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<cc.ibooker.ztextviewlib.MarqueeTextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:shadowColor="@color/textColorGray"
android:shadowDx="5"
android:shadowDy="5"
android:shadowRadius="1"
android:text="TextView"
android:textColor="@color/colorBlack"
android:transitionName="title" />
<cc.ibooker.ztextviewlib.MarqueeTextView
android:id="@+id/artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:shadowColor="@color/textColorGray"
android:shadowDx="5"
android:shadowDy="5"
android:shadowRadius="1"
android:text="TextView"
android:textColor="@color/colorBlack"
android:transitionName="artist" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:gravity="end"
android:orientation="horizontal">
<ImageButton
android:id="@+id/previous"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:scaleType="fitCenter"
android:transitionName="previous"
app:srcCompat="@android:drawable/ic_media_previous" />
<ImageButton
android:id="@+id/play"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:scaleType="fitCenter"
android:transitionName="play"
app:srcCompat="@android:drawable/ic_media_play" />
<ImageButton
android:id="@+id/next"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginEnd="10dp"
android:scaleType="fitCenter"
android:transitionName="next"
app:srcCompat="@android:drawable/ic_media_next" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -5,7 +5,7 @@
<color name="colorAccent">#03DAC5</color>
<color name="colorBlack">#000000</color>
<color name="musicTitle">#000000</color>
<color name="musicTitle">#FFFFFF</color>
<color name="musicArtist">#000000</color>
<color name="textColorGray">#DEDEDE</color>
<color name="textColorWhite">#FFFFFF</color>