QQ音乐/酷狗音乐锁屏控制实现原理

我实现的效果

混乱的锁屏控制

Android自4.0版本, 也就是API level 14开始, 加入了锁屏控制的功能, 相关的类是RemoteControlClient, 这个类在API level 21中被标记为deprecated, 被新的类MediaSession所替代. 我们的音乐App中最开始使用的是原生锁屏控制API, 说实话这个API不好用, 遇到了一些小坑, 最要命的是不同品牌的手机, 锁屏界面长的还不一样, 就连我自己都没见过原生4.0的锁屏控制界面是什么样的. 国内的手机厂商都自以为自己的审美很强, 设计了千奇百怪的锁屏控制界面, MIUI更奇怪, MIUI 6是在原生4.4.4的基础上改的, 竟然有一段时间都没有锁屏控制界面, 后来更新才有. 而原生Android在5.0时, 将锁屏和通知栏控制合并, 整个逻辑非常混乱. 我们还是决定像QQ音乐/酷狗音乐那样, 自己做一个锁屏控制页面

题外话: 给RemoteControlClient设置封面时, 参数是一个Bitmap, 这个参数传入后, 千万不要在其他地方使用这个Bitmap, 也不要持有它的引用, 更不要自作聪明调用它的recycle方法.

实现思路

锁屏应用: 大炮打蚊子

首先想到的因该是做一个锁屏, 也就是使用Android的API, 做一个锁屏应用, 和输入法等应用一样, 但这个方法成本很高. 国内的那些锁屏应用, 首先要做的就是引导用户设置锁屏应用, 步骤相当繁杂, 只是为了一个播放控制就用一个锁屏应用, 没有哪个用户会这么有耐心.

悬浮窗: 黑魔法

得益于我国程序员的脑洞, 我们有了第二种思路: 悬浮窗.

悬浮窗的一个比较严谨的名字叫系统警告窗口, 国内外的一些流氓厂商, 经常用悬浮窗弹一些广告, 这个悬浮窗是浮在正常的app的上面的, 所以如果它不消失, 很可能你连正常使用手机都有问题.

这是一个比较打扰用户的东西, 而且也有一定的安全风险. MIUI的权限管理默认是将悬浮窗关闭的, 而有道词典的复制查词功能, 就是用悬浮窗做的, 如果你没给有道词典打开这个权限, 复制查词这个功能就废了.

普通Activity伪造锁屏

文章开头的GIF图片展示的效果, 就是用一个普通Activity做的.

国内的app们, 最终都选择了这条道路, 不知道他们是谁抄的谁, 第一个想到使用普通Activity伪造一个锁屏的开发者, 我只能说非常有创造力.

监听锁屏事件

准确来说我们监听的是屏幕熄灭事件, 关屏事件的Intent是Intent.ACTION_SCREEN_OFF, 不需要任何权限就可以监听, 但是必须使用代码注册, 也就是说我们必须有一个Service在后台监听才行, 对音乐类app来说, 这不是问题, 音乐app本身就是使用Service来控制MediaPlayer的. 只需要在Service中注册监听Intent.ACTION_SCREEN_OFF就行. 监听到这个事件,

@Override
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    if (action.equals(Intent.ACTION_SCREEN_OFF)) {
        Intent lockscreen = new Intent(PlaybackService.this, LockScreenActivity.class);
        lockscreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(lockscreen);
    }
}

注意我们在Service中启动一个Activity, 需要加上Intent.FLAG_ACTIVITY_NEW_TASK这个flag才行.

透明背景

要想做到锁屏那样滑动解锁, 比如像图中的样子, 我们除了要根据手势移动View以外, 还要让Activity的背景透明, 比如将theme设置成下面这样.

<style name="LockScreenBase" parent="AppBaseTheme">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:colorBackgroundCacheHint">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:backgroundDimEnabled">false</item>
    <item name="android:windowAnimationStyle">@null</item>
    <item name="android:windowContentOverlay">@null</item>
</style>

这个style其实做了很多东西, 大家根据自己的需要可以删减一部分, 比如状态栏透明, 不使用TitleBar之类的.

解锁屏幕与显示在锁屏之上

在显示我们的假锁屏的时候, 我们应当帮用户解锁, 这样我们才能冒充锁屏, 而不会出现用户”解锁”两次的情况, 但我们只能要求系统解锁没有密码的锁屏, 有密码的情况下, 我们是不能解锁屏幕的, 这时我们应该覆盖在锁屏界面上, 幸好, 在API level 5中就引入了两个Flag, FLAG_DISMISS_KEYGUARDFLAG_SHOW_WHEN_LOCKED

在锁屏Activity的onCreate方法中给Activity加上两个Flag

this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);

一定要两个一起用, 否则效果不大好, 当时测试了好久, 后来看了一下QQ音乐的实现, 才发现两个一起用效果才好, 否则会有一些奇怪的问题.

隐藏踪迹与独立的Task

作为一个锁屏界面, 应当是独立的, 也就是说, 我们这个Activity应当独立于我们的App存在, 至少看起来是这样. 从Android的角度来看, 我们app的主界面里的所有Activity, 应当在一个Task里, 而锁屏Activity, 应当在一个独立的Task里, 因此我们需要给锁屏Activity一个独立的Task, 而且无论何时, 都只有一个锁屏Activity实例存在.

另外, Android有查看近期任务的功能, 我们不希望锁屏界面这个独立的Task显示在里面, 所以锁屏Activity不能显示在近期任务中.

说了这么多, 要做很简单, 只需要在Manifest里面声明Activity时加入几个属性即可

<activity android:excludeFromRecents="true"
    android:exported="false"
    android:launchMode="singleInstance"
    android:name=".view.lockscreen.LockScreenActivity"
    android:screenOrientation="portrait"
    android:taskAffinity="com.package.name.lockscreen"
    android:theme="@style/LockScreenTheme">
</activity>

上面的属性中android:excludeFromRecents="true"让锁屏Activity不显示在近期任务中, android:launchMode="singleInstance"android:taskAffinity="com.package.name.lockscreen"保证锁屏Activity有一个单独的Task, 且这个Task里永远只有它一个实例.

不响应Back按键

锁屏界面当然不响应Back按键, 只需要重写Activity的onBackPressed方法即可

@Override
public void onBackPressed() {
    // do nothing
}

对Home按键的处理

我们无法监听Home按键, 但是可以改变因Home进入后台时的处理, 比如在Manifest的activity声明中加上

android:noHistory="true"

这样如果用户通过Home按键让我们的应用进入后台, 我们会让这个activity销毁, 就像我们被滑动关闭一样.

如果不加, 最好重写Activity的onNewIntent来应对因Home进入后台, 然后Service再次启动锁屏Activity的情况.

处理黑色闪屏

我们的锁屏Activity在滑动”解锁”之后, 理论上是直接进入下面的界面, 但有时如果下面不是launcher, 而是一个app, 有可能会闪一下黑屏, 这个其实是底下activity的入场动画导致的, 某些Android版本会对顶部activity透明时处理有些奇怪, 我们不能保证其他的应用不闪黑屏, 但是对自己的的应用还是可以的, 只需要在我们的主体activity的style中加上

<item name="android:windowAnimationStyle">@null</item>

就不会有这种情况发生了, 但是这样的话入场动画也没了, 总之如何取舍看大家了.

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-06 12:32:28

QQ音乐/酷狗音乐锁屏控制实现原理的相关文章

Java爬虫系列之实战:爬取酷狗音乐网 TOP500 的歌曲

在前面分享的两篇随笔中分别介绍了HttpClient和Jsoup以及简单的代码案例: Java爬虫系列二:使用HttpClient抓取页面HTML Java爬虫系列三:使用Jsoup解析HTML 今天就来实战下,用他们来抓取酷狗音乐网上的 Top500排行榜音乐.接下来的代码中除了会用到HttpClient和Jsoup之外,还会用到log4j和ehcache,分别用来记录日志和实现缓存,如果看官对这两个不是很熟悉的话,请自行百度,现在网上的入门实例有很多,我就不专门记笔记了. 那为什么会想到爬取

htmlunit+fastjson抓取酷狗音乐 qq音乐链接及下载

上次学了jsoup之后,发现一些动态生成的网页内容是无法抓取的,于是又学习了htmlunit,下面是抓取酷狗音乐与qq音乐链接的例子: 酷狗音乐: import java.io.BufferedInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.net.URL; import java.net.URLEncoder; import java.util.UUID; import

仿酷狗音乐播放器已开源!

转载请说明原出处,谢谢:http://blog.csdn.net/zhuhongshu/article/details/41037875 距离我发布测试版的Redrain音乐盒(仿酷狗播放器),现在正好刚2个月.博客留言和QQ群里也一直有网友关心这个小项目开源的问题.先感谢网友对这个小项目的支持.之前我一直担心版权问题而没有开源这个项目,因为我只是个在校大学生,不想惹麻烦,希望大家体谅! 关于这个Redrain音乐盒的发布程序的说明和使用方法,见<Redrain仿酷狗音乐播放器开发完毕,发布测试

关于仿酷狗音乐播放器开源:寻求一套音乐播放器素材,让仿酷狗开源

转载请说明原出处,谢谢~~ 距离公布測试版的仿酷狗音乐播放器.已经几个月过去了.期间非常多网友加我QQ来问我开源的问题,我也早有开源意向. 但我也一直没有得到可靠的信息,保证开源后没有不论什么问题. 所以我打算给这个软件全然换一套界面素材.放弃原来的酷狗素材. 这样开源也就没有不论什么问题了,问题是我个人PS水平太烂.仅仅会切切图.如今寻求一套完整的音乐播放器的素材,素材内容要全面,能够用来替代酷狗的素材. 假设有哪位朋友有这种素材,或者有时间能够做出一套素材让我使用,我将感激不尽.素材替换完成

酷狗音乐7635 VIP去广告绿色清爽版

昨天,酷狗音乐官方又例行悄悄上架了最新包V7635,新版去掉了“附近”功能,这次又增加智能限速功能,同时优化加快了启动速度,每次总有新功能,推荐酷狗迷们下载更新! 酷狗音乐7.6新版特性:次世代音效:极智丽音.超重低音.纯净人声,混合电台.高品质电台.一键智能推荐.单曲智能推荐.观看真人演唱.传歌到手机.手机投放控制PC.音频输出支持ASIO等特性. 此VIP去广告绿色清爽版,由zd423专注持续修改,不带广告弹窗干扰 ,普通用户登陆为VIP会员,免费畅享VIP试听及下载加速.免登陆试听下载无损

记一次酷狗音乐API的获取,感兴趣的可以自己封装开发自己的音乐播放器

1.本教程仅供个人学习用,禁止用于任何的商业和非法用途,如涉及版权问题请联系笔者删除. 2.随笔系作者原创文档,转载请注明文档来源:http://www.cnblogs.com/apresunday/p/8448126.html,谢谢 小八这几天正在学习微信小程序的开发,于是想在学的同时能开发出来一个关于音乐的项目,但是问题在于音乐这东西.一方面是数据量太大,第二个方面就是牵扯到很多的版权的问题,所以笔者就想着借助于目前市面上的音乐播放器上的音乐文件,鉴于酷狗音乐上边的歌多而且比较的全面,在此就

Qt实战之酷狗音乐

此项目仅仅实现实现基本功能: 界面的模仿. 歌词功能的实现.歌曲在线试听和下载. 专辑写真的播放. 在线歌词搜索.以及主要的button功能. 界面没有採用设计器. 所有手写规划.这里先放出效果图. 这段时间忙,等有空时,将又一次架构.一步一步带领新手写出简版酷狗音乐.实现MV等播放. 播放时的单词界面: 实现平滑滚动效果  当中背景写真来源于酷我音乐... 可点击进度条快进快退  .. 歌词会随之修改 . . 歌词支持拉动   鼠标在歌词部分按下后出现横线(可怜的鼠标没截图到. .. ) 然后

仿酷狗音乐播放器开发日志二十一 开发动态调色板控件(附源代码)

转载请说明原出处,谢谢~~ 上一篇仿酷狗日志结束后,整个换肤功能就仅仅剩下调色板功能没有做了.我本以为会非常easy.可是研究了酷狗的调色板功能后发现不是那么简单的事情.首先看一下酷狗的调色板的样子: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemh1aG9uZ3NodQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" > waterm

酷狗音乐展示滚动歌词效果的控件实现

文章来自http://blog.csdn.net/zhaodecang 在音乐播放器项目中使用到酷狗音乐展示歌词的效果,需要支持修改字体.颜色.渐变色等功能 截图如下(效果不是很好,请下载Demo查看) 歌词绘制流程核心代码如下(具体实现过程请看Github源码) @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 中心Y坐标 float centerY = getHeight() / 2 + mTe