Android 音乐APP(四)显示专辑图片、本地数据库、自定义通知栏样式、通知栏显示(1)

android:onClick=“onClick”

android:orientation=“vertical”>

<ImageView

android:layout_width=“@dimen/dp_40”

android:layout_height=“@dimen/dp_40”

android:src=“@mipmap/icon_local” />

<TextView

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_marginTop=“@dimen/dp_8”

android:text=“本地音乐”

android:textColor=“@color/white”

android:textSize=“@dimen/sp_14” />

<TextView

android:id=“@+id/tv_local_music_num”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_marginTop=“@dimen/dp_4”

android:text=“0”

android:textColor=“@color/white_8”

android:textSize=“@dimen/sp_12” />

加了一个本地音乐的数量。这样用户可以更好的感知当前音乐有多少,而不用到LocalMusicActivity中查看了。布局有了,下面自然要改动UI了。回到MainActivity,

/**

  • 本地音乐数量

*/

private TextView tvLocalMusicNum;

然后在initData下,绑定这个控件。

在这里插入图片描述

现在这个控件可以正常使用了,重写onResume方法

@Override

protected void onResume() {

super.onResume();

BLog.d(TAG, “onResume”);

mList = LitePal.findAll(Song.class);

tvLocalMusicNum.setText(String.valueOf(mList.size()));

}

在这里显示歌曲的数量。然后可以运行测试一波,看看效果如何。

在这里插入图片描述

效果显著,下面进入下一环境,通知栏的显示。

③ 自定义通知栏样式、通知栏显示


说道后台播放,可能不了解的人觉得很难,一听头都大了,后台这两个字,一听就是要掉头发的节奏,首先不要有这样的心理,代码又不是洪荒猛兽,又不会吃了你,所以不要怕,恐惧会让你止步不前的,进而颓废。后台,相信你在了解Android的四大组件的时候就知道了,后台最多的是什么?Service,就是服务,这个东西你是看不见的,所以理解起来就没有那么容易,但是你能感觉得到。比如过放音乐,你是听到的音乐。其实放音乐对于用户来说就是禁止的,因为你看不出什么名堂,你是用听的,为了让用户知道现在正在播放音乐,就会有播放的进度条,播放的状态,这些动态效果的支撑就来源于后台的服务,比如你就拿现在这个APP来说,你现在播放一首歌,然后你点击home键回到手机桌面,音乐还是在播放的,这时候音乐就是在后台的,但是你看不见,你能听见。

说了这么多都是概念性的东西,为什么要用服务在后台播放音乐呢?音乐你播放一首歌,就是在整个APP任何地方你都要知道这个歌曲当前的状态和播放进度,针对于这个需求,用Service来实现无疑是最好的方式,没有之一。下面在com.llw.goodmusic下新建一个service包,在这里插入图片描述

然后新建一个Service。命名为MusicService。

在这里插入图片描述

点击Finish就创建完成了。我自己创建一个MusicService类然后继承Service也是一样的呀。那么我这样创建有什么好处呢?打开AndroidManifest.xml

在这里插入图片描述

可以看到,自动生成了Service的配置,就不需要我们手动再去写配置了,有的时候写代码往往会忘记这一步,通过AS来创建Service就避免了这个问题,何乐而不为呢?

现在MusicService创建好了,那么这个服务要做什么事情呢?首先要播放音乐,然后就是通知栏显示,之后才是通知栏和Activity之间的通信。

在layout下创建一个notification.xml。里面的代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:orientation=“horizontal”>

<ImageView

android:id=“@+id/iv_album_cover”

android:layout_width=“64dp”

android:layout_height=“64dp”

android:src=“@mipmap/icon_notification_default” />

<LinearLayout

android:gravity=“center_vertical”

android:paddingStart=“@dimen/dp_12”

android:paddingEnd=“@dimen/dp_6”

android:orientation=“vertical”

android:layout_width=“match_parent”

android:layout_height=“@dimen/dp_64”>

<LinearLayout

android:gravity=“center_vertical”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:orientation=“horizontal”>

<TextView

android:id=“@+id/tv_notification_song_name”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:ellipsize=“marquee”

android:focusable=“true”

android:focusableInTouchMode=“true”

android:marqueeRepeatLimit=“marquee_forever”

android:singleLine=“true”

android:text=“歌曲名”

android:textColor=“@color/black”

android:textSize=“14sp” />

<TextView

android:layout_marginStart=“@dimen/dp_12”

android:id=“@+id/tv_notification_singer”

android:layout_width=“0dp”

android:layout_weight=“1”

android:singleLine=“true”

android:layout_height=“wrap_content”

android:text=“歌手名”

android:textSize=“@dimen/sp_12” />

<ImageButton

android:id=“@+id/btn_notification_close”

android:layout_width=“@dimen/dp_20”

android:layout_height=“@dimen/dp_20”

android:background=“@color/transparent”

android:src=“@drawable/close_gray” />

<LinearLayout

android:layout_marginTop=“@dimen/dp_4”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:gravity=“center”>

<ImageButton

android:id=“@+id/btn_notification_previous”

android:layout_width=“@dimen/dp_30”

android:layout_height=“@dimen/dp_30”

android:background=“@null”

android:scaleType=“fitCenter”

android:src=“@drawable/previous_black” />

<ImageButton

android:id=“@+id/btn_notification_play”

android:layout_width=“@dimen/dp_30”

android:layout_height=“@dimen/dp_30”

android:layout_marginStart=“@dimen/dp_30”

android:layout_marginEnd=“@dimen/dp_30”

android:background=“@null”

android:scaleType=“fitCenter”

android:src=“@drawable/play_black” />

<ImageButton

android:id=“@+id/btn_notification_next”

android:layout_width=“@dimen/dp_30”

android:layout_height=“@dimen/dp_30”

android:background=“@null”

android:scaleType=“fitCenter”

android:src=“@drawable/next_black” />

icon_notification_default.png

在这里插入图片描述

close_gray.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<vector xmlns:android=“http://schemas.android.com/apk/res/android”

android:width=“24dp”

android:height=“24dp”

android:tint=“#8a8a8a”

android:viewportWidth=“24.0”

android:viewportHeight=“24.0”>

<path

android:fillColor=“@android:color/white”

android:pathData=“M18.3,5.71c-0.39,-0.39 -1.02,-0.39 -1.41,0L12,10.59 7.11,5.7c-0.39,-0.39 -1.02,-0.39 -1.41,0 -0.39,0.39 -0.39,1.02 0,1.41L10.59,12 5.7,16.89c-0.39,0.39 -0.39,1.02 0,1.41 0.39,0.39 1.02,0.39 1.41,0L12,13.41l4.89,4.89c0.39,0.39 1.02,0.39 1.41,0 0.39,-0.39 0.39,-1.02 0,-1.41L13.41,12l4.89,-4.89c0.38,-0.38 0.38,-1.02 0,-1.4z” />

previous_black.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<vector xmlns:android=“http://schemas.android.com/apk/res/android”

android:width=“36dp”

android:height=“36dp”

android:tint=“#000000”

android:viewportWidth=“24.0”

android:viewportHeight=“24.0”>

<path

android:fillColor=“@android:color/white”

android:pathData=“M7,6c0.55,0 1,0.45 1,1v10c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1L6,7c0,-0.55 0.45,-1 1,-1zM10.66,12.82l5.77,4.07c0.66,0.47 1.58,-0.01 1.58,-0.82L18.01,7.93c0,-0.81 -0.91,-1.28 -1.58,-0.82l-5.77,4.07c-0.57,0.4 -0.57,1.24 0,1.64z” />

play_black.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<vector xmlns:android=“http://schemas.android.com/apk/res/android”

android:width=“36dp”

android:height=“36dp”

android:tint=“#000000”

android:viewportWidth=“24.0”

android:viewportHeight=“24.0”>

<path

android:fillColor=“@android:color/white”

android:pathData=“M8,6.82v10.36c0,0.79 0.87,1.27 1.54,0.84l8.14,-5.18c0.62,-0.39 0.62,-1.29 0,-1.69L9.54,5.98C8.87,5.55 8,6.03 8,6.82z” />

pause_black.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<vector xmlns:android=“http://schemas.android.com/apk/res/android”

android:width=“36dp”

android:height=“36dp”

android:tint=“#000000”

android:viewportWidth=“24.0”

android:viewportHeight=“24.0”>

<path

android:fillColor=“@android:color/white”

android:pathData=“M8,19c1.1,0 2,-0.9 2,-2L10,7c0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2v10c0,1.1 0.9,2 2,2zM14,7v10c0,1.1 0.9,2 2,2s2,-0.9 2,-2L18,7c0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2z” />

next_black.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<vector xmlns:android=“http://schemas.android.com/apk/res/android”

android:width=“36dp”

android:height=“36dp”

android:tint=“#000000”

android:viewportWidth=“24.0”

android:viewportHeight=“24.0”>

<path

android:fillColor=“@android:color/white”

android:pathData=“M7.58,16.89l5.77,-4.07c0.56,-0.4 0.56,-1.24 0,-1.63L7.58,7.11C6.91,6.65 6,7.12 6,7.93v8.14c0,0.81 0.91,1.28 1.58,0.82zM16,7v10c0,0.55 0.45,1 1,1s1,-0.45 1,-1V7c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1z” />

一共六个图标,一个png格式,其余五个为xml格式。

下面进入到MusicService中。里面的代码如下:

private static final String TAG = “MusicService”;

public class MusicBinder extends Binder {

public MusicService getService() {

return MusicService.this;

}

}

@Override

public IBinder onBind(Intent intent) {

super.onBind(intent);

return new MusicBinder();

}

@Override

public void onCreate() {

super.onCreate();

BLog.d(TAG, “onCreate”);

}

通过绑定的方式启动服务,回到MainActivity,创建变量

private MusicService.MusicBinder musicBinder;

private MusicService musicService;

然后创建服务连接器

/**

  • 服务连接

*/

private ServiceConnection connection = new ServiceConnection() {

/**

  • 连接服务

  • @param name

  • @param service

*/

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

musicBinder = (MusicService.MusicBinder) service;

musicService = musicBinder.getService();

BLog.d(TAG, “Service与Activity已连接”);

}

//断开服务

@Override

public void onServiceDisconnected(ComponentName name) {

musicBinder = null;

}

};

在initData方法中绑定服务。

//绑定服务

Intent serviceIntent = new Intent(context, MusicService.class);

bindService(serviceIntent, connection, BIND_AUTO_CREATE);

也要在页面销毁时解绑

@Override

protected void onDestroy() {

super.onDestroy();

unbindService(connection);

System.exit(0);

}

我在initData中加了日志的打印

BLog.d(TAG, “initData”);

下面运行一下:

在这里插入图片描述

从日志上可以得出,在initData中绑定时,会创建一个服务连接,在连接时对服务进行创建,创建之后连接这个服务,此时服务在后台运行,下面就要在服务中显示通知栏。

private static NotificationManager manager;

/**

  • 显示通知

*/

private void showNotification() {

String channelId = “play_control”;

String channelName = “播放控制”;

int importance = NotificationManager.IMPORTANCE_HIGH;

createNotificationChannel(channelId, channelName, importance);

RemoteViews remoteViews = new RemoteViews(this.getPackageName(), R.layout.notification);

Notification notification = new NotificationCompat.Builder(this, “play_control”)

.setWhen(System.currentTimeMillis())

.setSmallIcon(R.mipmap.icon_big_logo)

.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.icon_big_logo))

.setCustomContentView(remoteViews)

.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)

.setAutoCancel(false)

.setOnlyAlertOnce(true)

.setOngoing(true)

.build();

//发送通知

manager.notify(1, notification);

}

/**

  • 创建通知渠道

尾声

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

  • 思维脑图
  • 性能优化学习笔记


  • 性能优化视频

    当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

  • 思维脑图
    [外链图片转存中…(img-ARc4kuEV-1714337461159)]
  • 性能优化学习笔记
    [外链图片转存中…(img-LfBbctWt-1714337461160)]
    [外链图片转存中…(img-r1iQf2uj-1714337461160)]

[外链图片转存中…(img-DhN1lGIs-1714337461160)]
[外链图片转存中…(img-j3kbEAIh-1714337461161)]

  • 性能优化视频
    [外链图片转存中…(img-fmP2fGSw-1714337461161)]
    当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值