() {
40 | @Override
41 | public void call(Void aVoid) {
42 | MusicClient.setPlayListAndPlayAt(tracks,helper.getLayoutPosition());
43 | }
44 | });
45 | }
46 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/imageloader/processors/internal/RSBlur.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.imageloader.processors.internal;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.os.Build;
7 | import android.renderscript.Allocation;
8 | import android.renderscript.Element;
9 | import android.renderscript.RSRuntimeException;
10 | import android.renderscript.RenderScript;
11 | import android.renderscript.ScriptIntrinsicBlur;
12 |
13 | /**
14 | * Copyright (C) 2015 Wasabeef
15 | *
16 | * Licensed under the Apache License, Version 2.0 (the "License");
17 | * you may not use this file except in compliance with the License.
18 | * You may obtain a copy of the License at
19 | *
20 | * http://www.apache.org/licenses/LICENSE-2.0
21 | *
22 | * Unless required by applicable law or agreed to in writing, software
23 | * distributed under the License is distributed on an "AS IS" BASIS,
24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 | * See the License for the specific language governing permissions and
26 | * limitations under the License.
27 | */
28 |
29 | public class RSBlur {
30 |
31 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
32 | public static Bitmap blur(Context context, Bitmap bitmap, int radius) throws RSRuntimeException {
33 | RenderScript rs = null;
34 | try {
35 | rs = RenderScript.create(context);
36 | Allocation input =
37 | Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE,
38 | Allocation.USAGE_SCRIPT);
39 | Allocation output = Allocation.createTyped(rs, input.getType());
40 | ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
41 |
42 | blur.setInput(input);
43 | blur.setRadius(radius);
44 | blur.forEach(output);
45 | output.copyTo(bitmap);
46 | } finally {
47 | if (rs != null) {
48 | rs.destroy();
49 | }
50 | }
51 |
52 | return bitmap;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/imageloader/frescoview/BaseFrescoImageView.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.imageloader.frescoview;
2 |
3 | import com.facebook.drawee.controller.ControllerListener;
4 | import com.facebook.drawee.generic.RoundingParams;
5 | import com.facebook.drawee.interfaces.DraweeController;
6 | import com.facebook.imagepipeline.request.ImageRequest;
7 | import com.facebook.imagepipeline.request.Postprocessor;
8 |
9 | /**
10 | * Created by Linhh on 16/3/2.
11 | */
12 | public interface BaseFrescoImageView {
13 |
14 | /**
15 | * 获得当前监听
16 | * @return
17 | */
18 | public ControllerListener getControllerListener();
19 |
20 | /**
21 | * 获得当前使用的DraweeController
22 | * @return
23 | */
24 | public DraweeController getDraweeController();
25 |
26 | /**
27 | * 获得低级别ImageRequest
28 | * @return
29 | */
30 | public ImageRequest getLowImageRequest();
31 |
32 | /**
33 | * 获得当前使用的ImageRequest
34 | * @return
35 | */
36 | public ImageRequest getImageRequest();
37 |
38 | /**
39 | * 获得当前使用的RoundingParams
40 | */
41 | public RoundingParams getRoundingParams();
42 |
43 | /**
44 | * 是否开启动画
45 | * @return
46 | */
47 | public boolean isAnim();
48 |
49 | /**
50 | * 获得当前后处理
51 | * @return
52 | */
53 | public Postprocessor getPostProcessor();
54 |
55 | /**
56 | * 获得当前使用的默认图
57 | * @return
58 | */
59 | public int getDefaultResID();
60 |
61 | /**
62 | * 获得当前加载的图片
63 | * @return
64 | */
65 | public String getThumbnailUrl();
66 |
67 | /**
68 | * 获得当前低分辨率图片
69 | * @return
70 | */
71 | public String getLowThumbnailUrl();
72 |
73 | /**
74 | * 获得加载的本地图片
75 | * @return
76 | */
77 | public String getThumbnailPath();
78 |
79 | /**
80 | * 是否可以点击重试,默认false
81 | * @return
82 | */
83 | public boolean getTapToRetryEnabled();
84 |
85 | /**
86 | * 是否自动旋转
87 | * @return
88 | */
89 | public boolean getAutoRotateEnabled();
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/audiocache/IgnoreHostProxySelector.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.audiocache;
2 |
3 | import java.io.IOException;
4 | import java.net.Proxy;
5 | import java.net.ProxySelector;
6 | import java.net.SocketAddress;
7 | import java.net.URI;
8 | import java.util.Arrays;
9 | import java.util.List;
10 |
11 | import static com.yjl.funk.audiocache.Preconditions.checkNotNull;
12 |
13 | /**
14 | * {@link ProxySelector} that ignore system default proxies for concrete host.
15 | *
16 | * It is important to ignore system proxy for localhost connection.
17 | *
18 | * @author Alexey Danilov (danikula@gmail.com).
19 | */
20 | class IgnoreHostProxySelector extends ProxySelector {
21 |
22 | private static final List NO_PROXY_LIST = Arrays.asList(Proxy.NO_PROXY);
23 |
24 | private final ProxySelector defaultProxySelector;
25 | private final String hostToIgnore;
26 | private final int portToIgnore;
27 |
28 | IgnoreHostProxySelector(ProxySelector defaultProxySelector, String hostToIgnore, int portToIgnore) {
29 | this.defaultProxySelector = checkNotNull(defaultProxySelector);
30 | this.hostToIgnore = checkNotNull(hostToIgnore);
31 | this.portToIgnore = portToIgnore;
32 | }
33 |
34 | static void install(String hostToIgnore, int portToIgnore) {
35 | ProxySelector defaultProxySelector = ProxySelector.getDefault();
36 | ProxySelector ignoreHostProxySelector = new IgnoreHostProxySelector(defaultProxySelector, hostToIgnore, portToIgnore);
37 | ProxySelector.setDefault(ignoreHostProxySelector);
38 | }
39 |
40 | @Override
41 | public List select(URI uri) {
42 | boolean ignored = hostToIgnore.equals(uri.getHost()) && portToIgnore == uri.getPort();
43 | return ignored ? NO_PROXY_LIST : defaultProxySelector.select(uri);
44 | }
45 |
46 | @Override
47 | public void connectFailed(URI uri, SocketAddress address, IOException failure) {
48 | defaultProxySelector.connectFailed(uri, address, failure);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 一款基于Android 5.0以上MaterialDesign风格的音乐播放器——FunkMusicPlayer(Aidl)
2 | ====
3 |
4 |
5 | ScreenShots
6 | ----
7 | 
8 | 
9 | 
10 | 
11 |
12 | Thanks
13 | ---
14 | - [AndroidVideoCache](https://github.com/danikula/AndroidVideoCache)
15 | - [okhttp-utils](https://github.com/hongyangAndroid/okhttp-utils)
16 | - [Fresco](https://github.com/facebook/fresco)
17 | - [RxBinding](https://github.com/JakeWharton/RxBinding)
18 | - [BaseRecyclerViewAdapterHelper](https://github.com/CymChad/BaseRecyclerViewAdapterHelper)
19 |
20 | Features
21 | -----
22 | MaterialDisgn风格
23 |
24 | 在线播放
25 |
26 | 搜索音乐
27 |
28 | 边播边缓存音乐(已缓存过的音乐可以离线收听)
29 |
30 | TODO
31 | ----
32 | 下载
33 |
34 | 多选编辑
35 |
36 | 本地音乐扫描
37 |
38 | 项目ui完善
39 |
40 | 项目还未完成,仅供参考
41 |
42 | ApiCopyright
43 | ----
44 | 百度音乐
45 |
46 | License
47 | -----
48 |
49 | Copyright 2017 TonyYam
50 |
51 | Licensed under the Apache License, Version 2.0 (the "License");
52 | you may not use this file except in compliance with the License.
53 | You may obtain a copy of the License at
54 |
55 | http://www.apache.org/licenses/LICENSE-2.0
56 |
57 | Unless required by applicable law or agreed to in writing, software
58 | distributed under the License is distributed on an "AS IS" BASIS,
59 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
60 | See the License for the specific language governing permissions and
61 | limitations under the License.
62 |
63 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
22 |
23 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_search.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
24 |
30 |
31 |
32 |
33 |
40 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/widget/LoadingDialog.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.widget;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.view.Gravity;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.view.Window;
9 | import android.view.WindowManager;
10 |
11 | import com.yjl.funk.R;
12 | import com.yjl.funk.utils.DensityUtils;
13 |
14 |
15 | /**
16 | * Created by Administrator on 2017/3/18.
17 | * 加载弹窗
18 | */
19 |
20 | public class LoadingDialog extends Dialog {
21 | private Context context;
22 | private LoadingProgressView loadingProgressView;
23 | public LoadingDialog(Context context) {
24 | this(context, R.style.LoadingDialogStyle);
25 |
26 | }
27 |
28 | public LoadingDialog(Context context, int themeResId) {
29 | super(context, themeResId);
30 | this.context = context;
31 | initView();
32 | }
33 |
34 | @Override
35 | public void onBackPressed() {
36 | super.onBackPressed();
37 | this.dismiss();
38 | }
39 | public void initView(){
40 | View view = View.inflate(context,R.layout.loading_dialog,null);
41 | loadingProgressView = (LoadingProgressView) view.findViewById(R.id.load_view);
42 | Window dialogWindow = this.getWindow();
43 | WindowManager.LayoutParams lp = dialogWindow.getAttributes();
44 | dialogWindow.setGravity(Gravity.CENTER);
45 | lp.width = DensityUtils.dip2px(context,75); // 宽度
46 | lp.height = DensityUtils.dip2px(context,75); // 高度
47 | this.addContentView(view,lp);
48 | this.setCancelable(false);
49 | }
50 | public void onShow(){
51 | loadingProgressView.post(new Runnable() {
52 | @Override
53 | public void run() {
54 | loadingProgressView.startAnim();
55 | }
56 | });
57 | this.show();
58 | }
59 | public void onDismiss() {
60 | if (loadingProgressView != null)
61 | loadingProgressView.post(new Runnable() {
62 | @Override
63 | public void run() {
64 | loadingProgressView.stopAnim();
65 | }
66 | });
67 |
68 | if (this.isShowing())
69 | this.dismiss();
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/audiocache/file/LruDiskUsage.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.audiocache.file;
2 |
3 |
4 | import java.io.File;
5 | import java.io.IOException;
6 | import java.util.List;
7 | import java.util.concurrent.Callable;
8 | import java.util.concurrent.ExecutorService;
9 | import java.util.concurrent.Executors;
10 | import java.util.logging.Logger;
11 |
12 | /**
13 | * {@link DiskUsage} that uses LRU (Least Recently Used) strategy to trim cache.
14 | *
15 | * @author Alexey Danilov (danikula@gmail.com).
16 | */
17 | public abstract class LruDiskUsage implements DiskUsage {
18 |
19 | private final ExecutorService workerThread = Executors.newSingleThreadExecutor();
20 |
21 | @Override
22 | public void touch(File file) throws IOException {
23 | workerThread.submit(new TouchCallable(file));
24 | }
25 |
26 | private void touchInBackground(File file) throws IOException {
27 | Files.setLastModifiedNow(file);
28 | List files = Files.getLruListFiles(file.getParentFile());
29 | trim(files);
30 | }
31 |
32 | protected abstract boolean accept(File file, long totalSize, int totalCount);
33 |
34 | private void trim(List files) {
35 | long totalSize = countTotalSize(files);
36 | int totalCount = files.size();
37 | for (File file : files) {
38 | boolean accepted = accept(file, totalSize, totalCount);
39 | if (!accepted) {
40 | long fileSize = file.length();
41 | boolean deleted = file.delete();
42 | if (deleted) {
43 | totalCount--;
44 | totalSize -= fileSize;
45 | } else {
46 | }
47 | }
48 | }
49 | }
50 |
51 | private long countTotalSize(List files) {
52 | long totalSize = 0;
53 | for (File file : files) {
54 | totalSize += file.length();
55 | }
56 | return totalSize;
57 | }
58 |
59 | private class TouchCallable implements Callable {
60 |
61 | private final File file;
62 |
63 | public TouchCallable(File file) {
64 | this.file = file;
65 | }
66 |
67 | @Override
68 | public Void call() throws Exception {
69 | touchInBackground(file);
70 | return null;
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
19 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/utils/Preferences.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.preference.PreferenceManager;
6 | import android.support.annotation.Nullable;
7 |
8 | import com.yjl.funk.R;
9 |
10 | public class Preferences {
11 | private static final String MUSIC_ID = "music_id";
12 | private static final String PLAY_MODE = "play_mode";
13 |
14 | private static Context sContext;
15 |
16 | public static void init(Context context) {
17 | sContext = context.getApplicationContext();
18 | }
19 |
20 | public static long getCurrentSongId() {
21 | return getLong(MUSIC_ID, -1);
22 | }
23 |
24 | public static void saveCurrentSongId(long id) {
25 | saveLong(MUSIC_ID, id);
26 | }
27 |
28 | public static int getPlayMode() {
29 | return getInt(PLAY_MODE, 0);
30 | }
31 |
32 | public static void savePlayMode(int mode) {
33 | saveInt(PLAY_MODE, mode);
34 | }
35 |
36 |
37 |
38 |
39 | private static boolean getBoolean(String key, boolean defValue) {
40 | return getPreferences().getBoolean(key, defValue);
41 | }
42 |
43 | private static void saveBoolean(String key, boolean value) {
44 | getPreferences().edit().putBoolean(key, value).apply();
45 | }
46 |
47 | private static int getInt(String key, int defValue) {
48 | return getPreferences().getInt(key, defValue);
49 | }
50 |
51 | private static void saveInt(String key, int value) {
52 | getPreferences().edit().putInt(key, value).apply();
53 | }
54 |
55 | private static long getLong(String key, long defValue) {
56 | return getPreferences().getLong(key, defValue);
57 | }
58 |
59 | private static void saveLong(String key, long value) {
60 | getPreferences().edit().putLong(key, value).apply();
61 | }
62 |
63 | private static String getString(String key, @Nullable String defValue) {
64 | return getPreferences().getString(key, defValue);
65 | }
66 |
67 | private static void saveString(String key, @Nullable String value) {
68 | getPreferences().edit().putString(key, value).apply();
69 | }
70 |
71 | private static SharedPreferences getPreferences() {
72 | return PreferenceManager.getDefaultSharedPreferences(sContext);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/widget/ToastyUtils.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.PorterDuff;
5 | import android.graphics.drawable.Drawable;
6 | import android.graphics.drawable.NinePatchDrawable;
7 | import android.os.Build;
8 | import android.support.annotation.ColorInt;
9 | import android.support.annotation.DrawableRes;
10 | import android.support.annotation.NonNull;
11 | import android.view.View;
12 | import com.yjl.funk.R;
13 |
14 |
15 | /**
16 | * This file is part of Toasty.
17 | *
18 | * Toasty is free software: you can redistribute it and/or modify
19 | * it under the terms of the GNU General Public License as published by
20 | * the Free Software Foundation, either version 3 of the License, or
21 | * (at your option) any later version.
22 | *
23 | * Toasty is distributed in the hope that it will be useful,
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 | * GNU General Public License for more details.
27 | *
28 | * You should have received a copy of the GNU General Public License
29 | * along with Toasty. If not, see .
30 | */
31 |
32 | final class ToastyUtils {
33 | private ToastyUtils() {
34 | }
35 |
36 | static Drawable tintIcon(@NonNull Drawable drawable, @ColorInt int tintColor) {
37 | drawable.setColorFilter(tintColor, PorterDuff.Mode.SRC_IN);
38 | return drawable;
39 | }
40 |
41 | static Drawable tint9PatchDrawableFrame(@NonNull Context context, @ColorInt int tintColor) {
42 | final NinePatchDrawable toastDrawable = (NinePatchDrawable) getDrawable(context, R.drawable.toast_frame);
43 | return tintIcon(toastDrawable, tintColor);
44 | }
45 |
46 | static void setBackground(@NonNull View view, Drawable drawable) {
47 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
48 | view.setBackground(drawable);
49 | else
50 | view.setBackgroundDrawable(drawable);
51 | }
52 |
53 | static Drawable getDrawable(@NonNull Context context, @DrawableRes int id) {
54 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
55 | return context.getDrawable(id);
56 | else
57 | return context.getResources().getDrawable(id);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/player/Constants.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.player;
2 |
3 | /**
4 | * Created by tonyy on 2017/11/12.
5 | */
6 |
7 | public class Constants {
8 | public static final String PLAYSTATE_CHANGED = "com.yjl.funk.playstatechanged";
9 | public static final String MUSIC_CHANGED = "com.yjl.funk.musicchanged";
10 | public static final String PLAYLIST_CHANGED = "com.yjl.funk.playlistchanged";
11 | public static final String LRC_ERROR = "com.yjl.funk.lrcerror";
12 | public static final String LRC_DOWNLOADED = "com.yjl.funk.lrcdownloaded";
13 | public static final String TRACK_ERROR = "com.yjl.funk.trackerror";
14 | public static final String SERVICECMD = "com.yjl.funk.musicservicecommand";
15 | public static final String TOGGLEPAUSE_ACTION = "com.yjl.funk.togglepause";
16 | public static final String PAUSE_ACTION = "com.yjl.funk.pause";
17 | public static final String STOP_ACTION = "com.yjl.funk.stop";
18 | public static final String PREVIOUS_ACTION = "com.yjl.funk.previous";
19 | public static final String NEXT_ACTION = "com.yjl.funk.next";
20 | public static final String REPEAT_ACTION = "com.yjl.funk.repeat";
21 | public static final String SHUFFLE_ACTION = "com.yjl.funk.shuffle";
22 | public static final String CMDNAME = "command";
23 | public static final String CMDTOGGLEPAUSE = "togglepause";
24 | public static final String CMDSTOP = "stop";
25 | public static final String CMDPAUSE = "pause";
26 | public static final String CMDPLAY = "play";
27 | public static final String CMDPREVIOUS = "previous";
28 | public static final String CMDNEXT = "next";
29 | public static final String EXTRA_NOTIFICATION = "FROM_FUNK_MUSIC_NOTIFICATION";
30 | //随机
31 | public static final int SHUFFLE= 201;
32 | //单曲循环
33 | public static final int REPEAT_CURRENT = 202;
34 | //列表循环
35 | public static final int REPEAT_ALL = 203;
36 | public static final String TAG = "MusicPlaybackService";
37 | //关闭当前服务
38 | public static final String SHUTDOWN = "com.yjl.funk.shutdown";
39 | //播放器焦点变化
40 | public static final int FOCUSCHANGE = 5;
41 | //音量递减
42 | public static final int FADEDOWN = 6;
43 | //音量递增
44 | public static final int FADEUP = 7;
45 | //关闭当前服务延时
46 | public static final int IDLE_DELAY = 5 * 60 * 1000;
47 | //歌曲名称
48 | public static final String TRACK_ERROR_INFO = "trackerrorinfo";
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_special_album.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
20 |
21 |
28 |
29 |
40 |
41 |
51 |
52 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/ui/base/BaseMusicActivity.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.ui.base;
2 |
3 |
4 | import android.content.ComponentName;
5 | import android.content.ServiceConnection;
6 | import android.media.AudioManager;
7 | import android.os.Bundle;
8 | import android.os.IBinder;
9 | import android.support.v7.app.AppCompatActivity;
10 |
11 | import com.yjl.funk.IFunkService;
12 | import com.yjl.funk.player.MusicClient;
13 | import com.yjl.funk.utils.ScreenUtils;
14 |
15 | import butterknife.ButterKnife;
16 |
17 |
18 | /**
19 | * Created by Administrator on 2017/3/2.
20 | */
21 |
22 | public abstract class BaseMusicActivity extends AppCompatActivity implements ServiceConnection {
23 | private MusicClient.ServiceToken mToken;
24 | @Override
25 | protected void onCreate( Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | setContentView(OnLayoutInit());
28 | ButterKnife.bind(this);
29 | initToolBar();
30 | initViews();
31 | initListeners();
32 | ScreenUtils.setSystemBarTransparent(this);
33 |
34 | mToken = MusicClient.bindToService(this, this);
35 | setVolumeControlStream(AudioManager.STREAM_MUSIC);
36 | }
37 |
38 |
39 | public abstract int OnLayoutInit();
40 | /**
41 | * 初始化控件
42 | *
43 | */
44 | public abstract void initViews();
45 |
46 | /**
47 | * 监听设置
48 | */
49 | public abstract void initListeners();
50 | /**
51 | * 初始化工具栏*/
52 | public abstract void initToolBar();
53 | /**
54 | * app字体不随系统字体的大小改变而改变
55 | */
56 |
57 | @Override
58 | public void onServiceConnected(final ComponentName name, final IBinder service) {
59 | MusicClient.mService = IFunkService.Stub.asInterface(service);
60 |
61 | }
62 |
63 |
64 | @Override
65 | public void onServiceDisconnected(final ComponentName name) {
66 | MusicClient.mService = null;
67 | }
68 | @Override
69 | protected void onResume() {
70 | super.onResume();
71 | }
72 |
73 |
74 | @Override
75 | protected void onPause() {
76 | super.onPause();
77 |
78 | }
79 | @Override
80 | protected void onStart(){
81 | super.onStart();
82 | }
83 | @Override
84 | protected void onDestroy() {
85 | super.onDestroy();
86 | //解注eventbus
87 | if (mToken != null) {
88 | MusicClient.unbindFromService(mToken);
89 | mToken = null;
90 | }
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/receiver/MediaButtonIntentReceiver.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.yjl.funk.receiver;
4 |
5 | import android.content.BroadcastReceiver;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.media.AudioManager;
9 | import android.view.KeyEvent;
10 | import com.yjl.funk.player.Constants;
11 | import com.yjl.funk.service.FunkMusicService;
12 |
13 | /**
14 | * 耳机线控
15 | */
16 | public class MediaButtonIntentReceiver extends BroadcastReceiver {
17 |
18 | private static void sendBroadCast(Context context, String command) {
19 | final Intent i = new Intent(context, FunkMusicService.class);
20 | i.setAction(Constants.SERVICECMD);
21 | i.putExtra(Constants.CMDNAME, command);
22 | context.startService(i);
23 | }
24 | @Override
25 | public void onReceive(final Context context, final Intent intent) {
26 | final String intentAction = intent.getAction();
27 | //拔耳机
28 | if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intentAction)) {
29 | sendBroadCast(context, Constants.CMDPAUSE);
30 | } else if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
31 | final KeyEvent event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
32 | if (event == null) {
33 | return;
34 | }
35 | final int keycode = event.getKeyCode();
36 |
37 | String command = null;
38 | switch (keycode) {
39 | case KeyEvent.KEYCODE_MEDIA_STOP:
40 | command = Constants.CMDSTOP;
41 | break;
42 | case KeyEvent.KEYCODE_MEDIA_NEXT:
43 | command = Constants.CMDNEXT;
44 | break;
45 | case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
46 | command = Constants.CMDPREVIOUS;
47 | break;
48 | case KeyEvent.KEYCODE_MEDIA_PAUSE:
49 | command = Constants.CMDPAUSE;
50 | break;
51 | case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
52 | case KeyEvent.KEYCODE_HEADSETHOOK:
53 | command = Constants.CMDTOGGLEPAUSE;
54 | break;
55 | case KeyEvent.KEYCODE_MEDIA_PLAY:
56 | command = Constants.CMDPLAY;
57 | break;
58 | }
59 | abortBroadcast();
60 | sendBroadCast(context, command);
61 |
62 | }
63 | }
64 | }
65 |
66 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/utils/FileUtils.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.utils;
2 |
3 | import android.content.Context;
4 | import android.os.Environment;
5 |
6 |
7 | import com.yjl.funk.network.HttpCallback;
8 | import com.yjl.funk.network.HttpClient;
9 | import com.yjl.funk.network.HttpException;
10 |
11 | import java.io.BufferedWriter;
12 | import java.io.File;
13 | import java.io.FileWriter;
14 | import java.io.IOException;
15 |
16 | public class FileUtils {
17 | public static final String MP3 = ".mp3";
18 | public static final String LRC = ".lrc";
19 | public static final String COVER = "cover_";
20 | public static String getAppDir() {
21 | return Environment.getExternalStorageDirectory().getAbsolutePath() + "/FunkMusic";
22 | }
23 |
24 | public static String getMusicDir() {
25 | String dir = getAppDir() + "/music/";
26 | return mkdirs(dir);
27 | }
28 | public static File getCacheDirFile() {
29 | String dir = getAppDir() + "/cache/";
30 | return new File(dir);
31 | }
32 | public static String getLrcDir() {
33 | String dir = getAppDir() + "/lyric/";
34 | return mkdirs(dir);
35 | }
36 |
37 | public static String getAlbumDir() {
38 | String dir = getAppDir() + "/album/";
39 | return mkdirs(dir);
40 | }
41 |
42 |
43 | private static String mkdirs(String dir) {
44 | File file = new File(dir);
45 | if (!file.exists()) {
46 | file.mkdirs();
47 | }
48 | return dir;
49 | }
50 | public static boolean exists(String path) {
51 | File file = new File(path);
52 | return file.exists();
53 | }
54 | //下载专辑封面
55 | public static void downloadAlbumCover(String picUrl, String fileName) {
56 | HttpClient.downloadFile(picUrl, FileUtils.getAlbumDir(), fileName, new HttpCallback() {
57 | @Override
58 | public void onSuccess(File file) {
59 | }
60 |
61 | @Override
62 | public void onFail(HttpException e) {
63 | }
64 |
65 | @Override
66 | public void onFinish() {
67 |
68 | }
69 | });
70 | }
71 | public static void saveLrcFile(String path, String content) {
72 | try {
73 | BufferedWriter bw = new BufferedWriter(new FileWriter(path));
74 | bw.write(content);
75 | bw.flush();
76 | bw.close();
77 | } catch (IOException e) {
78 | e.printStackTrace();
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/audiocache/GetRequest.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.audiocache;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.io.BufferedReader;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.io.InputStreamReader;
9 | import java.util.regex.Matcher;
10 | import java.util.regex.Pattern;
11 |
12 | import static com.yjl.funk.audiocache.Preconditions.checkNotNull;
13 |
14 | /**
15 | * Model for Http GET request.
16 | *
17 | * @author Alexey Danilov (danikula@gmail.com).
18 | */
19 | class GetRequest {
20 |
21 | private static final Pattern RANGE_HEADER_PATTERN = Pattern.compile("[R,r]ange:[ ]?bytes=(\\d*)-");
22 | private static final Pattern URL_PATTERN = Pattern.compile("GET /(.*) HTTP");
23 |
24 | public final String uri;
25 | public final long rangeOffset;
26 | public final boolean partial;
27 |
28 | public GetRequest(String request) {
29 | checkNotNull(request);
30 | long offset = findRangeOffset(request);
31 | this.rangeOffset = Math.max(0, offset);
32 | this.partial = offset >= 0;
33 | this.uri = findUri(request);
34 | }
35 |
36 | public static GetRequest read(InputStream inputStream) throws IOException {
37 | BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
38 | StringBuilder stringRequest = new StringBuilder();
39 | String line;
40 | while (!TextUtils.isEmpty(line = reader.readLine())) { // until new line (headers ending)
41 | stringRequest.append(line).append('\n');
42 | }
43 | return new GetRequest(stringRequest.toString());
44 | }
45 |
46 | private long findRangeOffset(String request) {
47 | Matcher matcher = RANGE_HEADER_PATTERN.matcher(request);
48 | if (matcher.find()) {
49 | String rangeValue = matcher.group(1);
50 | return Long.parseLong(rangeValue);
51 | }
52 | return -1;
53 | }
54 |
55 | private String findUri(String request) {
56 | Matcher matcher = URL_PATTERN.matcher(request);
57 | if (matcher.find()) {
58 | return matcher.group(1);
59 | }
60 | throw new IllegalArgumentException("Invalid request `" + request + "`: url not found!");
61 | }
62 |
63 | @Override
64 | public String toString() {
65 | return "GetRequest{" +
66 | "rangeOffset=" + rangeOffset +
67 | ", partial=" + partial +
68 | ", uri='" + uri + '\'' +
69 | '}';
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/ui/adapter/NewAlbumListAdapter.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.ui.adapter;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.graphics.Point;
6 | import android.support.annotation.LayoutRes;
7 | import android.text.TextUtils;
8 | import android.view.View;
9 | import android.widget.TextView;
10 |
11 | import com.chad.library.adapter.base.BaseQuickAdapter;
12 | import com.chad.library.adapter.base.BaseViewHolder;
13 | import com.jakewharton.rxbinding.view.RxView;
14 | import com.yjl.funk.R;
15 | import com.yjl.funk.imageloader.frescohelper.FrescoHelper;
16 | import com.yjl.funk.imageloader.frescoview.FrescoImageView;
17 | import com.yjl.funk.model.Album;
18 | import com.yjl.funk.ui.activity.MainActivity;
19 | import com.yjl.funk.utils.NetworkUtil;
20 | import com.yjl.funk.widget.Toasty;
21 |
22 | import java.util.List;
23 | import java.util.concurrent.TimeUnit;
24 |
25 | import rx.functions.Action1;
26 |
27 | /**
28 | * Created by Administrator on 2017/11/6.
29 | */
30 |
31 | public class NewAlbumListAdapter extends BaseQuickAdapter {
32 | private Context context;
33 | private boolean is_time;
34 | public NewAlbumListAdapter(Context context, @LayoutRes int resId, List list,boolean is_time) {
35 | super(resId, list);
36 | this.context = context;
37 | this.is_time = is_time;
38 | }
39 |
40 |
41 | @Override
42 | protected void convert(BaseViewHolder helper, final Album item) {
43 | if (item != null) {
44 | FrescoHelper.loadFrescoImage((FrescoImageView) helper.getView(R.id.iv_pic), item.getPic_big() + "@s_1,w_450,h_450", R.drawable.default_load_cover, false, new Point(400, 500));
45 | helper.setText(R.id.tv_name, item.getTitle());
46 | helper.setText(R.id.tv_describe, item.getAuthor());
47 | TextView publish = helper.getView(R.id.tv_publish_time);
48 | if(is_time)
49 | publish.setText("发布时间 " + item.getPublishtime());
50 | else publish.setVisibility(View.GONE);
51 | RxView.clicks(helper.itemView).throttleFirst(1, TimeUnit.SECONDS).subscribe(new Action1() {
52 | @Override
53 | public void call(Void aVoid) {
54 | if (NetworkUtil.isNetConnect(context)) {
55 | MainActivity.getInstance().switchAlbumInfoFragment(item.getAlbum_id());
56 | } else {
57 | Toasty.error(context, "网络无连接,请检查您的网络设置").show();
58 | }
59 | }
60 | });
61 |
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_artist_hot_song.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
19 |
20 |
29 |
30 |
39 |
40 |
53 |
54 |
61 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/imageloader/processors/MaskPostprocessor.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.imageloader.processors;
2 |
3 | /**
4 | * Copyright (C) 2015 Wasabeef
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import android.content.Context;
20 | import android.graphics.Bitmap;
21 | import android.graphics.Canvas;
22 | import android.graphics.Paint;
23 | import android.graphics.PorterDuff;
24 | import android.graphics.PorterDuffXfermode;
25 | import android.graphics.drawable.Drawable;
26 |
27 | import com.facebook.cache.common.CacheKey;
28 | import com.facebook.cache.common.SimpleCacheKey;
29 | import com.facebook.imagepipeline.request.BasePostprocessor;
30 | import com.yjl.funk.imageloader.processors.internal.Utils;
31 |
32 |
33 | public class MaskPostprocessor extends BasePostprocessor {
34 |
35 | private static Paint paint = new Paint();
36 | private Context context;
37 | private int maskId;
38 |
39 | static {
40 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
41 | }
42 |
43 | /**
44 | * @param maskId If you change the mask file, please also rename the mask file, or Glide will get
45 | * the cache with the old mask. Because getId() return the same values if using the
46 | * same make file name. If you have a good idea please tell us, thanks.
47 | */
48 | public MaskPostprocessor(Context context, int maskId) {
49 | this.context = context.getApplicationContext();
50 | this.maskId = maskId;
51 | }
52 |
53 | @Override public void process(Bitmap dest, Bitmap source) {
54 |
55 | Bitmap result =
56 | Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
57 |
58 | Drawable mask = Utils.getMaskDrawable(context, maskId);
59 |
60 | Canvas canvas = new Canvas(result);
61 | mask.setBounds(0, 0, source.getWidth(), source.getHeight());
62 | mask.draw(canvas);
63 | canvas.drawBitmap(source, 0, 0, paint);
64 |
65 | super.process(dest, result);
66 | }
67 |
68 | @Override public String getName() {
69 | return getClass().getSimpleName();
70 | }
71 |
72 | @Override public CacheKey getPostprocessorCacheKey() {
73 | return new SimpleCacheKey("mask=" + context.getResources().getResourceEntryName(maskId));
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_album_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
16 |
17 |
18 |
23 |
24 |
30 |
31 |
36 |
37 |
47 |
48 |
54 |
55 |
62 |
63 |
64 |
65 |
73 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/MyApplication.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk;
2 |
3 | import android.app.ActivityManager;
4 | import android.app.Application;
5 | import android.content.Context;
6 |
7 | import com.facebook.drawee.backends.pipeline.Fresco;
8 | import com.facebook.imagepipeline.core.ImagePipelineConfig;
9 | import com.yjl.funk.audiocache.HttpProxyCacheServer;
10 | import com.yjl.funk.imageloader.frescohelper.FrescoHelper;
11 | import com.yjl.funk.imageloader.frescohelper.MyBitmapMemoryCacheParamsSupplier;
12 | import com.yjl.funk.network.HttpInterceptor;
13 | import com.yjl.funk.utils.FileUtils;
14 | import com.zhy.http.okhttp.OkHttpUtils;
15 |
16 | import java.util.concurrent.TimeUnit;
17 |
18 | import okhttp3.OkHttpClient;
19 |
20 |
21 | /**
22 | * project:KDB—seller
23 | * Created on 2017/5/2 0002.
24 | * author :yanjinlong
25 | */
26 |
27 | public class MyApplication extends Application {
28 |
29 | private static MyApplication instance;
30 | private HttpProxyCacheServer proxy;
31 |
32 | public static HttpProxyCacheServer getProxy(Context context) {
33 | MyApplication app = (MyApplication) context.getApplicationContext();
34 | return app.proxy == null ? (app.proxy = app.newProxy()) : app.proxy;
35 | }
36 |
37 | private HttpProxyCacheServer newProxy() {
38 | return new HttpProxyCacheServer.Builder(this)
39 | .maxCacheFilesCount(10)
40 | .cacheDirectory(FileUtils.getCacheDirFile())
41 | .build();
42 | }
43 |
44 | @Override
45 | public void onCreate() {
46 | super.onCreate();
47 | if (instance == null) {
48 | synchronized (MyApplication.class) {
49 | if (instance == null) {
50 | instance= this;
51 | }
52 | }
53 | }
54 | initOkHttpUtils();
55 | ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this)
56 | .setDownsampleEnabled(true)
57 | .setBitmapMemoryCacheParamsSupplier(new MyBitmapMemoryCacheParamsSupplier((ActivityManager)getSystemService(Context.ACTIVITY_SERVICE)))
58 | .build();
59 | Fresco.initialize(this,config);
60 |
61 | }
62 | public static MyApplication getInstance() {
63 | return instance;
64 | }
65 | @Override
66 | public void onTrimMemory(int level) {
67 | super.onTrimMemory(level);
68 | FrescoHelper.trimMemory(level);
69 | }
70 |
71 |
72 | @Override
73 | public void onLowMemory() {
74 | super.onLowMemory();
75 | FrescoHelper.clearMemory();
76 | }
77 | private void initOkHttpUtils() {
78 | OkHttpClient okHttpClient = new OkHttpClient.Builder()
79 | .connectTimeout(10, TimeUnit.SECONDS)
80 | .readTimeout(10, TimeUnit.SECONDS)
81 | .writeTimeout(10, TimeUnit.SECONDS)
82 | .addInterceptor(new HttpInterceptor())
83 | .build();
84 | OkHttpUtils.initClient(okHttpClient);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
17 |
27 |
31 |
35 |
45 |
51 |
55 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/widget/AlbumIntroDialog.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.widget;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.graphics.Point;
6 | import android.text.TextUtils;
7 | import android.view.Gravity;
8 | import android.view.View;
9 | import android.view.Window;
10 | import android.view.WindowManager;
11 | import android.widget.ImageView;
12 | import android.widget.TextView;
13 |
14 | import com.jakewharton.rxbinding.view.RxView;
15 | import com.yjl.funk.R;
16 | import com.yjl.funk.imageloader.frescohelper.FrescoHelper;
17 | import com.yjl.funk.imageloader.frescoview.FrescoImageView;
18 | import com.yjl.funk.imageloader.processors.BlurPostprocessor;
19 | import com.yjl.funk.model.AlbumInfo;
20 |
21 | import java.util.concurrent.TimeUnit;
22 |
23 | import butterknife.ButterKnife;
24 | import rx.functions.Action1;
25 |
26 |
27 | /**
28 | * Created by Administrator on 2017/11/8.
29 | */
30 |
31 | public class AlbumIntroDialog extends Dialog {
32 | private Context context;
33 | private AlbumInfo info;
34 | private FrescoImageView ivBg,ivAlbum;
35 | private ImageView ivCLose;
36 | private TextView tv_name,tv_describe;
37 | public AlbumIntroDialog(Context context, AlbumInfo info) {
38 | this(context, R.style.Dialog_Fullscreen);
39 | this.context = context;
40 | this.info = info;
41 | initView();
42 | }
43 |
44 | public AlbumIntroDialog(Context context, int themeResId) {
45 | super(context, themeResId);
46 | }
47 |
48 | @Override
49 | public void onBackPressed() {
50 | super.onBackPressed();
51 | this.dismiss();
52 | }
53 | public void initView(){
54 | View view = View.inflate(context,R.layout.dialog_album_info,null);
55 | ivAlbum = ButterKnife.findById(view,R.id.iv_album_img);
56 | ivBg = ButterKnife.findById(view,R.id.iv_album_bg);
57 | tv_name = ButterKnife.findById(view,R.id.tv_album_name);
58 | tv_describe = ButterKnife.findById(view,R.id.tv_album_describe);
59 | ivCLose = ButterKnife.findById(view,R.id.iv_close);
60 | if(info!=null) {
61 | FrescoHelper.loadFrescoImageCircle(ivAlbum, info.getAlbumInfo().getPic_s500(), 0, false);
62 | FrescoHelper.loadFrescoImage(ivBg, info.getAlbumInfo().getPic_s500(), 0, false, new Point(720, 480), new BlurPostprocessor(context, 15));
63 | tv_name.setText(info.getAlbumInfo().getTitle());
64 | if(TextUtils.isEmpty(info.getAlbumInfo().getInfo()))
65 | tv_describe.setText("暂无简介");
66 | else
67 | tv_describe.setText(info.getAlbumInfo().getInfo());
68 | }
69 | RxView.clicks(ivCLose).throttleFirst(1, TimeUnit.SECONDS).subscribe(new Action1() {
70 | @Override
71 | public void call(Void aVoid) {
72 | AlbumIntroDialog.this.dismiss();
73 | }
74 | });
75 | Window dialogWindow = this.getWindow();
76 | WindowManager.LayoutParams lp = dialogWindow.getAttributes();
77 | dialogWindow.setGravity(Gravity.CENTER);
78 | this.addContentView(view,lp);
79 | }
80 |
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/ui/adapter/OnlineMusicListAdapter.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.ui.adapter;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.LayoutRes;
5 | import android.support.v4.content.ContextCompat;
6 | import android.text.TextUtils;
7 | import android.view.View;
8 | import android.widget.TextView;
9 |
10 | import com.chad.library.adapter.base.BaseQuickAdapter;
11 | import com.chad.library.adapter.base.BaseViewHolder;
12 | import com.jakewharton.rxbinding.view.RxView;
13 | import com.yjl.funk.player.MusicClient;
14 | import com.yjl.funk.R;
15 | import com.yjl.funk.imageloader.frescohelper.FrescoHelper;
16 | import com.yjl.funk.imageloader.frescoview.FrescoImageView;
17 | import com.yjl.funk.model.MusicTrack;
18 | import com.yjl.funk.utils.DensityUtils;
19 |
20 | import java.util.List;
21 | import java.util.concurrent.TimeUnit;
22 |
23 | import rx.functions.Action1;
24 |
25 | /**
26 | * Created by Administrator on 2017/11/7.
27 | */
28 |
29 | public class OnlineMusicListAdapter extends BaseQuickAdapter {
30 | private Context context;
31 | private boolean is_rank, is_img;//是否显示排名 是否显示图片
32 | private List list;
33 |
34 | public OnlineMusicListAdapter(Context context, @LayoutRes int resId, List list, boolean is_rank, boolean is_img) {
35 | super(resId, list);
36 | this.context = context;
37 | this.is_rank = is_rank;
38 | this.is_img = is_img;
39 | this.list = list;
40 | }
41 |
42 | @Override
43 | protected void convert(final BaseViewHolder helper, MusicTrack item) {
44 | TextView rank = helper.getView(R.id.tv_rank);
45 | if (is_rank) {
46 | if (helper.getLayoutPosition() < 3) {
47 | rank.setTextColor(ContextCompat.getColor(context, R.color.colorAccent));
48 | } else {
49 | rank.setTextColor(ContextCompat.getColor(context, R.color.text_gray));
50 | }
51 | rank.setText(String.valueOf(helper.getLayoutPosition() + 1));
52 | } else {
53 | rank.setVisibility(View.GONE);
54 | }
55 | helper.setText(R.id.tv_name, item.getTitle());
56 | helper.setText(R.id.tv_describe, item.getAuthor() + " · " + item.getAlbum_title());
57 | if (is_img) {
58 | String cover = "";
59 | if(TextUtils.isEmpty(item.getPic_big())){
60 | if(!TextUtils.isEmpty(item.getPic_small()))
61 | cover = item.getPic_small().split("\\@")[0]+"@s_1,w_500,h_500";
62 |
63 | }else {
64 | cover = item.getPic_big();
65 | }
66 | FrescoHelper.loadFrescoImage((FrescoImageView) helper.getView(R.id.iv_song),cover, R.drawable.default_load_cover_small, DensityUtils.dip2px(context, 2), false);
67 | }else
68 | helper.setVisible(R.id.iv_song, false);
69 |
70 | RxView.clicks(helper.itemView).throttleFirst(1, TimeUnit.SECONDS).subscribe(new Action1() {
71 | @Override
72 | public void call(Void aVoid) {
73 | MusicClient.setPlayListAndPlayAt(list, helper.getLayoutPosition());
74 | }
75 | });
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_notification.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
26 |
27 |
36 |
37 |
46 |
47 |
48 |
52 |
53 |
61 |
62 |
70 |
71 |
79 |
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/audiocache/file/Files.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.audiocache.file;
2 |
3 |
4 | import java.io.File;
5 | import java.io.IOException;
6 | import java.io.RandomAccessFile;
7 | import java.util.Arrays;
8 | import java.util.Collections;
9 | import java.util.Comparator;
10 | import java.util.Date;
11 | import java.util.LinkedList;
12 | import java.util.List;
13 |
14 | /**
15 | * Utils for work with files.
16 | *
17 | * @author Alexey Danilov (danikula@gmail.com).
18 | */
19 | class Files {
20 |
21 |
22 | static void makeDir(File directory) throws IOException {
23 | if (directory.exists()) {
24 | if (!directory.isDirectory()) {
25 | throw new IOException("File " + directory + " is not directory!");
26 | }
27 | } else {
28 | boolean isCreated = directory.mkdirs();
29 | if (!isCreated) {
30 | throw new IOException(String.format("Directory %s can't be created", directory.getAbsolutePath()));
31 | }
32 | }
33 | }
34 |
35 | static List getLruListFiles(File directory) {
36 | List result = new LinkedList<>();
37 | File[] files = directory.listFiles();
38 | if (files != null) {
39 | result = Arrays.asList(files);
40 | Collections.sort(result, new LastModifiedComparator());
41 | }
42 | return result;
43 | }
44 |
45 | static void setLastModifiedNow(File file) throws IOException {
46 | if (file.exists()) {
47 | long now = System.currentTimeMillis();
48 | boolean modified = file.setLastModified(now); // on some devices (e.g. Nexus 5) doesn't work
49 | if (!modified) {
50 | modify(file);
51 | if (file.lastModified() < now) {
52 | // NOTE: apparently this is a known issue (see: http://stackoverflow.com/questions/6633748/file-lastmodified-is-never-what-was-set-with-file-setlastmodified)
53 | }
54 | }
55 | }
56 | }
57 |
58 | static void modify(File file) throws IOException {
59 | long size = file.length();
60 | if (size == 0) {
61 | recreateZeroSizeFile(file);
62 | return;
63 | }
64 |
65 | RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
66 | accessFile.seek(size - 1);
67 | byte lastByte = accessFile.readByte();
68 | accessFile.seek(size - 1);
69 | accessFile.write(lastByte);
70 | accessFile.close();
71 | }
72 |
73 | private static void recreateZeroSizeFile(File file) throws IOException {
74 | if (!file.delete() || !file.createNewFile()) {
75 | throw new IOException("Error recreate zero-size file " + file);
76 | }
77 | }
78 |
79 | private static final class LastModifiedComparator implements Comparator {
80 |
81 | @Override
82 | public int compare(File lhs, File rhs) {
83 | return compareLong(lhs.lastModified(), rhs.lastModified());
84 | }
85 |
86 | private int compareLong(long first, long second) {
87 | return (first < second) ? -1 : ((first == second) ? 0 : 1);
88 | }
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/audiocache/StorageUtils.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.audiocache;
2 |
3 | import android.content.Context;
4 | import android.os.Environment;
5 |
6 |
7 | import java.io.File;
8 |
9 | import static android.os.Environment.MEDIA_MOUNTED;
10 |
11 | /**
12 | * Provides application storage paths
13 | *
14 | * See https://github.com/nostra13/Android-Universal-Image-Loader
15 | *
16 | * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
17 | * @since 1.0.0
18 | */
19 | final class StorageUtils {
20 |
21 | private static final String INDIVIDUAL_DIR_NAME = "video-cache";
22 |
23 | /**
24 | * Returns individual application cache directory (for only video caching from Proxy). Cache directory will be
25 | * created on SD card ("/Android/data/[app_package_name]/cache/video-cache") if card is mounted .
26 | * Else - Android defines cache directory on device's file system.
27 | *
28 | * @param context Application context
29 | * @return Cache {@link File directory}
30 | */
31 | public static File getIndividualCacheDirectory(Context context) {
32 | File cacheDir = getCacheDirectory(context, true);
33 | return new File(cacheDir, INDIVIDUAL_DIR_NAME);
34 | }
35 |
36 | /**
37 | * Returns application cache directory. Cache directory will be created on SD card
38 | * ("/Android/data/[app_package_name]/cache") (if card is mounted and app has appropriate permission) or
39 | * on device's file system depending incoming parameters.
40 | *
41 | * @param context Application context
42 | * @param preferExternal Whether prefer external location for cache
43 | * @return Cache {@link File directory}.
44 | * NOTE: Can be null in some unpredictable cases (if SD card is unmounted and
45 | * {@link Context#getCacheDir() Context.getCacheDir()} returns null).
46 | */
47 | private static File getCacheDirectory(Context context, boolean preferExternal) {
48 | File appCacheDir = null;
49 | String externalStorageState;
50 | try {
51 | externalStorageState = Environment.getExternalStorageState();
52 | } catch (NullPointerException e) { // (sh)it happens
53 | externalStorageState = "";
54 | }
55 | if (preferExternal && MEDIA_MOUNTED.equals(externalStorageState)) {
56 | appCacheDir = getExternalCacheDir(context);
57 | }
58 | if (appCacheDir == null) {
59 | appCacheDir = context.getCacheDir();
60 | }
61 | if (appCacheDir == null) {
62 | String cacheDirPath = "/data/data/" + context.getPackageName() + "/cache/";
63 | appCacheDir = new File(cacheDirPath);
64 | }
65 | return appCacheDir;
66 | }
67 |
68 | private static File getExternalCacheDir(Context context) {
69 | File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data");
70 | File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache");
71 | if (!appCacheDir.exists()) {
72 | if (!appCacheDir.mkdirs()) {
73 |
74 | return null;
75 | }
76 | }
77 | return appCacheDir;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/service/ServiceStub.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.service;
2 |
3 | import android.os.RemoteException;
4 |
5 | import com.yjl.funk.IFunkService;
6 | import com.yjl.funk.model.MusicTrack;
7 |
8 | import java.lang.ref.WeakReference;
9 | import java.util.List;
10 |
11 | public class ServiceStub extends IFunkService.Stub {
12 |
13 | private final WeakReference mService;
14 |
15 | public ServiceStub(final FunkMusicService service) {
16 | mService = new WeakReference(service);
17 | }
18 |
19 |
20 | @Override
21 | public void play(int position) throws RemoteException {
22 | mService.get().play(position);
23 | }
24 |
25 | @Override
26 | public void setPlayListAndPlay(List tracks, int position) throws RemoteException {
27 | mService.get().setPlayListAndPlayAt(tracks,position);
28 | }
29 |
30 | @Override
31 | public MusicTrack getCurrentTrack() throws RemoteException {
32 | return mService.get().getCurrentMusicTrack();
33 | }
34 |
35 | @Override
36 | public List getPlayList() throws RemoteException {
37 | return mService.get().getPlayList();
38 | }
39 |
40 | @Override
41 | public void setPlayMode(int mode) throws RemoteException {
42 | mService.get().setPlayMode(mode);
43 | }
44 |
45 | @Override
46 | public int getPlayMode() throws RemoteException {
47 | return mService.get().getPlayMode();
48 | }
49 |
50 | @Override
51 | public int getNowPlayingPosition() throws RemoteException {
52 | return mService.get().getCurrentPlayListPosition();
53 | }
54 |
55 | @Override
56 | public boolean isPlaying() throws RemoteException {
57 | return mService.get().isPlaying();
58 | }
59 |
60 | @Override
61 | public boolean isPreparing() throws RemoteException {
62 | return mService.get().isPreparing();
63 | }
64 |
65 | @Override
66 | public boolean isPausing() throws RemoteException {
67 | return mService.get().isPausing();
68 | }
69 |
70 | @Override
71 | public boolean isIdle() throws RemoteException {
72 | return mService.get().isIDLE();
73 | }
74 |
75 | @Override
76 | public int duration() throws RemoteException {
77 | return mService.get().duration();
78 | }
79 |
80 | @Override
81 | public int position() throws RemoteException {
82 | return mService.get().position();
83 | }
84 |
85 | @Override
86 | public int secondPosition() throws RemoteException {
87 | return mService.get().secondPosition();
88 | }
89 |
90 | @Override
91 | public void playOrPause() throws RemoteException {
92 | mService.get().playOrPause();
93 | }
94 |
95 | @Override
96 | public void next() throws RemoteException {
97 | mService.get().next();
98 | }
99 |
100 | @Override
101 | public void prev() throws RemoteException {
102 | mService.get().prev();
103 | }
104 |
105 | @Override
106 | public void seekTo(int progress) throws RemoteException {
107 | mService.get().seek(progress);
108 | }
109 |
110 | }
111 |
112 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_special_music.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
19 |
20 |
24 |
25 |
30 |
31 |
49 |
50 |
51 |
65 |
66 |
78 |
79 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/imageloader/frescoview/FrescoController.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.imageloader.frescoview;
2 |
3 | import com.facebook.drawee.controller.ControllerListener;
4 | import com.facebook.drawee.drawable.ScalingUtils;
5 | import com.facebook.drawee.generic.RoundingParams;
6 | import com.facebook.imagepipeline.request.Postprocessor;
7 |
8 | /**
9 | * Created by Linhh on 16/3/2.
10 | */
11 | public interface FrescoController {
12 |
13 | public final static String HTTP_PERFIX = "http://";
14 | public final static String HTTPS_PERFIX = "https://";
15 | public final static String FILE_PERFIX = "file://";
16 |
17 | /**
18 | * 加载网络图片
19 | * @param lowUrl 低分辨率图片
20 | * @param url 网络图片
21 | * @param defaultResID 默认图
22 | */
23 | public void loadView(String lowUrl, String url, int defaultResID);
24 |
25 | /**
26 | * 加载网络图片
27 | * @param url 网络图片
28 | * @param defaultResID 默认图
29 | */
30 | public void loadView(String url, int defaultResID);
31 |
32 | /**
33 | * 加载本地图片
34 | * @param path 图片路劲
35 | * @param defaultRes 默认图
36 | */
37 | public void loadLocalImage(String path, int defaultRes);
38 |
39 | /**
40 | * 将该Fresco处理为圆形
41 | */
42 | public void asCircle();
43 |
44 | /**
45 | * 用一种颜色来遮挡View以实现圆形,在一些内存较低的机器上推荐使用
46 | * @param overlay_color
47 | */
48 | public void setCircle(int overlay_color);
49 |
50 | /**
51 | * 设置圆角
52 | * @param radius
53 | */
54 | public void setCornerRadius(float radius);
55 |
56 | /**
57 | * 用一种颜色来遮挡View以实现圆角,在一些内存较低的机器上推荐使用
58 | * @param radius
59 | * @param overlay_color
60 | */
61 | public void setCornerRadius(float radius, int overlay_color);
62 |
63 | /**
64 | * 设置边框
65 | * @param color
66 | * @param width
67 | */
68 | public void setBorder(int color, float width);
69 |
70 | /**
71 | * 清除所使用的RoundingParams
72 | */
73 | public void clearRoundingParams();
74 |
75 | /**
76 | * 设置RoundingParams
77 | * @param roundingParmas
78 | */
79 | public void setRoundingParmas(RoundingParams roundingParmas);
80 |
81 | /**
82 | * 设置下载监听器
83 | * @param controllerListener
84 | */
85 | public void setControllerListener(ControllerListener controllerListener);
86 |
87 |
88 | /**
89 | * 设置后处理
90 | * @param postProcessor
91 | */
92 | public void setPostProcessor(Postprocessor postProcessor);
93 |
94 |
95 | /**
96 | * 是否开启动画
97 | * @param anim
98 | */
99 | public void setAnim(boolean anim);
100 |
101 | /**
102 | * 是否可以点击重试
103 | * @param tapToRetryEnabled
104 | */
105 | public void setTapToRetryEnabled(boolean tapToRetryEnabled);
106 |
107 | /**
108 | * 是否自动旋转
109 | * @param autoRotateEnabled
110 | */
111 | public void setAutoRotateEnabled(boolean autoRotateEnabled);
112 |
113 | /**
114 | * 设置图片缩放type
115 | * @param scaleType
116 | */
117 | public void setActualImageScaleType(ScalingUtils.ScaleType scaleType);
118 |
119 | /**
120 | * 设置图片切换动时间
121 | * @param time
122 | * */
123 | public void setFadeTime(int time);
124 |
125 | }
126 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/audiocache/ProxyCacheUtils.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.audiocache;
2 |
3 | import android.text.TextUtils;
4 | import android.webkit.MimeTypeMap;
5 |
6 | import java.io.Closeable;
7 | import java.io.IOException;
8 | import java.io.UnsupportedEncodingException;
9 | import java.net.URLDecoder;
10 | import java.net.URLEncoder;
11 | import java.security.MessageDigest;
12 | import java.security.NoSuchAlgorithmException;
13 | import java.util.Arrays;
14 |
15 | import static com.yjl.funk.audiocache.Preconditions.checkArgument;
16 | import static com.yjl.funk.audiocache.Preconditions.checkNotNull;
17 |
18 |
19 | /**
20 | * Just simple utils.
21 | *
22 | * @author Alexey Danilov (danikula@gmail.com).
23 | */
24 | public class ProxyCacheUtils {
25 |
26 | static final int DEFAULT_BUFFER_SIZE = 8 * 1024;
27 | static final int MAX_ARRAY_PREVIEW = 16;
28 |
29 | static String getSupposablyMime(String url) {
30 | MimeTypeMap mimes = MimeTypeMap.getSingleton();
31 | String extension = MimeTypeMap.getFileExtensionFromUrl(url);
32 | return TextUtils.isEmpty(extension) ? null : mimes.getMimeTypeFromExtension(extension);
33 | }
34 |
35 | static void assertBuffer(byte[] buffer, long offset, int length) {
36 | checkNotNull(buffer, "Buffer must be not null!");
37 | checkArgument(offset >= 0, "Data offset must be positive!");
38 | checkArgument(length >= 0 && length <= buffer.length, "Length must be in range [0..buffer.length]");
39 | }
40 |
41 | static String preview(byte[] data, int length) {
42 | int previewLength = Math.min(MAX_ARRAY_PREVIEW, Math.max(length, 0));
43 | byte[] dataRange = Arrays.copyOfRange(data, 0, previewLength);
44 | String preview = Arrays.toString(dataRange);
45 | if (previewLength < length) {
46 | preview = preview.substring(0, preview.length() - 1) + ", ...]";
47 | }
48 | return preview;
49 | }
50 |
51 | static String encode(String url) {
52 | try {
53 | return URLEncoder.encode(url, "utf-8");
54 | } catch (UnsupportedEncodingException e) {
55 | throw new RuntimeException("Error encoding url", e);
56 | }
57 | }
58 |
59 | static String decode(String url) {
60 | try {
61 | return URLDecoder.decode(url, "utf-8");
62 | } catch (UnsupportedEncodingException e) {
63 | throw new RuntimeException("Error decoding url", e);
64 | }
65 | }
66 |
67 | static void close(Closeable closeable) {
68 | if (closeable != null) {
69 | try {
70 | closeable.close();
71 | } catch (IOException e) {
72 | }
73 | }
74 | }
75 |
76 | public static String computeMD5(String string) {
77 | try {
78 | MessageDigest messageDigest = MessageDigest.getInstance("MD5");
79 | byte[] digestBytes = messageDigest.digest(string.getBytes());
80 | return bytesToHexString(digestBytes);
81 | } catch (NoSuchAlgorithmException e) {
82 | throw new IllegalStateException(e);
83 | }
84 | }
85 |
86 | private static String bytesToHexString(byte[] bytes) {
87 | StringBuffer sb = new StringBuffer();
88 | for (byte b : bytes) {
89 | sb.append(String.format("%02x", b));
90 | }
91 | return sb.toString();
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/app/src/main/java/com/yjl/funk/handler/MusicPlayerHandler.java:
--------------------------------------------------------------------------------
1 | package com.yjl.funk.handler;
2 |
3 | import android.media.AudioManager;
4 | import android.media.MediaPlayer;
5 | import android.os.Handler;
6 | import android.os.Looper;
7 | import android.os.Message;
8 |
9 | import com.yjl.funk.service.FunkMusicService;
10 |
11 | import java.lang.ref.WeakReference;
12 |
13 | import static com.yjl.funk.player.Constants.FADEDOWN;
14 | import static com.yjl.funk.player.Constants.FADEUP;
15 | import static com.yjl.funk.player.Constants.FOCUSCHANGE;
16 |
17 | /**
18 | * MediaPLayer 控制Handler
19 | **/
20 | public class MusicPlayerHandler extends Handler {
21 | private final WeakReference mService;
22 | private float mCurrentVolume = 1.0f;
23 | private MediaPlayer mPlayer;
24 |
25 | public MusicPlayerHandler(final FunkMusicService service, MediaPlayer player, final Looper looper) {
26 | super(looper);
27 | mService = new WeakReference(service);
28 | this.mPlayer = player;
29 | }
30 |
31 |
32 | @Override
33 | public void handleMessage(final Message msg) {
34 | final FunkMusicService service = mService.get();
35 | if (service == null) {
36 | return;
37 | }
38 | synchronized (service) {
39 | switch (msg.what) {
40 | case FADEDOWN:
41 | mCurrentVolume -= .05f;
42 | if (mCurrentVolume > .2f) {
43 | sendEmptyMessageDelayed(FADEDOWN, 10);
44 | } else {
45 | mCurrentVolume = .2f;
46 | }
47 | mPlayer.setVolume(mCurrentVolume,mCurrentVolume);
48 | break;
49 | case FADEUP:
50 | mCurrentVolume += .01f;
51 | if (mCurrentVolume < 1.0f) {
52 | sendEmptyMessageDelayed(FADEUP, 10);
53 | } else {
54 | mCurrentVolume = 1.0f;
55 | }
56 | mPlayer.setVolume(mCurrentVolume,mCurrentVolume);
57 | break;
58 | case FOCUSCHANGE:
59 | switch (msg.arg1) {
60 | case AudioManager.AUDIOFOCUS_LOSS:
61 | case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
62 | service.pause();
63 | break;
64 | case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
65 | removeMessages(FADEUP);
66 | sendEmptyMessage(FADEDOWN);
67 | break;
68 | case AudioManager.AUDIOFOCUS_GAIN:
69 | if (!service.isPlaying()) {
70 | mCurrentVolume = 0f;
71 | service.mPlayer.setVolume(mCurrentVolume,mCurrentVolume);
72 | service.start();
73 | } else {
74 | removeMessages(FADEDOWN);
75 | sendEmptyMessage(FADEUP);
76 | }
77 | break;
78 | }
79 | break;
80 | default:
81 | break;
82 | }
83 | }
84 | }
85 | }
--------------------------------------------------------------------------------