转自:http://blog.csdn.net/lfdfhl/article/details/33394531
MainActivity如下:
- package cc.cc;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.app.Activity;
- import android.content.Context;
- import android.content.Intent;
- /**
- * Demo描述:
- * 仿360在Launcher画面显示内存使用率的浮窗.
- * 当然这里只是简单地仿O(∩_∩)O
- *
- * 思路整理:
- * 1 涉及到大小两个浮窗.并且两个浮窗之间有逻辑联系.比如:
- * 显示小浮窗时不显示大浮窗.所以利用DriftingWindowManager
- * 来管理这两个浮窗
- * 2 各用一个类来封装和实现两个浮窗的操作
- * 3 以上两个类均继承自Layout
- *
- * 总的来讲该示例还是比较简单的
- *
- * 学习资料:
- * 1 http://blog.csdn.net/guolin_blog/article/details/8689140
- * 2 http://blog.csdn.net/feng88724/article/details/6362710
- * 3 http://blog.csdn.net/hudashi/article/details/6901118
- * 4 http://blog.csdn.net/hudashi/article/details/7060882
- * 5 http://blog.csdn.net/hudashi/article/details/7061240
- * Thank you very much
- *
- */
- public class MainActivity extends Activity {
- private Context mContext;
- private Button mStartButton;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- init();
- }
- private void init(){
- mContext=this;
- mStartButton=(Button) findViewById(R.id.button);
- mStartButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent=new Intent();
- intent.setAction("dws");
- mContext.startService(intent);
- finish();
- }
- });
- }
- }
DriftingBigWindow如下:
- package cc.cc;
- import android.content.Context;
- import android.content.Intent;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.widget.Button;
- import android.widget.LinearLayout;
- /**
- *大浮窗
- *
- *大浮窗继承自LinearLayout
- *该大浮窗主要实现的功能
- *1 关闭大浮窗显示小浮窗
- *2 关闭所有浮窗且停止对于内存使用率的监控
- *
- *注意方法:
- *LayoutInflater.inflate(int resource, ViewGroup root)的第二参数
- *若设置了root,那么会把新生成的View连接到root,该方法的返回为root.
- *否未设置root,则返回的是新生成的View
- */
- public class DriftingBigWindow extends LinearLayout {
- //整个大浮窗的宽和高
- public static int width=0;
- public static int height=0;
- private Context mContext;
- public DriftingBigWindow(Context context) {
- super(context);
- mContext=context;
- LayoutInflater layoutInflater=LayoutInflater.from(mContext);
- View bigWindowView=layoutInflater.inflate(R.layout.drifting_window_big, this);
- View driftingBigWindowRootView=bigWindowView.findViewById(R.id.driftingBigWindowRootView);
- //获取大浮窗整个布局的宽和高
- width=driftingBigWindowRootView.getLayoutParams().width;
- height=driftingBigWindowRootView.getLayoutParams().height;
- //停止服务且移除浮窗
- Button closeButton=(Button) bigWindowView.findViewById(R.id.closeButton);
- closeButton.setOnClickListener(new ClickListenerImpl());
- //显示小浮窗
- Button backButton=(Button) bigWindowView.findViewById(R.id.backButton);
- backButton.setOnClickListener(new ClickListenerImpl());
- }
- private class ClickListenerImpl implements OnClickListener{
- @Override
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.closeButton:
- Intent intent=new Intent();
- intent.setAction("dws");
- mContext.stopService(intent);
- DriftingWindowManager.removeDriftingSmallWindow(mContext);
- DriftingWindowManager.removeDriftingBiglWindow(mContext);
- break;
- case R.id.backButton:
- DriftingWindowManager.showDriftingSmallWindow(mContext);
- DriftingWindowManager.removeDriftingBiglWindow(mContext);
- break;
- default:
- break;
- }
- }
- }
- }
DriftingSmallWindow如下:
- package cc.cc;
- import android.content.Context;
- import android.view.LayoutInflater;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.WindowManager;
- import android.widget.LinearLayout;
- import android.widget.TextView;
- /**
- *小浮窗
- *
- *小浮窗继承自LinearLayout
- *该小浮窗主要实现的功能:
- *1 显示手机的内存使用率
- *2 在Home界面被随意移动位置
- * 所以重点是实现TouchListener,在Touch监听中
- * 不断调用mWindowManager.updateViewLayout()
- * 修改小浮窗在屏幕上的LayoutParams
- *
- *注意方法:
- *LayoutInflater.inflate(int resource, ViewGroup root)的第二参数
- *若设置了root,那么会把新生成的View连接到root,该方法的返回为root.
- *否未设置root,则返回的是新生成的View
- */
- public class DriftingSmallWindow extends LinearLayout {
- //整个小浮窗的宽和高
- public static int width=0;
- public static int height=0;
- private float XInScreen_Down = 0;
- private float YInScreen_Down = 0;
- private float XInScreen_Move = 0;
- private float YInScreen_Move = 0;
- private float XInScreen_Up = 0;
- private float YInScreen_Up = 0;
- private float XInView_Down=0;
- private float YInView_Down=0;
- private Context mContext;
- private WindowManager mWindowManager;
- private static WindowManager.LayoutParams mWindowManagerLayoutParams;
- public DriftingSmallWindow(Context context) {
- super(context);
- mContext=context;
- mWindowManager=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- LayoutInflater layoutInflater = LayoutInflater.from(context);
- View smallWindowView=layoutInflater.inflate(R.layout.drifting_window_small, this);
- View driftingSmallWindowRootView=smallWindowView.findViewById(R.id.driftingSmallWindowRootView);
- TextView percentTextView=(TextView) smallWindowView.findViewById(R.id.percentTextView);
- //获取小浮窗整个布局的宽和高
- width=driftingSmallWindowRootView.getLayoutParams().width;
- height=driftingSmallWindowRootView.getLayoutParams().height;
- percentTextView.setText(Utils.getAvailMemoryPercent(context));
- this.setOnTouchListener(new TouchListenerImpl());
- //this.setOnClickListener(new ClickListenerImpl());
- }
- /**
- * 利用该方式监听点击事件不靠谱
- * 所以在MotionEvent.ACTION_UP中处理点击事件
- */
- private class ClickListenerImpl implements OnClickListener{
- @Override
- public void onClick(View view) {
- }
- }
- /**
- * 对于小浮窗Touch事件的监听
- * 注意在MotionEvent.ACTION_UP中处理点击事件
- */
- private class TouchListenerImpl implements OnTouchListener{
- @Override
- public boolean onTouch(View view, MotionEvent event) {
- int statusBarHeight=Utils.getStatusBarHeight(mContext);
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- XInScreen_Down=event.getRawX();
- YInScreen_Down=event.getRawY()-statusBarHeight;
- XInView_Down=event.getX();
- YInView_Down=event.getY();
- break;
- case MotionEvent.ACTION_MOVE:
- XInScreen_Move=event.getRawX();
- YInScreen_Move=event.getRawY()-statusBarHeight;
- updateWindowManagerLayoutParams();
- break;
- case MotionEvent.ACTION_UP:
- XInScreen_Up=event.getRawX();
- YInScreen_Up=event.getRawY()-statusBarHeight;
- if (XInScreen_Down==XInScreen_Up&&YInScreen_Down==YInScreen_Up) {
- showDriftingBigWindow();
- }
- break;
- default:
- break;
- }
- return true;
- }
- };
- /**
- * 保存小浮窗在Window中的布局参数
- */
- public static void saveWindowManagerLayoutParams(WindowManager.LayoutParams layoutParams){
- mWindowManagerLayoutParams=layoutParams;
- }
- /**
- * 更新小浮窗在Window中的布局参数
- *
- * 注意事项:
- * X(Y)InScreen_Move表示触摸点离屏幕左上角的距离
- * X(Y)InView_Down表示触摸点离DriftingSmallWindow(小浮窗)自身左上角的距离.
- * 两者相减即得DriftingSmallWindow(小浮窗)左上角的坐标
- */
- private void updateWindowManagerLayoutParams(){
- mWindowManagerLayoutParams.x=(int) (XInScreen_Move-XInView_Down);
- mWindowManagerLayoutParams.y=(int) (YInScreen_Move-YInView_Down);
- mWindowManager.updateViewLayout(this, mWindowManagerLayoutParams);
- }
- /**
- * 显示大浮窗且关闭小浮窗
- */
- private void showDriftingBigWindow(){
- DriftingWindowManager.showDriftingBiglWindow(mContext);
- DriftingWindowManager.removeDriftingSmallWindow(mContext);
- }
- }
DriftingWindowManager如下:
- package cc.cc;
- import android.content.Context;
- import android.graphics.PixelFormat;
- import android.view.Gravity;
- import android.view.WindowManager;
- import android.view.WindowManager.LayoutParams;
- import android.widget.TextView;
- /**
- * 管理大小浮动窗口
- * 在该应用中主要包含了大小两个浮动窗口及其对应的操作
- * 比如显示,更新和移除等,所以就写了个DriftingWindowManager
- * 来实施这些操作.
- * 至于大小浮窗各自要做的操作则是在DriftingSmallWindow和DriftingBigWindow
- * 各个类中具体实施的.
- * 这个和平时其他的代码原理是一样的:
- * 比如在一个类A中使用了(类似于此处的浮窗显示,更新,移除)B和C的对象.
- * 但B和C对象的方法是在各自的类中实现的.
- */
- public class DriftingWindowManager {
- private static WindowManager mWindowManager=null;
- private static DriftingSmallWindow mDriftingSmallWindow=null;
- private static DriftingBigWindow mDriftingBigWindow=null;
- //注意该LayoutParams属于android.view.WindowManager.LayoutParams
- private static LayoutParams mDriftingSmallWindowLayoutParams;
- private static LayoutParams mDriftingBigWindowLayoutParams;
- /**
- * 显示小浮窗
- * 显示位置为屏幕中间右对齐
- */
- public static void showDriftingSmallWindow(Context context) {
- WindowManager windowManager = getWindowManager(context);
- int screenWidth = windowManager.getDefaultDisplay().getWidth();
- int screenHeight = windowManager.getDefaultDisplay().getHeight();
- //new了一个DriftingSmallWindow对象,在后面会用WindowManager将
- //其添加到屏幕中
- mDriftingSmallWindow = new DriftingSmallWindow(context);
- if (mDriftingSmallWindowLayoutParams == null) {
- mDriftingSmallWindowLayoutParams = new LayoutParams();
- mDriftingSmallWindowLayoutParams.type = LayoutParams.TYPE_PHONE;
- mDriftingSmallWindowLayoutParams.format = PixelFormat.RGBA_8888;
- mDriftingSmallWindowLayoutParams.flags =
- LayoutParams.FLAG_NOT_TOUCH_MODAL| LayoutParams.FLAG_NOT_FOCUSABLE;
- mDriftingSmallWindowLayoutParams.gravity = Gravity.LEFT| Gravity.TOP;
- mDriftingSmallWindowLayoutParams.width = DriftingSmallWindow.width;
- mDriftingSmallWindowLayoutParams.height = DriftingSmallWindow.height;
- //使小浮窗在屏幕上垂直居中,水平靠右的位置显示
- mDriftingSmallWindowLayoutParams.x = screenWidth-DriftingSmallWindow.width;
- mDriftingSmallWindowLayoutParams.y = screenHeight / 2;
- System.out.println("DriftingSmallWindow.width="+DriftingSmallWindow.width);
- System.out.println("mDriftingSmallWindowLayoutParams.x="+mDriftingSmallWindowLayoutParams.x);
- System.out.println("mDriftingSmallWindowLayoutParams.y="+mDriftingSmallWindowLayoutParams.y);
- }
- //当显示小浮窗的时保存小浮窗的LayoutParams至该DriftingSmallWindow对象
- //因为每次移动小浮窗的时候需要修改该LayoutParams的参数值X和Y
- mDriftingSmallWindow.saveWindowManagerLayoutParams(mDriftingSmallWindowLayoutParams);
- mWindowManager.addView(mDriftingSmallWindow,mDriftingSmallWindowLayoutParams);
- }
- /**
- * 更新小浮窗
- */
- public static void updateDriftingSmallWindow(Context context){
- if(mDriftingSmallWindow!=null){
- TextView percentTextView=(TextView) mDriftingSmallWindow.findViewById(R.id.percentTextView);
- percentTextView.setText(Utils.getAvailMemoryPercent(context));
- }
- }
- /**
- * 移除小浮窗
- */
- public static void removeDriftingSmallWindow(Context context){
- mWindowManager=getWindowManager(context);
- if(mWindowManager!=null&&mDriftingSmallWindow!=null){
- mWindowManager.removeView(mDriftingSmallWindow);
- mDriftingSmallWindow=null;
- }
- }
- /**
- * 显示大浮窗
- * 显示位置为屏幕中间
- *
- * 注意细节问题
- * 如下写法,有偏差,显示效果并不好
- * mDriftingBigWindowLayoutParams.x = screenWidth / 2;
- * mDriftingBigWindowLayoutParams.y = screenHeight / 2;
- * 给人的感觉是大浮窗并没有在屏幕中间位置.
- * 因为这个mDriftingBigWindowLayoutParams.x(y)指的是大浮窗
- * 在屏幕上显示的x(y)的开始坐标值,即从哪个坐标开始摆放大浮窗.
- * 极端地说如果大浮窗就沙子那么大,那么这么做就没有问题,因为大浮窗
- * 本身就没有什么宽和高.
- * 但在实际中我们还要考虑到控件本身(此处的大浮窗)的长和宽,做到
- * 真的居中显示
- * 所以应该这么写:
- * mDriftingBigWindowLayoutParams.x = screenWidth / 2- DriftingBigWindow.width / 2;
- * mDriftingBigWindowLayoutParams.y = screenHeight / 2- DriftingBigWindow.height / 2;
- * 类似的问题在小浮窗的拖动过程中也有
- */
- public static void showDriftingBiglWindow(Context context) {
- WindowManager windowManager = getWindowManager(context);
- int screenWidth = windowManager.getDefaultDisplay().getWidth();
- int screenHeight = windowManager.getDefaultDisplay().getHeight();
- mDriftingBigWindow = new DriftingBigWindow(context);
- if (mDriftingBigWindowLayoutParams == null) {
- mDriftingBigWindowLayoutParams = new LayoutParams();
- mDriftingBigWindowLayoutParams.x = screenWidth / 2- DriftingBigWindow.width / 2;
- mDriftingBigWindowLayoutParams.y = screenHeight / 2- DriftingBigWindow.height / 2;
- mDriftingBigWindowLayoutParams.type = LayoutParams.TYPE_PHONE;
- mDriftingBigWindowLayoutParams.format = PixelFormat.RGBA_8888;
- mDriftingBigWindowLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
- mDriftingBigWindowLayoutParams.width = DriftingBigWindow.width;
- mDriftingBigWindowLayoutParams.height = DriftingBigWindow.height;
- }
- windowManager.addView(mDriftingBigWindow,mDriftingBigWindowLayoutParams);
- }
- /**
- * 移除大浮窗
- */
- public static void removeDriftingBiglWindow(Context context){
- mWindowManager=getWindowManager(context);
- if(mWindowManager!=null&&mDriftingBigWindow!=null){
- mWindowManager.removeView(mDriftingBigWindow);
- mDriftingBigWindow=null;
- }
- }
- /**
- * 是否有浮窗在Launcher上显示
- */
- public static boolean isDriftingWindowShowing(){
- if (mDriftingSmallWindow!=null||mDriftingBigWindow!=null) {
- return true;
- } else {
- return false;
- }
- }
- /**
- * 获取WindowManager
- */
- private static WindowManager getWindowManager(Context context){
- if (mWindowManager==null) {
- mWindowManager=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- }
- return mWindowManager;
- }
- }
DriftingWindowService如下:
- package cc.cc;
- import java.util.Timer;
- import java.util.TimerTask;
- import android.app.Service;
- import android.content.Context;
- import android.content.Intent;
- import android.os.Handler;
- import android.os.IBinder;
- /**
- * 利用该服务进行定时任务
- *
- */
- public class DriftingWindowService extends Service {
- private Timer mTimer;
- private TimerTask mTimerTask;
- private Context mContext;
- private Handler mHandler;
- @Override
- public void onCreate() {
- super.onCreate();
- }
- @Override
- public void onStart(Intent intent, int startId) {
- super.onStart(intent, startId);
- mContext=this;
- mHandler=new Handler();
- mTimer=new Timer();
- mTimerTask=new TimerTaskSubclass();
- //开启定时的任务
- mTimer.schedule(mTimerTask, 100, 500);
- }
- @Override
- public IBinder onBind(Intent arg0) {
- return null;
- }
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (mTimer!=null) {
- mTimer.cancel();
- }
- }
- private class TimerTaskSubclass extends TimerTask{
- @Override
- public void run() {
- //当前是Launcher,则显示小浮窗
- if (Utils.currentIsLauncher(mContext)&&!DriftingWindowManager.isDriftingWindowShowing()) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- DriftingWindowManager.showDriftingSmallWindow(mContext);
- }
- });
- }
- //当前不是Launcher且有浮窗显示,则移除浮窗
- if(!Utils.currentIsLauncher(mContext)&&DriftingWindowManager.isDriftingWindowShowing()){
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- DriftingWindowManager.removeDriftingSmallWindow(mContext);
- DriftingWindowManager.removeDriftingBiglWindow(mContext);
- }
- });
- }
- //当前是Launcher,则更新内存使用率
- if(Utils.currentIsLauncher(mContext)){
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- DriftingWindowManager.updateDriftingSmallWindow(mContext);
- }
- });
- }
- }
- }
- }
Utils如下:
- package cc.cc;
- import java.io.BufferedReader;
- import java.io.FileReader;
- import java.io.IOException;
- import java.lang.reflect.Field;
- import java.util.List;
- import android.app.ActivityManager;
- import android.app.ActivityManager.MemoryInfo;
- import android.app.ActivityManager.RunningTaskInfo;
- import android.content.ComponentName;
- import android.content.Context;
- public class Utils {
- /**
- * 获取设备状态栏高度
- */
- public static int getStatusBarHeight(Context context) {
- int statusBarHeight = 0;
- try {
- Class clazz = Class.forName("com.android.internal.R$dimen");
- Object object = clazz.newInstance();
- Field field = clazz.getField("status_bar_height");
- // 反射出该对象中status_bar_height字段所对应的在R文件的id值
- // 该id值由系统工具自动生成,文档描述如下:
- // The desired resource identifier, as generated by the aapt tool.
- int id = Integer.parseInt(field.get(object).toString());
- // 依据id值获取到状态栏的高度,单位为像素
- statusBarHeight = context.getResources().getDimensionPixelSize(id);
- } catch (Exception e) {
- }
- return statusBarHeight;
- }
- /**
- * 判断设备当前是否停留在Launcher
- */
- public static boolean currentIsLauncher(Context context){
- boolean isLauncher=false;
- String topActivityName=getTopActivityName(context);
- if (topActivityName!=null&&topActivityName.startsWith("HomeActivity")) {
- isLauncher=true;
- }
- return isLauncher;
- }
- /**
- * 获取栈顶Activity名称
- */
- public static String getTopActivityName(Context context) {
- String topActivityName = null;
- ActivityManager activityManager =
- (ActivityManager)(context.getSystemService(android.content.Context.ACTIVITY_SERVICE));
- List<RunningTaskInfo> runningTaskInfos = activityManager.getRunningTasks(1);
- if (runningTaskInfos != null) {
- ComponentName f = runningTaskInfos.get(0).topActivity;
- String topActivityClassName = f.getClassName();
- String temp[] = topActivityClassName.split("\\.");
- // 栈顶Activity的名称
- topActivityName = temp[temp.length - 1];
- }
- return topActivityName;
- }
- /**
- * 获取当前内存的可用率
- */
- public static String getAvailMemoryPercent(Context context){
- String info=null;
- long availMemory=getAvailMemory(context);
- long totalMemory=getTotalMemory();
- float percent=(availMemory*100/totalMemory);
- info=percent+"%";
- return info;
- }
- /**
- * 获取内存总大小
- */
- public static long getTotalMemory() {
- // 系统的内存信息文件
- String filePath = "/proc/meminfo";
- String lineString;
- String[] stringArray;
- long totalMemory = 0;
- try {
- FileReader fileReader = new FileReader(filePath);
- BufferedReader bufferedReader = new BufferedReader(fileReader,1024 * 8);
- // 读取meminfo第一行,获取系统总内存大小
- lineString = bufferedReader.readLine();
- // 按照空格拆分
- stringArray = lineString.split("\\s+");
- // 获得系统总内存,单位KB
- totalMemory = Integer.valueOf(stringArray[1]).intValue();
- bufferedReader.close();
- } catch (IOException e) {
- }
- return totalMemory / 1024;
- }
- /**
- * 获取可用内存大小
- */
- public static long getAvailMemory(Context context) {
- ActivityManager activityManager =
- (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- MemoryInfo memoryInfo = new MemoryInfo();
- activityManager.getMemoryInfo(memoryInfo);
- return memoryInfo.availMem / (1024 * 1024);
- }
- }
main.xml如下:
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
- <Button
- android:id="@+id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="开启浮动窗口"
- android:layout_centerInParent="true"
- />
- </RelativeLayout>
drifting_window_big.xml如下:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/driftingBigWindowRootView"
- android:layout_width="130dip"
- android:layout_height="130dip"
- android:orientation="vertical" >
- <Button
- android:id="@+id/closeButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:text="关闭所有浮窗" />
- <Button
- android:id="@+id/backButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:text="返回到小浮窗" />
- </LinearLayout>
drifting_window_small.xml如下:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout
- android:id="@+id/driftingSmallWindowRootView"
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="45dip"
- android:layout_height="30dip"
- android:background="#00cc00"
- android:orientation="horizontal" >
- <TextView
- android:id="@+id/percentTextView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:textColor="#ff0000"
- android:layout_gravity="center_vertical"
- />
- </LinearLayout>
AndroidManifest.xml如下:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="cc.cc"
- android:versionCode="1"
- android:versionName="1.0" >
- <uses-sdk
- android:minSdkVersion="10"
- android:targetSdkVersion="10" />
- <!-- 注意权限 -->
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
- <uses-permission android:name="android.permission.GET_TASKS"/>
- <application
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
- <activity
- android:name="cc.cc.MainActivity"
- android:label="@string/app_name" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <!-- 注册服务 -->
- <service android:name="cc.cc.DriftingWindowService">
- <intent-filter >
- <action android:name="dws"/>
- </intent-filter>
- </service>
- </application>
- </manifest>