Android6.0系统适配桌面歌词效果
2016-03-22 16:38
555 查看
github地址:https://github.com/coolstar1204/ActivityShowHide
在360手机助手及各家的音乐播放器软件上,都使用了桌面浮动窗功能,桌面歌词都是在音乐客户端显示在前台时隐藏,在用户把软件切换到后台后显示出来,此效果在Android 6.0以前,大部分都是使用系统的ActivityManager系统类的getRunningAppProcesses或getRunningTasks(Android5.0需要多判断一步)来进行软件前后台状态的判断,然后使用WindowManager进行浮动窗控件的增加和删除实现桌面歌词的显示与隐藏。但在Android6.0后,如果是使用SDK中6.0的编译工具编译的App,ActivityManager的方法和WindowManager的方法都有权限问题,不能简单直接的使用了。下面通过一个模仿桌面歌词效果的例子,来说明6.0上的实现。
然后在接口实现类中,实现如下代码,在全局进行状态标识更新
上面需要注意的是,一定要把判断逻辑放到started和stopped回调事件中,而不能放到Resumed和paused事件中,因为这二个事件在应用有多个Activity进行交替打开时,桌面歌词会显一下。
上面这种方法不需要申请权限,简单安全。
权限,就可以在代码中通过WindowManager的addView进行悬浮窗的显示与隐藏(国内有些手机系统(小米、华为等)在4.X系统上自己增加了悬浮窗的控制,需要提示用户先去打开才能正常)。
在6.0以后,除了上面在AndroidManifest.xml声明权限外,因为此权限特别,还需要使用代码,引导用户到系统的设置界面,打开对应的打关,系统才能正常执行。代码及界面如下:
这段代码,在应用启动时,就会直接引导用户去设置界面去打开开关。
当用户操作完成后,软件会进入到主界面,这时用户有可能打开也有可能没打开,所以在使用的地方,还是需要再判断一下的。
实现了这二个功能后,组合到一起,就是类似360手机助手那个悬浮的内存清理球或音乐客户端的桌面歌词效果。
在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<RunningAppProcessInfo> 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<RunningTaskInfo> 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中声明<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
权限,就可以在代码中通过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手机助手那个悬浮的内存清理球或音乐客户端的桌面歌词效果。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories