From 6c7b150b134f4f8433b10ef3b070191e086f9f1b Mon Sep 17 00:00:00 2001 From: jsyjst Date: Fri, 22 Mar 2019 20:34:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=AD=8C=E8=AF=8D=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/codeStyles/Project.xml | 29 +++ .idea/misc.xml | 17 +- .idea/modules.xml | 1 - app/build.gradle | 4 + .../musicplayer/configure/BaseUri.java | 1 + .../musicplayer/contract/IPlayContract.java | 13 +- .../example/musicplayer/entiy/LrcBean.java | 49 +++++ .../musicplayer/https/api/SearchApi.java | 8 + .../musicplayer/https/api/SingerImgApi.java | 4 + .../example/musicplayer/model/PlayModel.java | 85 ++++++-- .../musicplayer/presenter/PlayPresenter.java | 45 +++- .../example/musicplayer/util/FileHelper.java | 1 - .../com/example/musicplayer/util/LrcUtil.java | 90 ++++++++ .../example/musicplayer/util/MediaUtil.java | 4 + .../musicplayer/view/MainFragment.java | 2 +- .../musicplayer/view/PlayActivity.java | 191 ++++++++++++++--- .../musicplayer/view/WelcomeActivity.java | 2 +- .../example/musicplayer/widget/LrcView.java | 194 ++++++++++++++++++ app/src/main/res/layout/activity_play.xml | 14 +- .../main/res/layout/dialog_delete_photo.xml | 1 + .../res/layout/fragment_search_content.xml | 2 - app/src/main/res/values/attrs.xml | 13 +- app/src/main/res/values/strings.xml | 4 +- build.gradle | 1 + 24 files changed, 723 insertions(+), 52 deletions(-) create mode 100644 .idea/codeStyles/Project.xml create mode 100644 app/src/main/java/com/example/musicplayer/entiy/LrcBean.java create mode 100644 app/src/main/java/com/example/musicplayer/util/LrcUtil.java create mode 100644 app/src/main/java/com/example/musicplayer/widget/LrcView.java diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..30aa626 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index f342a0b..92413e2 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,26 +5,37 @@ - + diff --git a/.idea/modules.xml b/.idea/modules.xml index 1ed77b7..67b9978 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,6 @@ - diff --git a/app/build.gradle b/app/build.gradle index 33c8545..703d2b0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,6 +16,10 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { + sourceCompatibility = '1.8' + targetCompatibility = '1.8' + } } allprojects { repositories { diff --git a/app/src/main/java/com/example/musicplayer/configure/BaseUri.java b/app/src/main/java/com/example/musicplayer/configure/BaseUri.java index 125bbf3..4e7e512 100644 --- a/app/src/main/java/com/example/musicplayer/configure/BaseUri.java +++ b/app/src/main/java/com/example/musicplayer/configure/BaseUri.java @@ -12,6 +12,7 @@ public class BaseUri { public static String QQ_URL="https://api.bzqll.com/music/tencent/"; public static String STORAGE_IMG_FILE=MyApplication.getContext().getExternalFilesDir("") + "/yuanmusic/img/"; + public static String STORAGE_LRC_FILE=MyApplication.getContext().getExternalFilesDir("") + "/yuanmusic/lrc/"; public static final String BASE_API_URL_LASTFM = "http://ws.audioscrobbler.com/2.0/"; } diff --git a/app/src/main/java/com/example/musicplayer/contract/IPlayContract.java b/app/src/main/java/com/example/musicplayer/contract/IPlayContract.java index 335921b..f88d82a 100644 --- a/app/src/main/java/com/example/musicplayer/contract/IPlayContract.java +++ b/app/src/main/java/com/example/musicplayer/contract/IPlayContract.java @@ -1,15 +1,19 @@ package com.example.musicplayer.contract; import com.example.musicplayer.entiy.Love; +import com.example.musicplayer.entiy.SeachSong; import com.example.musicplayer.entiy.Song; +import java.util.List; + /** * Created by 残渊 on 2018/10/26. */ public interface IPlayContract { interface Model{ - void getSingerImg(String singer);//网络请求获得歌手uri + void getSingerImg(String singer,String song,long duration);//网络请求获得歌手uri + void getLrc(String song,long duration);//网络获取歌词 void queryLove(String songId);//查询我喜欢的数据库中有没这首歌 void saveToLove(Song song); //添加到我喜欢的表 void deleteFromLove(String songId); //从我喜欢的表中移除 @@ -23,11 +27,16 @@ public interface IPlayContract { void showLoveAnim(); //喜欢的动画 void saveToLoveSuccess();//保存到我喜欢数据库成功 void sendUpdateCollection(); //发送广播更新收藏列表 + void showLrcMessage(String lrc); //显示歌词获取信息 } interface Presenter{ - void getSingerImg(String singer); + void getSingerImg(String singer,String song,long duration); + void getLrc(String song,long duration); void getSingerImgSuccess(String ImgUrl); //成功获取图片 + void getSongLrcSuccess(List dataBeans,long duration); //成功获取歌词 + void getSongLrcFail(); //获取歌词失败 void getSingerImgFail(); //请求失败 + void showNetWorkError();//网络超时 void queryLove(String songId);//查询我喜欢的数据库中有没这首歌 void saveToLove(Song song); //添加到我喜欢的表 void deleteFromLove(String songId); //从我喜欢的表中移除 diff --git a/app/src/main/java/com/example/musicplayer/entiy/LrcBean.java b/app/src/main/java/com/example/musicplayer/entiy/LrcBean.java new file mode 100644 index 0000000..198fe95 --- /dev/null +++ b/app/src/main/java/com/example/musicplayer/entiy/LrcBean.java @@ -0,0 +1,49 @@ +package com.example.musicplayer.entiy; + +/** + *
+ *     author : 残渊
+ *     time   : 2019/03/18
+ *     desc   : 歌词实体类
+ * 
+ */ + +public class LrcBean { + private String lrc; + private long start; + private long end; + + public LrcBean() { + } + + public LrcBean(String text, long start, long end) { + this.lrc = text; + this.start = start; + this.end = end; + } + + public String getLrc() { + return lrc; + } + + public void setLrc(String lrc) { + this.lrc = lrc; + } + + public long getStart() { + return start; + } + + public void setStart(long start) { + this.start = start; + } + + public long getEnd() { + return end; + } + + public void setEnd(long end) { + this.end = end; + } +} + diff --git a/app/src/main/java/com/example/musicplayer/https/api/SearchApi.java b/app/src/main/java/com/example/musicplayer/https/api/SearchApi.java index d16eeec..9a4920a 100644 --- a/app/src/main/java/com/example/musicplayer/https/api/SearchApi.java +++ b/app/src/main/java/com/example/musicplayer/https/api/SearchApi.java @@ -21,4 +21,12 @@ public interface SearchApi { @GET("search?key=579621905&type=album&limit=30") Observable searchAlbum(@Query("s") String seek,@Query("offset")int offset); + + /** + * 搜索歌词 + * @param seek + * @return + */ + @GET("search?key=579621905&type=song&limit=10&offset=0") + Observable search(@Query("s") String seek); } diff --git a/app/src/main/java/com/example/musicplayer/https/api/SingerImgApi.java b/app/src/main/java/com/example/musicplayer/https/api/SingerImgApi.java index 44c171c..553a238 100644 --- a/app/src/main/java/com/example/musicplayer/https/api/SingerImgApi.java +++ b/app/src/main/java/com/example/musicplayer/https/api/SingerImgApi.java @@ -1,11 +1,14 @@ package com.example.musicplayer.https.api; +import com.example.musicplayer.entiy.SeachSong; import com.example.musicplayer.entiy.SingerImg; import io.reactivex.Observable; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; +import retrofit2.http.GET; import retrofit2.http.POST; +import retrofit2.http.Query; /** * Created by 残渊 on 2018/10/26. @@ -15,4 +18,5 @@ public interface SingerImgApi { @POST("web?csrf_token=&type=100") @FormUrlEncoded Observable getSingerImg(@Field("s")String singer); + } diff --git a/app/src/main/java/com/example/musicplayer/model/PlayModel.java b/app/src/main/java/com/example/musicplayer/model/PlayModel.java index fe33e12..bc52963 100644 --- a/app/src/main/java/com/example/musicplayer/model/PlayModel.java +++ b/app/src/main/java/com/example/musicplayer/model/PlayModel.java @@ -5,6 +5,7 @@ import android.util.Log; import com.example.musicplayer.configure.Constant; import com.example.musicplayer.contract.IPlayContract; import com.example.musicplayer.entiy.Love; +import com.example.musicplayer.entiy.SeachSong; import com.example.musicplayer.entiy.SingerImg; import com.example.musicplayer.entiy.Song; import com.example.musicplayer.https.NetWork; @@ -15,13 +16,19 @@ import org.litepal.crud.callback.FindMultiCallback; import org.litepal.crud.callback.SaveCallback; import org.litepal.crud.callback.UpdateOrDeleteCallback; +import java.net.UnknownHostException; import java.util.List; +import io.reactivex.ObservableSource; import io.reactivex.Observer; +import io.reactivex.Scheduler; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; +import static com.example.musicplayer.view.AlbumSongFragment.ALBUM_SONG; /** @@ -38,31 +45,85 @@ public class PlayModel implements IPlayContract.Model { } @Override - public void getSingerImg(String singer) { + public void getSingerImg(final String singer, final String song, final long duration) { NetWork.getSingerImgApi() .getSingerImg(singer) .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Observer() { + .doOnNext(new Consumer() { + @Override + public void accept(SingerImg singerImg) throws Exception { + mPresenter.getSingerImgSuccess(singerImg.getResult().getArtists().get(0).getImg1v1Url()); + } + }) + .observeOn(Schedulers.io()) + .flatMap(new Function>() { + @Override + public ObservableSource apply(SingerImg singerImg) throws Exception { + return NetWork.getSearchApi().search(song); + } + }) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { - RxApiManager.get().add(Constant.LOCAL_IMG,d); + RxApiManager.get().add(Constant.LOCAL_IMG, d); } @Override - public void onNext(SingerImg value) { - if(value.getCode()==200) { - mPresenter.getSingerImgSuccess(value.getResult().getArtists().get(0).getImg1v1Url()); - Log.d(TAG, "onNext: "+value.getResult().getArtists().get(0).getImg1v1Url()); - }else{ - Log.d(TAG, "onNext: "+value.getCode()); - mPresenter.getSingerImgFail(); + public void onNext(SeachSong value) { + if (value.getCode() == 200) { + mPresenter.getSongLrcSuccess(value.getData(),duration); + } else { + mPresenter.getSongLrcFail(); + } + } + + @Override + public void onError(Throwable e) { + Log.d(TAG, "onError: " + e.toString()); + if (e instanceof UnknownHostException) { + mPresenter.getSongLrcFail(); + } else { + mPresenter.getSongLrcFail(); + } + } + + @Override + public void onComplete() { + + } + }); + + } + + @Override + public void getLrc(String song, long duration) { + NetWork.getSearchApi().search(song) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { + RxApiManager.get().add(Constant.LOCAL_IMG, d); + } + + @Override + public void onNext(SeachSong value) { + if (value.getCode() == 200) { + mPresenter.getSongLrcSuccess(value.getData(),duration); + } else { + mPresenter.getSongLrcFail(); } } @Override public void onError(Throwable e) { - e.printStackTrace(); - mPresenter.getSingerImgFail(); + Log.d(TAG, "onError: " + e.toString()); + if (e instanceof UnknownHostException) { + mPresenter.getSongLrcFail(); + } else { + mPresenter.getSongLrcFail(); + } } @Override diff --git a/app/src/main/java/com/example/musicplayer/presenter/PlayPresenter.java b/app/src/main/java/com/example/musicplayer/presenter/PlayPresenter.java index e593192..1f82c9a 100644 --- a/app/src/main/java/com/example/musicplayer/presenter/PlayPresenter.java +++ b/app/src/main/java/com/example/musicplayer/presenter/PlayPresenter.java @@ -1,25 +1,37 @@ package com.example.musicplayer.presenter; +import android.support.design.widget.TabLayout; +import android.util.Log; + import com.example.musicplayer.base.BasePresenter; import com.example.musicplayer.contract.IPlayContract; +import com.example.musicplayer.entiy.SeachSong; import com.example.musicplayer.entiy.Song; import com.example.musicplayer.model.PlayModel; +import com.example.musicplayer.util.MediaUtil; + +import java.util.List; /** * Created by 残渊 on 2018/10/26. */ public class PlayPresenter extends BasePresenter implements IPlayContract.Presenter { + private static final String TAG = "PlayPresenter"; private PlayModel mModel; public PlayPresenter(){ mModel=new PlayModel(this); } + @Override + public void getSingerImg(String singer, String song,long duration) { + mModel.getSingerImg(singer,song,duration); + } @Override - public void getSingerImg(String singer) { - mModel.getSingerImg(singer); + public void getLrc(String song, long duration) { + mModel.getLrc(song,duration); } @Override @@ -29,6 +41,30 @@ public class PlayPresenter extends BasePresenter implements } } + @Override + public void getSongLrcSuccess(List dataBeans,long duration) { + if(isAttachView()){ + Log.d(TAG, "getSongLrcSuccess: duration="+MediaUtil.formatLongToThree(duration)); + boolean isLrc =false; + for(SeachSong.DataBean dataBean : dataBeans){ + if(dataBean.getTime() == MediaUtil.formatLongToThree(duration)){ + isLrc = true; + getMvpView().showLrcMessage(dataBean.getLrc()); + break; + } + } + Log.d(TAG, "getSongLrcSuccess: "+isLrc); + if(!isLrc) getMvpView().showLrcMessage(dataBeans.get(0).getLrc()); + } + } + + @Override + public void getSongLrcFail() { + if(isAttachView()){ + getMvpView().showLrcMessage(null); + } + } + @Override public void getSingerImgFail() { if(isAttachView()){ @@ -36,6 +72,11 @@ public class PlayPresenter extends BasePresenter implements } } + @Override + public void showNetWorkError() { + + } + @Override public void queryLove(String songId) { mModel.queryLove(songId); diff --git a/app/src/main/java/com/example/musicplayer/util/FileHelper.java b/app/src/main/java/com/example/musicplayer/util/FileHelper.java index fb849c8..764f9eb 100644 --- a/app/src/main/java/com/example/musicplayer/util/FileHelper.java +++ b/app/src/main/java/com/example/musicplayer/util/FileHelper.java @@ -40,7 +40,6 @@ public class FileHelper { try { File file = new File(MyApplication.getContext().getExternalFilesDir("yuanmusic").getAbsolutePath()); if (!file.exists()) { - Log.d("Login", "------------------" + MyApplication.getContext().getExternalFilesDir("")); file.mkdirs(); } //写对象流的对象 diff --git a/app/src/main/java/com/example/musicplayer/util/LrcUtil.java b/app/src/main/java/com/example/musicplayer/util/LrcUtil.java new file mode 100644 index 0000000..18ce3b4 --- /dev/null +++ b/app/src/main/java/com/example/musicplayer/util/LrcUtil.java @@ -0,0 +1,90 @@ +package com.example.musicplayer.util; + +import com.example.musicplayer.entiy.LrcBean; + +import java.util.ArrayList; +import java.util.List; + +/** + *
+ *     author : 残渊
+ *     time   : 2019/03/18
+ *     desc   : 歌词工具类
+ * 
+ */ + +public class LrcUtil { + /** + * 传入的参数为标准歌词字符串 + * + * @param lrcStr + * @return + */ + public static List parseStr2List(String lrcStr) { + List list = new ArrayList<>(); + String lrcText = lrcStr.replaceAll(":", ":") + .replaceAll("'", "'") + .replaceAll(" ", "\n") + .replaceAll(".", ".") + .replaceAll(" ", " ") + .replaceAll("-", "-") + .replaceAll(" ", "\r") + .replaceAll("'", "'"); + String[] split = lrcText.split("\n"); + for (int i = 4; i < split.length; i++) { + String lrc = split[i]; + if (lrc.contains(".")) { + String min = lrc.substring(lrc.indexOf("[") + 1, lrc.indexOf("[") + 3); + String seconds = lrc.substring(lrc.indexOf(":") + 1, lrc.indexOf(":") + 3); + String mills = lrc.substring(lrc.indexOf(".") + 1, lrc.indexOf(".") + 3); + long startTime = Long.valueOf(min) * 60 * 1000 + Long.valueOf(seconds) * 1000 + Long.valueOf(mills) * 10; + String text = lrc.substring(lrc.indexOf("]") + 1); + if (text.equals("") || text == null) continue; + if (i == 5) { + int first = text.indexOf("("); + int second = text.indexOf("(", first + 1); + String textFront = null; + String textBehind = null; + boolean isTwo = true; + boolean isOne = true; + try { + textFront = text.substring(0, first); + }catch (StringIndexOutOfBoundsException e){ + isOne = false; + } + try { + textBehind = text.substring(first + 1, second); + } catch (StringIndexOutOfBoundsException e) { + isTwo = false; + } + LrcBean lrcBean1 = new LrcBean(); + lrcBean1.setStart(startTime); + if(isOne) { + lrcBean1.setLrc(textFront); + } else { + lrcBean1.setLrc(text); + } + list.add(lrcBean1); + if (isTwo) { + LrcBean lrcBean2 = new LrcBean(); + lrcBean2.setStart(startTime); + lrcBean2.setLrc(textBehind); + list.add(lrcBean2); + } + } else { + LrcBean lrcBean = new LrcBean(); + lrcBean.setStart(startTime); + lrcBean.setLrc(text); + list.add(lrcBean); + } + if (list.size() > 1) { + list.get(list.size() - 2).setEnd(startTime); + } + if (i == split.length - 1) { + list.get(list.size() - 1).setEnd(startTime + 100000); + } + } + } + return list; + } +} diff --git a/app/src/main/java/com/example/musicplayer/util/MediaUtil.java b/app/src/main/java/com/example/musicplayer/util/MediaUtil.java index b23a96c..4a78e17 100644 --- a/app/src/main/java/com/example/musicplayer/util/MediaUtil.java +++ b/app/src/main/java/com/example/musicplayer/util/MediaUtil.java @@ -49,6 +49,10 @@ public class MediaUtil { return singer.trim(); } + public static long formatLongToThree(long duration){ + return (duration/1000); + } + } diff --git a/app/src/main/java/com/example/musicplayer/view/MainFragment.java b/app/src/main/java/com/example/musicplayer/view/MainFragment.java index 996b505..a77fa99 100644 --- a/app/src/main/java/com/example/musicplayer/view/MainFragment.java +++ b/app/src/main/java/com/example/musicplayer/view/MainFragment.java @@ -91,7 +91,7 @@ public class MainFragment extends Fragment { mAlbumCollectionList = new ArrayList<>(); AlbumCollection albumCollection = new AlbumCollection(); albumCollection.setAlbumName("我喜欢"); - albumCollection.setSingerName("袁健策"); + albumCollection.setSingerName("残渊"); mLoveAlbumList.add(albumCollection); mAlbumCollectionList.add(mLoveAlbumList); mAlbumCollectionList.add(orderCollection(LitePal.findAll(AlbumCollection.class))); diff --git a/app/src/main/java/com/example/musicplayer/view/PlayActivity.java b/app/src/main/java/com/example/musicplayer/view/PlayActivity.java index 701fdb1..200b46b 100644 --- a/app/src/main/java/com/example/musicplayer/view/PlayActivity.java +++ b/app/src/main/java/com/example/musicplayer/view/PlayActivity.java @@ -55,9 +55,21 @@ import com.example.musicplayer.util.MediaUtil; import com.example.musicplayer.util.RxApiManager; import com.example.musicplayer.widget.BackgroundAnimationRelativeLayout; import com.example.musicplayer.widget.DiscView; - -import org.litepal.LitePal; - +import com.example.musicplayer.widget.LrcView; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; import java.util.List; /** @@ -92,6 +104,8 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { private TextView mCurrentTimeTv; private TextView mDurationTimeTv; + private String mLrc = null; + private Button mLoveBtn; private boolean isLove;//是否已经在我喜欢的列表中 @@ -102,6 +116,7 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { private Button mGetImgAndLrcBtn;//获取封面和歌词 private BackgroundAnimationRelativeLayout mRootLayout; private List mLocalSong;//用来判断是否有本地照片 + private LrcView mLrcView; //歌词自定义View //服务 private Thread mSeekBarThread; @@ -124,14 +139,14 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { } } else { setLocalImg(mSong.getSinger()); - mSeekBar.setSecondaryProgress((int)mSong.getDuration()); + mSeekBar.setSecondaryProgress((int) mSong.getDuration()); } mDurationTimeTv.setText(MediaUtil.formatTime(mSong.getDuration())); //缓存进度条 mPlayStatusBinder.getMediaPlayer().setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { @Override public void onBufferingUpdate(MediaPlayer mp, int percent) { - mSeekBar.setSecondaryProgress(percent*mSeekBar.getProgress()); + mSeekBar.setSecondaryProgress(percent * mSeekBar.getProgress()); } }); } @@ -192,6 +207,7 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { mDiscImg = findViewById(R.id.iv_disc_background); mLoveBtn = findViewById(R.id.btn_love); mOrderBtn = findViewById(R.id.btn_order); + mLrcView = findViewById(R.id.lrcView); //界面填充 mSong = FileHelper.getSong(); @@ -288,7 +304,6 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { @Override public void onStopTrackingTouch(SeekBar seekBar) { if (mPlayStatusBinder.isPlaying()) { - Log.d(TAG, "onStopTrackingTouch: isPlay"); mMediaPlayer = mPlayStatusBinder.getMediaPlayer(); mMediaPlayer.seekTo(seekBar.getProgress()); startUpdateSeekBarProgress(); @@ -304,7 +319,7 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { mOrderBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - CommonUtil.showToast(PlayActivity.this,"抱歉,目前只支持顺序播放,其他功能还在开发中"); + CommonUtil.showToast(PlayActivity.this, "抱歉,目前只支持顺序播放,其他功能还在开发中"); } }); @@ -332,7 +347,6 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { mPlayBtn.setSelected(true); startUpdateSeekBarProgress(); } else { - Log.d(TAG, "onClick: --------play"); if (isOnline) { mPlayStatusBinder.playOnline(); } else { @@ -370,16 +384,35 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { @Override public void onClick(View v) { showLoveAnim(); - if(isLove){ + if (isLove) { mLoveBtn.setSelected(false); mPresenter.deleteFromLove(FileHelper.getSong().getSongId()); - }else { + } else { mLoveBtn.setSelected(true); mPresenter.saveToLove(FileHelper.getSong()); } isLove = !isLove; } }); + + //唱碟点击效果 + mDisc.setOnClickListener(v -> { + if (!isOnline) { + if (getLrcFromLocal().equals("")) { + mPresenter.getLrc(getSongName(), mSong.getDuration()); + } + showLrc(getLrcFromLocal()); + } else { + mPresenter.getLrc(getSongName(), mSong.getDuration()); + } + } + ); + //歌词点击效果 + mLrcView.setOnClickListener(v -> { + mLrcView.setVisibility(View.GONE); + mDisc.setVisibility(View.VISIBLE); + }); + } @Override @@ -394,15 +427,19 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { } + private String getSongName() { + Song song = FileHelper.getSong(); + return song.getSongName().trim(); + } + @Override public void getSingerAndLrc() { mGetImgAndLrcBtn.setText("正在获取..."); - mPresenter.getSingerImg(getSingerName()); + mPresenter.getSingerImg(getSingerName(), getSongName(), mSong.getDuration()); } @Override public void setSingerImg(String ImgUrl) { - Log.d(TAG, "setSingerImg: success"); SimpleTarget target = new SimpleTarget(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) { @Override public void onResourceReady(@Nullable Drawable resource, Transition transition) { @@ -411,11 +448,10 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { if (!isOnline) { //保存图片到本地 FileHelper.saveImgToNative(PlayActivity.this, mImgBmp, getSingerName()); - CommonUtil.showToast(PlayActivity.this, "获取封面歌词成功"); //将封面地址放到数据库中 - LocalSong localSong =new LocalSong(); + LocalSong localSong = new LocalSong(); localSong.setPic(BaseUri.STORAGE_IMG_FILE + FileHelper.getSong().getSinger() + ".jpg"); - localSong.updateAll("songId=?",FileHelper.getSong().getSongId()); + localSong.updateAll("songId=?", FileHelper.getSong().getSongId()); } try2UpdateMusicPicBackground(mImgBmp); @@ -438,13 +474,13 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { @Override public void showLove(final boolean love) { - isLove =love; + isLove = love; runOnUiThread(new Runnable() { @Override public void run() { - if(love){ + if (love) { mLoveBtn.setSelected(true); - }else{ + } else { mLoveBtn.setSelected(false); } } @@ -461,7 +497,7 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { @Override public void saveToLoveSuccess() { - CommonUtil.showToast(PlayActivity.this,"添加成功"); + CommonUtil.showToast(PlayActivity.this, "添加成功"); } @Override @@ -469,11 +505,21 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { sendBroadcast(new Intent(BroadcastName.LOVE_SONG_CANCEL)); } + @Override + public void showLrcMessage(String lrc) { + if (lrc == null) { + CommonUtil.showToast(PlayActivity.this, "抱歉,获取不到该歌曲的歌词信息"); + mLrc = null; + } else { + mLrc = lrc; + saveLrcToLocal(); + } + } + //设置唱碟中歌手头像 private void setDiscImg(Bitmap bitmap) { mDiscImg.setImageDrawable(mDisc.getDiscDrawable(bitmap)); - int marginTop = (int) (DisplayUtil.SCALE_DISC_MARGIN_TOP * CommonUtil.getScreenHeight(PlayActivity.this)); RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mDiscImg .getLayoutParams(); @@ -486,6 +532,8 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { @Override public void onReceive(Context context, Intent intent) { + mDisc.setVisibility(View.VISIBLE); + mLrcView.setVisibility(View.GONE); Song mSong = FileHelper.getSong(); mSongTv.setText(mSong.getSongName()); mSingerTv.setText(mSong.getSinger()); @@ -497,8 +545,8 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { mPlayStatusBinder.getMediaPlayer().setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { @Override public void onBufferingUpdate(MediaPlayer mp, int percent) { - Log.d(TAG, "onBufferingUpdate: "+percent); - mSeekBar.setSecondaryProgress(percent*mSeekBar.getProgress()); + Log.d(TAG, "onBufferingUpdate: " + percent); + mSeekBar.setSecondaryProgress(percent * mSeekBar.getProgress()); } }); mPresenter.queryLove(mSong.getSongId()); //查找歌曲是否为我喜欢的歌曲 @@ -521,7 +569,6 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { } private void setLocalImg(String singer) { - String imgUrl = BaseUri.STORAGE_IMG_FILE + MediaUtil.formatSinger(singer) + ".jpg"; SimpleTarget target = new SimpleTarget(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) { @Override @@ -555,6 +602,104 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { } + private void saveLrcToLocal() { + new Thread(new Runnable() { + @Override + public void run() { + HttpURLConnection urlConnection = null; + BufferedReader reader = null; + BufferedWriter writer = null; + try { + URL url = new URL(mLrc); + urlConnection = (HttpURLConnection) url.openConnection(); + urlConnection.setRequestMethod("GET"); + InputStream inputStream = urlConnection.getInputStream(); + reader = new BufferedReader(new InputStreamReader(inputStream)); + StringBuilder lrcBuilder = new StringBuilder(); + String lrc; + + /** + * 保存到本地 + */ + if (!isOnline) { + File file = new File(BaseUri.STORAGE_LRC_FILE); + if (!file.exists()) { + file.mkdirs(); + } + File lrcFile = new File(file, getSongName() + ".lrc"); + FileOutputStream outputStream = new FileOutputStream(lrcFile); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "gbk"); + writer = new BufferedWriter(outputStreamWriter); + } + while ((lrc = reader.readLine()) != null) { + if (isOnline) { + lrcBuilder.append(lrc); + lrcBuilder.append("\n"); + } else { + //写入 + writer.write(lrc); + writer.newLine(); + } + + } + if (isOnline) showLrc(lrcBuilder.toString()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (urlConnection != null) urlConnection.disconnect(); + try { + if (reader != null) reader.close(); + if (writer != null) writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + }).start(); + } + + /** + * 从本地读取歌词文件 + */ + private String getLrcFromLocal() { + try { + InputStream inputStream = new FileInputStream(new File(BaseUri.STORAGE_LRC_FILE + getSongName() + ".lrc")); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len = -1; + while ((len = inputStream.read(buffer)) != -1) { + os.write(buffer, 0, len); + } + Log.d(TAG, "getLrcFromLocal: "+os.toString("gbk")); + return os.toString("gbk"); //文件编码是gbk + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return ""; + } + + /** + * 展示歌词 + * + * @param lrc + */ + private void showLrc(final String lrc) { + runOnUiThread(new Runnable() { + @Override + public void run() { + mDisc.setVisibility(View.GONE); + mLrcView.setVisibility(View.VISIBLE); + mLrcView.setLrc(lrc); + mLrcView.setHighLineColor(getResources().getColor(R.color.musicStyle)); + mLrcView.setPlayer(mPlayStatusBinder.getMediaPlayer()); + mLrcView.init(); + } + }); + } + @Override public void onDestroy() { super.onDestroy(); diff --git a/app/src/main/java/com/example/musicplayer/view/WelcomeActivity.java b/app/src/main/java/com/example/musicplayer/view/WelcomeActivity.java index 852469c..da36fc0 100644 --- a/app/src/main/java/com/example/musicplayer/view/WelcomeActivity.java +++ b/app/src/main/java/com/example/musicplayer/view/WelcomeActivity.java @@ -57,7 +57,7 @@ public class WelcomeActivity extends AppCompatActivity { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { mHandler.sendEmptyMessageDelayed(0, 2000); } else { - Toast.makeText(this, "软件工程3班:袁健策 3117004905\n拒绝该权限无法使用该程序", Toast.LENGTH_SHORT).show(); + Toast.makeText(this, "拒绝该权限无法使用该程序", Toast.LENGTH_SHORT).show(); finish(); } break; diff --git a/app/src/main/java/com/example/musicplayer/widget/LrcView.java b/app/src/main/java/com/example/musicplayer/widget/LrcView.java new file mode 100644 index 0000000..397f281 --- /dev/null +++ b/app/src/main/java/com/example/musicplayer/widget/LrcView.java @@ -0,0 +1,194 @@ +package com.example.musicplayer.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.media.MediaPlayer; +import android.util.AttributeSet; +import android.view.View; + +import com.example.musicplayer.R; +import com.example.musicplayer.entiy.LrcBean; +import com.example.musicplayer.util.LrcUtil; + +import java.util.List; + +/** + *
+ *     author : 残渊
+ *     time   : 2019/03/18
+ *     desc   : 自定义歌词界面
+ * 
+ */ + +public class LrcView extends View { + + private List list; + private Paint gPaint; + private Paint hPaint; + private int width = 0, height = 0; + private int currentPosition = 0; + private MediaPlayer player; + private int lastPosition = 0; + private int highLineColor; + private int lrcTextSize; + private int lrcColor; + private int mode = 0; + public final static int KARAOKE = 1; + + public void setHighLineColor(int highLineColor) { + this.highLineColor = highLineColor; + } + + public void setLrcColor(int lrcColor) { + this.lrcColor = lrcColor; + } + + public void setMode(int mode) { + this.mode = mode; + } + + public void setPlayer(MediaPlayer player) { + this.player = player; + } + + /** + * 标准歌词字符串 + * + * @param lrc + */ + public void setLrc(String lrc) { + list = LrcUtil.parseStr2List(lrc); + } + + public LrcView(Context context) { + this(context, null); + } + + public LrcView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public LrcView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LrcView); + highLineColor = ta.getColor(R.styleable.LrcView_hignLineColor, getResources().getColor(R.color.green)); + lrcColor = ta.getColor(R.styleable.LrcView_lrcColor, getResources().getColor(android.R.color.darker_gray)); + float densityText = getResources().getDisplayMetrics().scaledDensity; + lrcTextSize = ta.getDimensionPixelSize(R.styleable.LrcView_lrcTextSize,(int)(16*densityText)); + mode = ta.getInt(R.styleable.LrcView_lrcMode,mode); + ta.recycle(); + gPaint = new Paint(); + gPaint.setAntiAlias(true); + gPaint.setColor(lrcColor); + gPaint.setTextSize(lrcTextSize); + gPaint.setTextAlign(Paint.Align.CENTER); + hPaint = new Paint(); + hPaint.setAntiAlias(true); + hPaint.setColor(highLineColor); + hPaint.setTextSize(lrcTextSize); + hPaint.setTextAlign(Paint.Align.CENTER); + } + + @Override + protected void onDraw(Canvas canvas) { + if (width == 0 || height == 0) { + width = getMeasuredWidth(); + height = getMeasuredHeight(); + } + if (list == null || list.size() == 0) { + canvas.drawText("暂无歌词", width / 2, height / 2, gPaint); + return; + } + + getCurrentPosition(); + int currentMillis = player.getCurrentPosition(); + drawLrc2(canvas, currentMillis); + long start = list.get(currentPosition).getStart(); + float v = (currentMillis - start) > 500 ? currentPosition * 120 : lastPosition * 120 + (currentPosition - lastPosition) * 120 * ((currentMillis - start) / 500f); + setScrollY((int) v); + if (getScrollY() == currentPosition * 120) { + lastPosition = currentPosition; + } + postInvalidateDelayed(100); + } + + private void drawLrc2(Canvas canvas, int currentMillis) { + if (mode == 0) { + for (int i = 0; i < list.size(); i++) { + if (i == currentPosition) { + canvas.drawText(list.get(i).getLrc(), width / 2, height / 2 + 120 * i, hPaint); + } else { + canvas.drawText(list.get(i).getLrc(), width / 2, height / 2 + 120 * i, gPaint); + } + } + }else{ + for (int i = 0; i < list.size(); i++) { + canvas.drawText(list.get(i).getLrc(), width / 2, height / 2 + 80 * i, gPaint); + } + String highLineLrc = list.get(currentPosition).getLrc(); + int highLineWidth = (int) gPaint.measureText(highLineLrc); + int leftOffset = (width - highLineWidth) / 2; + LrcBean lrcBean = list.get(currentPosition); + long start = lrcBean.getStart(); + long end = lrcBean.getEnd(); + int i = (int) ((currentMillis - start) * 1.0f / (end - start) * highLineWidth); + if (i > 0) { + Bitmap textBitmap = Bitmap.createBitmap(i, 80, Bitmap.Config.ARGB_8888); + Canvas textCanvas = new Canvas(textBitmap); + textCanvas.drawText(highLineLrc, highLineWidth / 2, 80, hPaint); + canvas.drawBitmap(textBitmap, leftOffset, height / 2 + 80 * (currentPosition - 1), null); + } + } + } + + public void init() { + currentPosition = 0; + lastPosition = 0; + setScrollY(0); + invalidate(); + } + + private void drawLrc1(Canvas canvas) { + String text = list.get(currentPosition).getLrc(); + canvas.drawText(text, width / 2, height / 2, hPaint); + + for (int i = 1; i < 10; i++) { + int index = currentPosition - i; + if (index > -1) { + canvas.drawText(list.get(index).getLrc(), width / 2, height / 2 - 100 * i, gPaint); + } + } + for (int i = 1; i < 10; i++) { + int index = currentPosition + i; + if (index < list.size()) { + canvas.drawText(list.get(index).getLrc(), width / 2, height / 2 + 100 * i, gPaint); + } + } + } + + private void getCurrentPosition() { + try { + int currentMillis = player.getCurrentPosition(); + if (currentMillis < list.get(0).getStart()) { + currentPosition = 0; + return; + } + if (currentMillis > list.get(list.size() - 1).getStart()) { + currentPosition = list.size() - 1; + return; + } + for (int i = 0; i < list.size(); i++) { + if (currentMillis >= list.get(i).getStart() && currentMillis < list.get(i).getEnd()) { + currentPosition = i; + return; + } + } + } catch (Exception e) { + postInvalidateDelayed(100); + } + } +} diff --git a/app/src/main/res/layout/activity_play.xml b/app/src/main/res/layout/activity_play.xml index e798201..0848cca 100644 --- a/app/src/main/res/layout/activity_play.xml +++ b/app/src/main/res/layout/activity_play.xml @@ -1,5 +1,6 @@ + +