在360手机助手及各家的音乐播放器软件上,都使用了桌面浮动窗功能,桌面歌词都是在音乐客户端显示在前台时隐藏,在用户把软件切换到后台后显示出来,此效果在Android 6.0以前,大部分都是使用系统的ActivityManager系统类的getRunningAppProcesses或getRunningTasks(Android5.0需要多判断一步)来进行软件前后台状态的判断,然后使用WindowManager进行浮动窗控件的增加和删除实现桌面歌词的显示与隐藏。但在Android6.0后,如果是使用SDK中6.0的编译工具编译的App,ActivityManager的方法和WindowManager的方法都有权限问题,不能简单直接的使用了。下面通过一个模仿桌面歌词效果的例子,来说明6.0上的实现。

首先讲一下6.0以前版本判断前后台状态方式:

private static void UpdateForgroundState() {

boolean isForground = IS_FORGROUND;

Context ctx = App.getInstance().getApplicationContext();

ActivityManager activityManager = (ActivityManager)ctx.getSystemService(Context.ACTIVITY_SERVICE);

String packageName = ctx.getPackageName();

List appProcesses = activityManager.getRunningAppProcesses();

if (appProcesses == null) {

return;

}

for (RunningAppProcessInfo appProcess : appProcesses) {

if (!appProcess.processName.equals(packageName)) {

continue; //不是本程序的包名,跳过

}

isForground = CompatibleCheckAppState(ctx,activityManager,appProcess);

break;

}

if (IS_FORGROUND == isForground) {

return;

}

IS_FORGROUND = isForground;

if (isForground) {

//通知程序桌面歌词类,当前是前台状态,你要隐藏起来

} else {

//通知桌面歌词类,当前是后台运行中,你要出来显示了

}

}

private static boolean CompatibleCheckAppState(Context ctx,ActivityManager am,RunningAppProcessInfo pInfo){

if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.KITKAT){ //Android5.0的判断前后台和以前版本不一样。要通过topActivity找包名判断,

if(am==null){

return false;

}

List tasks = am.getRunningTasks(1);

if (!tasks.isEmpty()) {

ComponentName topActivity = tasks.get(0).topActivity;

if (topActivity!=null&&ctx!=null&&topActivity.getPackageName().equals(ctx.getPackageName())) {

return true;

}

}

return false;

}else{

//5.0以前的系统,可以直接通过RunningAppProcessInfo类的importance属性判断前后台状态

return pInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND;

}

}

Android4.0–Android6.0可通用的判断前台后的方法

首先要自定义Application类,在类中进行ActivityLifecycleCallbacks的接口实现类进行注册与反注册

@Override

public void onCreate() {

super.onCreate();

this.registerActivityLifecycleCallbacks(callbacks);

}

@Override

public void onTerminate() {

this.unregisterActivityLifecycleCallbacks(callbacks);

super.onTerminate();

}

然后在接口实现类中,实现如下代码,在全局进行状态标识更新

private Application.ActivityLifecycleCallbacks callbacks = new ActivityLifecycleCallbacks() {

@Override

public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

}

@Override

public void onActivityStarted(Activity activity) {

activityShowingCount++;

changeActivityFlag(activity,activityShowingCount>0);

}

@Override

public void onActivityResumed(Activity activity) {

}

@Override

public void onActivityPaused(Activity activity) {

}

@Override

public void onActivityStopped(Activity activity) {

activityShowingCount--;

changeActivityFlag(activity,activityShowingCount>0);

}

@Override

public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

}

@Override

public void onActivityDestroyed(Activity activity) {

}

};

上面需要注意的是,一定要把判断逻辑放到started和stopped回调事件中,而不能放到Resumed和paused事件中,因为这二个事件在应用有多个Activity进行交替打开时,桌面歌词会显一下。

上面这种方法不需要申请权限,简单安全。

关于悬浮窗的使用

在6.0以前,使用系统悬浮窗只需要在AndroidManifest.xml中声明

权限,就可以在代码中通过WindowManager的addView进行悬浮窗的显示与隐藏(国内有些手机系统(小米、华为等)在4.X系统上自己增加了悬浮窗的控制,需要提示用户先去打开才能正常)。

在6.0以后,除了上面在AndroidManifest.xml声明权限外,因为此权限特别,还需要使用代码,引导用户到系统的设置界面,打开对应的打关,系统才能正常执行。代码及界面如下:

if(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1){

if(Settings.canDrawOverlays(this)==false){

Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);

intent.setData(Uri.parse("package:" + getPackageName()));

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(intent);

}

}

这段代码,在应用启动时,就会直接引导用户去设置界面去打开开关。

当用户操作完成后,软件会进入到主界面,这时用户有可能打开也有可能没打开,所以在使用的地方,还是需要再判断一下的。

public static void changeView(final Context appContext, boolean isActivityShowing) {

WindowManager wndMgr = (WindowManager) appContext.getSystemService(Service.WINDOW_SERVICE);

if(isActivityShowing){

if(floatView!=null){

Log.e("FloatingWindow","removeView------------");

try{

wndMgr.removeView(floatView);

}catch (Throwable e){

}

floatView = null;

}

}else{

if(floatView==null) {

final LayoutInflater inflater = LayoutInflater.from(appContext);

floatView = inflater.inflate(R.layout.window_floating, null);

}

WindowManager.LayoutParams mDeskLrcLayoutParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

mDeskLrcLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;

mDeskLrcLayoutParams.format = PixelFormat.TRANSPARENT;

mDeskLrcLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

mDeskLrcLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;

mDeskLrcLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;

mDeskLrcLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

mDeskLrcLayoutParams.x = 320;

mDeskLrcLayoutParams.y = 620;

if(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1){

if(Settings.canDrawOverlays(appContext)){//这里一定要再判断一次。否则会崩溃哈

Log.e("FloatingWindow","addView------------");

wndMgr.addView(floatView,mDeskLrcLayoutParams);

}else{

Toast.makeText(appContext,"无权限,不能显示桌面浮动按钮",Toast.LENGTH_SHORT).show();

}

}else{

wndMgr.addView(floatView,mDeskLrcLayoutParams);

}

}

}

实现了这二个功能后,组合到一起,就是类似360手机助手那个悬浮的内存清理球或音乐客户端的桌面歌词效果。

android+桌面歌词,Android6.0系统适配桌面歌词效果相关推荐

  1. android 6.0 短信权限,Android6.0权限适配

    Code4Android .jpg 前言 现在谈论Android权限适配可能有点没必要,因为网上关于权限适配的文章很多,搜一下Android6.0权限适配关键词能搜到一堆文章,而且很多写的还很不错.不 ...

  2. Android6.0权限适配及兼容库的实现

    从6.0 MarshMallow开始,Android支持动态权限管理,即有些权限需要在使用到的时候动态申请,根据用户的选择需要有不同的处理,具体表现可以看下图: 本文并不关心权限适配的原理,原理可以参 ...

  3. Android6.0 ios,意超越iOS9!谷歌寄希望于Android6.0系统

    虽然在目前全球的移动操作系统上,谷歌的Android系统市场占有率傲视群雄,但在某些方面iOS系统还是更占优势.对此分析师Dan Gallagher认为谷歌和苹果.Android和iOS之间的战况将随 ...

  4. 零死角玩转Android6.0系统Healthd深入分析

    零死角玩转Android6.0系统Healthd深入分析 概述 Healthd是android4.4之后提出来的一种中介模型,该模型向下监听来自底层的电池事件,向上传递电池数据信息给Framework ...

  5. 华为升级harmonyos的机型名单,华为鸿蒙 OS 2.0 系统适配名单已出,四月推送,天玑机型暂时无缘...

    原标题:华为鸿蒙 OS 2.0 系统适配名单已出,四月推送,天玑机型暂时无缘 华为官方在 2020 年发布了旗下自研系统"HarmonyOS 2.0"版本,发布会现场展示了 Har ...

  6. 华为鸿蒙系统如何到手机桌面,鸿蒙OS2.0系统怎么降级到EMUI11 鸿蒙OS2.0系统降级到EMUI11方法...

    华为在2020.12.16举行了鸿蒙OS2.0beta的发布会,在发布会中华为表示EMUI11系统将第一时间体验到鸿蒙的系统,但是由于但是开发版本,所以华为也提供了降级的方法,那么鸿蒙OS2.0系统怎 ...

  7. 小米6系统 Android版本,追赶华为! 小米开启安卓8.0系统适配, 小米6最先更新!

    说起买手机,你可能会注意些什么呢?很多人会首先看手机的外观.配置或者价格等等,相信肯定也有一部分是冲着系统去了.比如说小米,之所以能够大卖,不仅仅是因为性价比,同样也因为它的MIUI系统,这也应该是目 ...

  8. android6.0系统车载航一,基于android的车载影音导航系统软件设计与实现-计算机应用技术专业论文.docx...

    基于android的车载影音导航系统软件设计与实现-计算机应用技术专业论文 西南科技大学硕士研究生学位论文 西南科技大学硕士研究生学位论文第1页 摘要 经过对车载影音/导航综合系统在国内外行业以及高校 ...

  9. Android教程 -05 Android6.0权限的管理

    视频为本篇博客知识的讲解,建议采用超清模式观看, 欢迎点击订阅我的优酷 height="498" width="510" src="http://pl ...

最新文章

  1. WIN7 64位系统下,右下角的声音和电源图标不见的解决办法
  2. delphi 纯虚函数的应用
  3. 为选择合适的ERP供应商,是否该发布需求建议书(RFP)?
  4. 光学定位与追踪技术_如何为射线光学仿真创建复杂的透镜几何结构
  5. 2018qs计算机科学专业,2018QS世界大学计算机科学专业排名.docx
  6. 作者:景志刚(1977-),男,就职于中国人民银行征信中心数据部
  7. 金属100寸“电视”却无屏,语音识别+DTS+1080P,微鲸M1测评
  8. 洛谷 1776 宝物筛选 【多重背包+二进制拆分】
  9. iPhone越狱cydia源大全
  10. 新电脑基本软件安装推荐
  11. KIB、MiB、GiB
  12. tensorflow获取tensor的shape
  13. Socket套接字,一个简单的聊天室案例!
  14. textview中划线效果
  15. RocketMq 消费者
  16. windows打不开应用商店,edge浏览器不能登录同步
  17. linux一键分区脚本,【Shell】Linux中分区脚本
  18. PXI/PXIe控制器 4Link架构 16GB带宽 兼容主流PXIe机箱 设计文件!!! 原理图PCB
  19. 论文解读:《基于BERT和二维卷积神经网络的DNA增强子序列识别transformer结构》
  20. 为什么要使用去耦电容?去耦电容的工作原理。

热门文章

  1. 阿里云5天学习感悟与案例分享
  2. python自动化:uiautomation、pyautogui操作会计记账系统(6):打印会计凭证
  3. TIM新版支持微信扫码登录:自动生成新QQ
  4. 小爱(小米),天猫精灵(阿里),小度(百度),小艺(华为)智能家居系统选择
  5. 标准化考场时钟系统方案
  6. TVS管和稳压管两者比较
  7. Linux Mint 18安装sougou拼音输入法
  8. icare3.0医用his软件部署基本流程
  9. 华为hcie认证-链路聚合作用
  10. DirectX11 骷髅头示例Demo