diff --git a/.idea/misc.xml b/.idea/misc.xml index 92413e2..b6ea2b1 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,40 +1,5 @@ - - - - diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 703d2b0..c9ebb4b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 27 + compileSdkVersion 28 defaultConfig { applicationId "com.example.musicplayer" minSdkVersion 22 - targetSdkVersion 27 + targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -30,15 +30,15 @@ allprojects { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' - implementation 'com.android.support:support-v4:27.1.1' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' - implementation 'com.android.support:design:27.1.1' + implementation 'com.android.support:design:28.0.0' implementation 'de.hdodenhof:circleimageview:2.2.0' - implementation 'com.android.support:recyclerview-v7:27.1.1' + implementation 'com.android.support:recyclerview-v7:28.0.0' + implementation 'com.android.support:support-v4:28.0.0' //RxJava2 implementation 'io.reactivex.rxjava2:rxjava:2.0.1' @@ -55,7 +55,7 @@ dependencies { //LRecyclerView implementation 'com.github.jdsjlzx:LRecyclerView:1.5.4.3' //CardView - implementation 'com.android.support:cardview-v7:27.1.1' + implementation 'com.android.support:cardview-v7:28.0.0' //滑动page implementation 'com.github.florent37:materialviewpager:1.2.3' implementation 'com.flaviofaria:kenburnsview:1.0.7' diff --git a/app/release/output.json b/app/release/output.json new file mode 100644 index 0000000..9f0c959 --- /dev/null +++ b/app/release/output.json @@ -0,0 +1 @@ +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file 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 4e7e512..5557540 100644 --- a/app/src/main/java/com/example/musicplayer/configure/BaseUri.java +++ b/app/src/main/java/com/example/musicplayer/configure/BaseUri.java @@ -13,6 +13,7 @@ public class BaseUri { public static String STORAGE_IMG_FILE=MyApplication.getContext().getExternalFilesDir("") + "/yuanmusic/img/"; public static String STORAGE_LRC_FILE=MyApplication.getContext().getExternalFilesDir("") + "/yuanmusic/lrc/"; + public static String STORAGE_SONG_FILE=MyApplication.getContext().getExternalFilesDir("") + "/yuanmusic/song/"; 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 f88d82a..ca1d7f0 100644 --- a/app/src/main/java/com/example/musicplayer/contract/IPlayContract.java +++ b/app/src/main/java/com/example/musicplayer/contract/IPlayContract.java @@ -13,7 +13,7 @@ import java.util.List; public interface IPlayContract { interface Model{ void getSingerImg(String singer,String song,long duration);//网络请求获得歌手uri - void getLrc(String song,long duration);//网络获取歌词 + void getLrcUrl(String song, long duration);//网络获取歌词地址 void queryLove(String songId);//查询我喜欢的数据库中有没这首歌 void saveToLove(Song song); //添加到我喜欢的表 void deleteFromLove(String songId); //从我喜欢的表中移除 @@ -27,11 +27,11 @@ public interface IPlayContract { void showLoveAnim(); //喜欢的动画 void saveToLoveSuccess();//保存到我喜欢数据库成功 void sendUpdateCollection(); //发送广播更新收藏列表 - void showLrcMessage(String lrc); //显示歌词获取信息 + void showLrcMessage(String lrc,String id); //显示歌词获取信息 } interface Presenter{ void getSingerImg(String singer,String song,long duration); - void getLrc(String song,long duration); + void getLrcUrl(String song, long duration); void getSingerImgSuccess(String ImgUrl); //成功获取图片 void getSongLrcSuccess(List dataBeans,long duration); //成功获取歌词 void getSongLrcFail(); //获取歌词失败 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 9a4920a..72e35b8 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 @@ -29,4 +29,12 @@ public interface SearchApi { */ @GET("search?key=579621905&type=song&limit=10&offset=0") Observable search(@Query("s") String seek); + + /** + * + * @param id 歌曲id + * @return + */ + @GET("lrc?key=579621905") + Observable getLrc(@Query("id") String id); } 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 bc52963..fe688d9 100644 --- a/app/src/main/java/com/example/musicplayer/model/PlayModel.java +++ b/app/src/main/java/com/example/musicplayer/model/PlayModel.java @@ -97,7 +97,7 @@ public class PlayModel implements IPlayContract.Model { } @Override - public void getLrc(String song, long duration) { + public void getLrcUrl(String song, long duration) { NetWork.getSearchApi().search(song) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) 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 1f82c9a..b141f84 100644 --- a/app/src/main/java/com/example/musicplayer/presenter/PlayPresenter.java +++ b/app/src/main/java/com/example/musicplayer/presenter/PlayPresenter.java @@ -1,6 +1,5 @@ package com.example.musicplayer.presenter; -import android.support.design.widget.TabLayout; import android.util.Log; import com.example.musicplayer.base.BasePresenter; @@ -30,8 +29,8 @@ public class PlayPresenter extends BasePresenter implements } @Override - public void getLrc(String song, long duration) { - mModel.getLrc(song,duration); + public void getLrcUrl(String song, long duration) { + mModel.getLrcUrl(song,duration); } @Override @@ -42,26 +41,25 @@ public class PlayPresenter extends BasePresenter implements } @Override - public void getSongLrcSuccess(List dataBeans,long duration) { + 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()); + getMvpView().showLrcMessage(dataBean.getLrc(),dataBean.getId()); break; } } - Log.d(TAG, "getSongLrcSuccess: "+isLrc); - if(!isLrc) getMvpView().showLrcMessage(dataBeans.get(0).getLrc()); + if(!isLrc) getMvpView().showLrcMessage(dataBeans.get(0).getLrc(),dataBeans.get(0).getId()); } } + @Override public void getSongLrcFail() { if(isAttachView()){ - getMvpView().showLrcMessage(null); + getMvpView().showLrcMessage(null,null); } } diff --git a/app/src/main/java/com/example/musicplayer/view/MainActivity.java b/app/src/main/java/com/example/musicplayer/view/MainActivity.java index 81336d2..07d04bf 100644 --- a/app/src/main/java/com/example/musicplayer/view/MainActivity.java +++ b/app/src/main/java/com/example/musicplayer/view/MainActivity.java @@ -4,6 +4,8 @@ package com.example.musicplayer.view; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.app.ActivityOptions; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -96,6 +98,7 @@ public class MainActivity extends AppCompatActivity { Intent playIntent = new Intent(MainActivity.this, PlayerService.class); bindService(playIntent, connection, Context.BIND_AUTO_CREATE); initView(); + } @Override public void onDestroy() { 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 200b46b..b9c954a 100644 --- a/app/src/main/java/com/example/musicplayer/view/PlayActivity.java +++ b/app/src/main/java/com/example/musicplayer/view/PlayActivity.java @@ -57,6 +57,7 @@ import com.example.musicplayer.widget.BackgroundAnimationRelativeLayout; import com.example.musicplayer.widget.DiscView; import com.example.musicplayer.widget.LrcView; +import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; @@ -67,11 +68,18 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.io.PrintStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.List; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import retrofit2.http.Url; + /** * 播放界面 */ @@ -104,6 +112,8 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { private TextView mCurrentTimeTv; private TextView mDurationTimeTv; + private ImageView mDownLoad; //下载 + private String mLrc = null; @@ -208,6 +218,7 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { mLoveBtn = findViewById(R.id.btn_love); mOrderBtn = findViewById(R.id.btn_order); mLrcView = findViewById(R.id.lrcView); + mDownLoad = findViewById(R.id.downloadIv); //界面填充 mSong = FileHelper.getSong(); @@ -399,11 +410,11 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { mDisc.setOnClickListener(v -> { if (!isOnline) { if (getLrcFromLocal().equals("")) { - mPresenter.getLrc(getSongName(), mSong.getDuration()); + mPresenter.getLrcUrl(getSongName(), mSong.getDuration()); } showLrc(getLrcFromLocal()); } else { - mPresenter.getLrc(getSongName(), mSong.getDuration()); + mPresenter.getLrcUrl(getSongName(), mSong.getDuration()); } } ); @@ -412,6 +423,11 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { mLrcView.setVisibility(View.GONE); mDisc.setVisibility(View.VISIBLE); }); + //歌曲下载 + mDownLoad.setOnClickListener(v -> { + CommonUtil.showToast(this,"开始下载歌曲"); + downLoad(mSong.getUrl(), mSong.getSongName()); + }); } @@ -506,7 +522,7 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { } @Override - public void showLrcMessage(String lrc) { + public void showLrcMessage(String lrc, String id) { if (lrc == null) { CommonUtil.showToast(PlayActivity.this, "抱歉,获取不到该歌曲的歌词信息"); mLrc = null; @@ -670,7 +686,6 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { 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) { @@ -687,17 +702,57 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View { * @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(); + runOnUiThread(()->{ + mDisc.setVisibility(View.GONE); + mLrcView.setVisibility(View.VISIBLE); + mLrcView.setLrc(lrc); + mLrcView.setHighLineColor(getResources().getColor(R.color.musicStyle)); + mLrcView.setPlayer(mPlayStatusBinder.getMediaPlayer()); + mLrcView.init(); + }); + + } + + private void downLoad(String url, String song) { + new Thread(() -> { + File file = new File(BaseUri.STORAGE_SONG_FILE); + if (!file.exists()) { + file.mkdirs(); } + File songFile = new File(file, song + ".mp3"); + BufferedOutputStream out = null; + try { + OkHttpClient client = new OkHttpClient(); + Request request = new Request.Builder().url(url).build(); + Response response = client.newCall(request).execute(); + if (response.isSuccessful()){ + out = new BufferedOutputStream(new FileOutputStream(songFile)); + byte[] bytes = response.body().bytes(); + out.write(bytes,0,bytes.length); + out.close(); + } + showLoadSuccess(); + } catch (IOException e){ + e.printStackTrace(); + }catch (Exception e) { + e.printStackTrace(); + }finally { + try{ + if(out != null) out.close(); + }catch (Exception e){ + e.printStackTrace(); + } + } + }).start(); + } + + + + private void showLoadSuccess(){ + runOnUiThread(()->{ + CommonUtil.showToast(this,"歌曲下载成功"); }); + } @Override diff --git a/app/src/main/res/drawable-xxhdpi/download_song.png b/app/src/main/res/drawable-xxhdpi/download_song.png new file mode 100644 index 0000000..2c92129 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/download_song.png differ diff --git a/app/src/main/res/layout/activity_play.xml b/app/src/main/res/layout/activity_play.xml index 0848cca..fd8f09a 100644 --- a/app/src/main/res/layout/activity_play.xml +++ b/app/src/main/res/layout/activity_play.xml @@ -67,7 +67,7 @@ android:layout_marginTop="@dimen/dp_40" android:layout_marginBottom="@dimen/dp_40" android:layout_below="@+id/relative_song" - android:layout_above="@+id/relative_music_time" + android:layout_above="@+id/downloadIv" app:lrcTextSize="18sp" app:hignLineColor="@color/musicStyle" android:visibility="gone"/> @@ -85,12 +85,22 @@ android:layout_height="wrap_content" android:layout_below="@+id/disc_view" android:layout_centerHorizontal="true" - android:layout_marginTop="30dp" + android:layout_marginTop="10dp" android:textColor="@color/white" android:background="@drawable/button_bg" android:text="获取封面歌词"/> + + +