package me.wcy.music.application;
import android.app.Application;
import android.content.Intent;
import me.wcy.music.service.PlayService;
import me.wcy.music.storage.db.DBManager;
/**
* 自定义Application
* Created by wcy on 2015/11/27.
*/
public class MusicApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
AppCache.get().init(this);
ForegroundObserver.init(this);
DBManager.get().init(this);
Intent intent = new Intent(this, PlayService.class);
startService(intent);
}
}
package me.wcy.music.application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.support.v4.app.NotificationCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RemoteViews;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import me.wcy.music.R;
import me.wcy.music.activity.MusicActivity;
import me.wcy.music.constants.Extras;
import me.wcy.music.model.Music;
import me.wcy.music.receiver.StatusBarReceiver;
import me.wcy.music.service.PlayService;
import me.wcy.music.utils.CoverLoader;
import me.wcy.music.utils.FileUtils;
/**
* Created by wcy on 2017/4/18.
*/
public class Notifier {
private static final int NOTIFICATION_ID = 0x111;
private PlayService playService;
private NotificationManager notificationManager;
public static Notifier get() {
return SingletonHolder.instance;
}
private static class SingletonHolder {
private static Notifier instance = new Notifier();
}
private Notifier() {
}
public void init(PlayService playService) {
this.playService = playService;
notificationManager = (NotificationManager) playService.getSystemService(Context.NOTIFICATION_SERVICE);
}
public void showPlay(Music music) {
if (music == null) {
return;
}
playService.startForeground(NOTIFICATION_ID, buildNotification(playService, music, true));
}
public void showPause(Music music) {
if (music == null) {
return;
}
playService.stopForeground(false);
notificationManager.notify(NOTIFICATION_ID, buildNotification(playService, music, false));
}
public void cancelAll() {
notificationManager.cancelAll();
}
private Notification buildNotification(Context context, Music music, boolean isPlaying) {
Intent intent = new Intent(context, MusicActivity.class);
intent.putExtra(Extras.EXTRA_NOTIFICATION, true);
intent.setAction(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.ic_notification)
.setCustomContentView(getRemoteViews(context, music, isPlaying));
return builder.build();
}
private RemoteViews getRemoteViews(Context context, Music music, boolean isPlaying) {
String title = music.getTitle();
String subtitle = FileUtils.getArtistAndAlbum(music.getArtist(), music.getAlbum());
Bitmap cover = CoverLoader.get().loadThumb(music);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.notification);
if (cover != null) {
remoteViews.setImageViewBitmap(R.id.iv_icon, cover);
} else {
remoteViews.setImageViewResource(R.id.iv_icon, R.drawable.ic_launcher);
}
remoteViews.setTextViewText(R.id.tv_title, title);
remoteViews.setTextViewText(R.id.tv_subtitle, subtitle);
boolean isLightNotificationTheme = isLightNotificationTheme(playService);
Intent playIntent = new Intent(StatusBarReceiver.ACTION_STATUS_BAR);
playIntent.putExtra(StatusBarReceiver.EXTRA, StatusBarReceiver.EXTRA_PLAY_PAUSE);
PendingIntent playPendingIntent = PendingIntent.getBroadcast(context, 0, playIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setImageViewResource(R.id.iv_play_pause, getPlayIconRes(isLightNotificationTheme, isPlaying));
remoteViews.setOnClickPendingIntent(R.id.iv_play_pause, playPendingIntent);
Intent nextIntent = new Intent(StatusBarReceiver.ACTION_STATUS_BAR);
nextIntent.putExtra(StatusBarReceiver.EXTRA, StatusBarReceiver.EXTRA_NEXT);
PendingIntent nextPendingIntent = PendingIntent.getBroadcast(context, 1, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setImageViewResource(R.id.iv_next, getNextIconRes(isLightNotificationTheme));
remoteViews.setOnClickPendingIntent(R.id.iv_next, nextPendingIntent);
return remoteViews;
}
private int getPlayIconRes(boolean isLightNotificationTheme, boolean isPlaying) {
if (isPlaying) {
return isLightNotificationTheme
? R.drawable.ic_status_bar_pause_dark_selector
: R.drawable.ic_status_bar_pause_light_selector;
} else {
return isLightNotificationTheme
? R.drawable.ic_status_bar_play_dark_selector
: R.drawable.ic_status_bar_play_light_selector;
}
}
private int getNextIconRes(boolean isLightNotificationTheme) {
return isLightNotificationTheme
? R.drawable.ic_status_bar_next_dark_selector
: R.drawable.ic_status_bar_next_light_selector;
}
private boolean isLightNotificationTheme(Context context) {
int notificationTextColor = getNotificationTextColor(context);
return isSimilarColor(Color.BLACK, notificationTextColor);
}
private int getNotificationTextColor(Context context) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Notification notification = builder.build();
RemoteViews remoteViews = notification.contentView;
if (remoteViews == null) {
return Color.BLACK;
}
int layoutId = remoteViews.getLayoutId();
ViewGroup notificationLayout = (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null);
TextView title = notificationLayout.findViewById(android.R.id.title);
if (title != null) {
return title.getCurrentTextColor();
} else {
return findTextColor(notificationLayout);
}
}
/**
* 如果通过 android.R.id.title 无法获得 title ,
* 则通过遍历 notification 布局找到 textSize 最大的 TextView ,应该就是 title 了。
*/
private int findTextColor(ViewGroup notificationLayout) {
List<TextView> textViewList = new ArrayList<>();
findTextView(notificationLayout, textViewList);
float maxTextSize = -1;
TextView maxTextView = null;
for (TextView textView : textViewList) {
if (textView.getTextSize() > maxTextSize) {
maxTextView = textView;
}
}
if (maxTextView != null) {
return maxTextView.getCurrentTextColor();
}
return Color.BLACK;
}
private void findTextView(View view, List<TextView> textViewList) {
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
findTextView(viewGroup.getChildAt(i), textViewList);
}
} else if (view instanceof TextView) {
textViewList.add((TextView) view);
}
}
private boolean isSimilarColor(int baseColor, int color) {
int simpleBaseColor = baseColor | 0xff000000;
int simpleColor = color | 0xff000000;
int baseRed = Color.red(simpleBaseColor) - Color.red(simpleColor);
int baseGreen = Color.green(simpleBaseColor) - Color.green(simpleColor);
int baseBlue = Color.blue(simpleBaseColor) - Color.blue(simpleColor);
double value = Math.sqrt(baseRed * baseRed + baseGreen * baseGreen + baseBlue * baseBlue);
return value < 180.0;
}
}
package me.wcy.music.http;
public abstract class HttpCallback<T> {
public abstract void onSuccess(T t);
public abstract void onFail(Exception e);
public void onFinish() {
}
}
package me.wcy.music.http;
import android.graphics.Bitmap;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.BitmapCallback;
import com.zhy.http.okhttp.callback.FileCallBack;
import java.io.File;
import java.util.concurrent.TimeUnit;
import me.wcy.music.model.ArtistInfo;
import me.wcy.music.model.DownloadInfo;
import me.wcy.music.model.Lrc;
import me.wcy.music.model.OnlineMusicList;
import me.wcy.music.model.SearchMusic;
import me.wcy.music.model.Splash;
import okhttp3.Call;
import okhttp3.OkHttpClient;
public class HttpClient {
private static final String SPLASH_URL = "http://localhost:8080";
private static final String BASE_URL = "http://music.163.com/song/media/outer/";
private static final String METHOD_GET_MUSIC_LIST = "baidu.ting.billboard.billList";
private static final String METHOD_DOWNLOAD_MUSIC = "baidu.ting.song.play";
private static final String METHOD_ARTIST_INFO = "baidu.ting.artist.getInfo";
private static final String METHOD_SEARCH_MUSIC = "baidu.ting.search.catalogSug";
private static final String METHOD_LRC = "baidu.ting.song.lry";
private static final String PARAM_METHOD = "method";
private static final String PARAM_TYPE = "type";
private static final String PARAM_SIZE = "size";
private static final String PARAM_OFFSET = "offset";
private static final String PARAM_SONG_ID = "songid";
private static final String PARAM_TING_UID = "tinguid";
private static final String PARAM_QUERY = "query";
static {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.addInterceptor(new HttpInterceptor())
.build();
OkHttpUtils.initClient(okHttpClient);
}
public static void getSplash(@NonNull final HttpCallback<Splash> callback) {
OkHttpUtils.get().url(SPLASH_URL).build()
.execute(new JsonCallback<Splash>(Splash.class) {
@Override
public void onResponse(Splash response, int id) {
callback.onSuccess(response);
}
@Override
public void onError(Call call, Exception e, int id) {
callback.onFail(e);
}
@Override
public void onAfter(int id) {
callback.onFinish();
}
});
}
public static void downloadFile(String url, String destFileDir, String destFileName, @Nullable final HttpCallback<File> callback) {
OkHttpUtils.get().url(url).build()
.execute(new FileCallBack(destFileDir, destFileName) {
@Override
public void inProgress(float progress, long total, int id) {
}
@Override
public void onResponse(File file, int id) {
if (callback != null) {
callback.onSuccess(file);
}
}
@Override
public void onError(Call call, Exception e, int id) {
if (callback != null) {
callback.onFail(e);
}
}
@Override
public void onAfter(int id) {
if (callback != null) {
callback.onFinish();
}
}
});
}
public static void getSongListInfo(String type, int size, int offset, @NonNull final HttpCallback<OnlineMusicList> callback) {
OkHttpUtils.get().url(BASE_URL)
.addParams(PARAM_METHOD, METHOD_GET_MUSIC_LIST)
.addParams(PARAM_TYPE, type)
.addParams(PARAM_SIZE, String.valueOf(size))
.addParams(PARAM_OFFSET, String.valueOf(offset))
.build()
.execute(new JsonCallback<OnlineMusicList>(OnlineMusicList.class) {
@Override
public void onResponse(OnlineMusicList response, int id) {
callback.onSuccess(response);
}
@Override
public void onError(Call call, Exception e, int id) {
callback.onFail(e);
}
@Override
public void onAfter(int id) {
callback.onFinish();
}
});
}
public static void getMusicDownloadInfo(String songId, @NonNull final HttpCallback<DownloadInfo> callback) {
OkHttpUtils.get().url(BASE_URL)
.addParams(PARAM_METHOD, METHOD_DOWNLOAD_MUSIC)
.addParams(PARAM_SONG_ID, songId)
.build()
.execute(new JsonCallback<DownloadInfo>(DownloadInfo.class) {
@Override
public void onResponse(DownloadInfo response, int id) {
callback.onSuccess(response);
}
@Override
public void onError(Call call, Exception e, int id) {
callback.onFail(e);
}
@Override
public void onAfter(int id) {
callback.onFinish();
}
});
}
public static void getBitmap(String url, @NonNull final HttpCallback<Bitmap> callback) {
OkHttpUtils.get().url(url).build()
.execute(new BitmapCallback() {
@Override
public void onResponse(Bitmap bitmap, int id) {
callback.onSuccess(bitmap);
}
@Override
public void onError(Call call, Exception e, int id) {
callback.onFail(e);
}
@Override
public void onAfter(int id) {
callback.onFinish();
}
});
}
public static void getLrc(String songId, @NonNull final HttpCallback<Lrc> callback) {
OkHttpUtils.get().url(BASE_URL)
.addParams(PARAM_METHOD, METHOD_LRC)
.addParams(PARAM_SONG_ID, songId)
.build()
.execute(new JsonCallback<Lrc>(Lrc.class) {
@Override
public void onResponse(Lrc response, int id) {
callback.onSuccess(response);
}
@Override
public void onError(Call call, Exception e, int id) {
callback.onFail(e);
}
@Override
public void onAfter(int id) {
callback.onFinish();
}
});
}
public static void searchMusic(String keyword, @NonNull final HttpCallback<SearchMusic> callback) {
OkHttpUtils.get().url(BASE_URL)
.addParams(PARAM_METHOD, METHOD_SEARCH_MUSIC)
.addParams(PARAM_QUERY, keyword)
.build()
.execute(new JsonCallback<SearchMusic>(SearchMusic.class) {
@Override
public void onResponse(SearchMusic response, int id) {
callback.onSuccess(response);
}
@Override
public void onError(Call call, Exception e, int id) {
callback.onFail(e);
}
@Override
public void onAfter(int id) {
callback.onFinish();
}
});
}
public static void getArtistInfo(String tingUid, @NonNull final HttpCallback<ArtistInfo> callback) {
OkHttpUtils.get().url(BASE_URL)
.addParams(PARAM_METHOD, METHOD_ARTIST_INFO)
.addParams(PARAM_TING_UID, tingUid)
.build()
.execute(new JsonCallback<ArtistInfo>(ArtistInfo.class) {
@Override
public void onResponse(ArtistInfo response, int id) {
callback.onSuccess(response);
}
@Override
public void onError(Call call, Exception e, int id) {
callback.onFail(e);
}
@Override
public void onAfter(int id) {
callback.onFinish();
}
});
}
}