android悬浮窗--获取内存显示当前内存使用量

原文地址:http://www.android100.org/html/201306/20/3224.html

运行效果:

其中,

这一块就是悬浮窗,可以随意拖动,动态显示当前内存使用量。

下面看一下代码是如何实现的:

悬浮窗的实现是用了一个service,为什么要用service呢?了解service特点的大体就会明白。下面看一下:

public class FloatService extends Service {

    WindowManager wm = null;
    WindowManager.LayoutParams wmParams = null;
    View view;
    private float mTouchStartX;
    private float mTouchStartY;
    private float x;
    private float y;
    int state;
    TextView tx1;
    TextView tx;
    ImageView iv;
    private float StartX;
    private float StartY;
    int delaytime=1000;
    @Override
    public void onCreate() {
        Log.d("FloatService", "onCreate");
        super.onCreate();
        view = LayoutInflater.from(this).inflate(R.layout.floating, null);
        tx = (TextView) view.findViewById(R.id.memunused);
        tx1 = (TextView) view.findViewById(R.id.memtotal);
        tx.setText("" + memInfo.getmem_UNUSED(this) + "KB");
        tx1.setText("" + memInfo.getmem_TOLAL() + "KB");
        iv = (ImageView) view.findViewById(R.id.img2);
        iv.setVisibility(View.GONE);
        createView();
        handler.postDelayed(task, delaytime);
    }

    private void createView() {
        // 获取WindowManager
        wm = (WindowManager) getApplicationContext().getSystemService("window");
        // 设置LayoutParams(全局变量)相关参数
        wmParams = new WindowManager.LayoutParams();
        wmParams.type = 2002;
        wmParams.flags |= 8;
        wmParams.gravity = Gravity.LEFT | Gravity.TOP; // 调整悬浮窗口至左上角
        // 以屏幕左上角为原点,设置x、y初始值
        wmParams.x = 0;
        wmParams.y = 0;
        // 设置悬浮窗口长宽数据
        wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        wmParams.format = 1;

        wm.addView(view, wmParams);

        view.setOnTouchListener(new OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                // 获取相对屏幕的坐标,即以屏幕左上角为原点
                x = event.getRawX();
                y = event.getRawY() - 25; // 25是系统状态栏的高度
                Log.i("currP", "currX" + x + "====currY" + y);// 调试信息
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    state = MotionEvent.ACTION_DOWN;
                    StartX = x;
                    StartY = y;
                    // 获取相对View的坐标,即以此View左上角为原点
                    mTouchStartX = event.getX();
                    mTouchStartY = event.getY();
                    Log.i("startP", "startX" + mTouchStartX + "====startY"
                            + mTouchStartY);// 调试信息
                    break;
                case MotionEvent.ACTION_MOVE:
                    state = MotionEvent.ACTION_MOVE;
                    updateViewPosition();
                    break;

                case MotionEvent.ACTION_UP:
                    state = MotionEvent.ACTION_UP;

                    updateViewPosition();
                    showImg();
                    mTouchStartX = mTouchStartY = 0;
                    break;
                }
                return true;
            }
        });

        iv.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent serviceStop = new Intent();
                serviceStop.setClass(FloatService.this, FloatService.class);
                stopService(serviceStop);
            }
        });

    }

    public void showImg() {
        if (Math.abs(x - StartX) < 1.5 && Math.abs(y - StartY) < 1.5
                && !iv.isShown()) {
            iv.setVisibility(View.VISIBLE);
        } else if (iv.isShown()) {
            iv.setVisibility(View.GONE);
        }
    }

    private Handler handler = new Handler();
    private Runnable task = new Runnable() {
        public void run() {
            // TODO Auto-generated method stub
            dataRefresh();
            handler.postDelayed(this, delaytime);
            wm.updateViewLayout(view, wmParams);
        }
    };

    public void dataRefresh() {
        tx.setText("" + memInfo.getmem_UNUSED(this) + "KB");
        tx1.setText("" + memInfo.getmem_TOLAL() + "KB");
    }

    private void updateViewPosition() {
        // 更新浮动窗口位置参数
        wmParams.x = (int) (x - mTouchStartX);
        wmParams.y = (int) (y - mTouchStartY);
        wm.updateViewLayout(view, wmParams);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        Log.d("FloatService", "onStart");
        setForeground(true);
        super.onStart(intent, startId);
    }

    @Override
    public void onDestroy() {
        handler.removeCallbacks(task);
        Log.d("FloatService", "onDestroy");
        wm.removeView(view);
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

其主要功能部分在creatView方法里:

private void createView() {
        // 获取WindowManager
        wm = (WindowManager) getApplicationContext().getSystemService("window");
        // 设置LayoutParams(全局变量)相关参数
        wmParams = new WindowManager.LayoutParams();
        wmParams.type = 2002;
        wmParams.flags |= 8;
        wmParams.gravity = Gravity.LEFT | Gravity.TOP; // 调整悬浮窗口至左上角
        // 以屏幕左上角为原点,设置x、y初始值
        wmParams.x = 0;
        wmParams.y = 0;
        // 设置悬浮窗口长宽数据
        wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        wmParams.format = 1;

        wm.addView(view, wmParams);

        view.setOnTouchListener(new OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                // 获取相对屏幕的坐标,即以屏幕左上角为原点
                x = event.getRawX();
                y = event.getRawY() - 25; // 25是系统状态栏的高度
                Log.i("currP", "currX" + x + "====currY" + y);// 调试信息
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    state = MotionEvent.ACTION_DOWN;
                    StartX = x;
                    StartY = y;
                    // 获取相对View的坐标,即以此View左上角为原点
                    mTouchStartX = event.getX();
                    mTouchStartY = event.getY();
                    Log.i("startP", "startX" + mTouchStartX + "====startY"
                            + mTouchStartY);// 调试信息
                    break;
                case MotionEvent.ACTION_MOVE:
                    state = MotionEvent.ACTION_MOVE;
                    updateViewPosition();
                    break;

                case MotionEvent.ACTION_UP:
                    state = MotionEvent.ACTION_UP;

                    updateViewPosition();
                    showImg();
                    mTouchStartX = mTouchStartY = 0;
                    break;
                }
                return true;
            }
        });

        iv.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent serviceStop = new Intent();
                serviceStop.setClass(FloatService.this, FloatService.class);
                stopService(serviceStop);
            }
        });

    }

首先,代码里面用到了 WindowManager借口,整 个Android的窗口机制是基于一个叫做 WindowManager,这个接口可以添加view到屏幕,也可以从屏幕删除view。它面向的对象一端是屏幕,另一端就是View,直接忽略我们以 前的Activity或者Dialog之类的东东。其实我们的Activity或者Diolog底层的实现也是通过WindowManager,这个 WindowManager是全局的,整个系统就是这个唯一的东东。它是显示View的最底层了。(该段文字来自网络)其方法很简单,基本用到的就三个addView,removeView,updateViewLayout。另:在设置View高度和宽度的时候一 个错误,即在View的构造函数中获取getWidth()和getHeight(),当一个view对象创建时,android并不知道其大小,所以 getWidth()和getHeight()返回的结果是0,真正大小是在计算布局时才会计算,所以会发现一个有趣的事,即在onDraw( ) 却能取得长宽的原因。使用一下方法即可:

width = activity.getWindowManager().getDefaultDisplay().getWidth();
height = activity.getWindowManager().getDefaultDisplay().getHeight(); 

下面是LayoutParams,设置他的属性:

在这里是设置成了所有应用程序之上,状态栏之下的形式,当移动的时候,会调用case MotionEvent.ACTION_MOVE:

下面的代码主要是:

private void updateViewPosition() {
        // 更新浮动窗口位置参数
        wmParams.x = (int) (x - mTouchStartX);
        wmParams.y = (int) (y - mTouchStartY);
        wm.updateViewLayout(view, wmParams);
    }

从新设置浮动栏的位置参数。这样就实现了拖动的功能。其内存数据是如何获取及及时更新的呢?

我们注意到了handler:

handler.postDelayed(task, delaytime);                                                                                                                       private Runnable task = new Runnable() {
        public void run() {
            // TODO Auto-generated method stub
            dataRefresh();
            handler.postDelayed(this, delaytime);
            wm.updateViewLayout(view, wmParams);
        }
    };  

我们找到dataRefresh方法,delaytime是设置的1000,也就是每一秒钟更新一次数据。

public void dataRefresh() {
        tx.setText("" + memInfo.getmem_UNUSED(this) + "KB");
        tx1.setText("" + memInfo.getmem_TOLAL() + "KB");
    }

最后,看下memInfo的定义:

public class memInfo {

    public static long getmem_UNUSED(Context mContext) {
        long MEM_UNUSED;
        ActivityManager am = (ActivityManager) mContext
                .getSystemService(Context.ACTIVITY_SERVICE);
        ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
        am.getMemoryInfo(mi);
        MEM_UNUSED = mi.availMem / 1024;
        return MEM_UNUSED;
    }

    public static long getmem_TOLAL() {
        long mTotal;
        // 系统内存
        String path = "/proc/meminfo";
        // 存储器内容
        String content = null;
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(path), 8);
            String line;
            if ((line = br.readLine()) != null) {
                // 采集内存信息
                content = line;
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        // beginIndex
        int begin = content.indexOf(‘:‘);
        // endIndex
        int end = content.indexOf(‘k‘);
        // 采集数量的内存
        content = content.substring(begin + 1, end).trim();
        // 转换为Int型
        mTotal = Integer.parseInt(content);
        return mTotal;
    }
}

里面只定义了两个方法,获取总内存和使用内存。

时间: 2024-10-18 16:38:44

android悬浮窗--获取内存显示当前内存使用量的相关文章

Android 悬浮窗、悬浮球开发

原文:Android 悬浮窗.悬浮球开发 1.权限管理 直接看我另外一篇博客吧,传送门: https://my.oschina.net/u/1462828/blog/1933162 2.Base类BaseSuspend import android.content.Context; import android.graphics.PixelFormat; import android.os.Build; import android.view.Gravity; import android.vi

Android 悬浮窗权限校验

原文:Android 悬浮窗权限校验 悬浮窗权限: <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> 权限检验和请求: //检查是否已经授予权限,大于6.0的系统适用,小于6.0系统默认打开,无需理会 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M&&!Settings.canDrawOverlays(

关于Android悬浮窗要获取按键响应的问题

要在Android中实现顶层的窗口弹出,一般都会用WindowsManager来实现,但是几乎所有的网站资源都是说弹出的悬浮窗不用接受任何按键响应. 而问题就是,我们有时候需要他响应按键,比如电视上的android,我们要它响应遥控器上的音量按键等等之类的.这时就必须要对添加的View进行LayoutParams的相关设置了. 主要的代码就两个地方. 第一,添加的view不可以设置layoutParams.flags=LayoutParams.FLAG_NOT_FOCUSABLE;//否则就完全

28.悬浮窗、listview显示不同条目

APP管理界面 布局 用户程序那一行一直在最上面,拖动到系统程序时又显示系统多少个 <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:id="@+id/ll_loading" android:layout_width="fill_parent"

Android悬浮窗实现 使用WindowManager

本文转载自: http://blog.csdn.net/stevenhu_223/article/details/8504058 悬浮窗口的实现涉及到WindowManager(基于4.0源码分析),它是一个接口,实现类有WindowManagerImpl,CompatModeWrapper(WindowManagerImpl的内部类),LocalWindowManager(Window的内部类),它们之间的关系如下图的类图: WindowManagerImpl: 1.是WindowManage

Android悬浮窗原理解析(Window)[源码]

悬浮窗,在大多数应用中还是很少见的,目前我们接触到的悬浮窗,差不多都是一些系统级的应用软件,例如:360安全卫士,腾讯手机管家等:在某些服务行业如金融,餐饮等,也会在应用中添加悬浮窗,例如:美团的偷红包,博闻金融快捷联系等.但两种悬浮窗还是有区别的: 系统悬浮窗:所有界面都会展示,包括主屏.锁屏 应用悬浮窗:只在应用Activity中展示. 一.窗口Window 在了解悬浮窗之前,首先我们需要认识一下Android窗口Window.Android Framework将窗口分为三个类型: 应用窗口

Android 悬浮窗

iPhone有个很好用的白色圆点,今天就来研究下Android中的悬浮框,这里主要是实现一个快捷键的功能,当然也可以在悬浮框中做想做的事! 悬浮窗的实现主要是通过WindowManager实现,当然WindowManager只是一个接口,想了解源码的同志们可以去看WindowManagerImpl,悬浮框主要是通过WindowManager中的addView,updateView,removeView实现 WindowManager.LayoutParams这个类用于提供悬浮窗所需的参数 Win

Android 悬浮窗各机型各系统适配大全

这篇博客主要介绍的是 Android 主流各种机型和各种版本的悬浮窗权限适配,但是由于碎片化的问题,所以在适配方面也无法做到完全的主流机型适配,这个需要大家的一起努力,这个博客的名字永远都是一个将来时,感兴趣或者找到其他机型适配方法的请留言告诉我,或者加群544645972一起交流一下,非常感谢~ 相关权限请看我的另一篇博客:android permission权限与安全机制解析(下),或者关于权限的案例使用:android WindowManager解析与骗取QQ密码案例分析. 转载请注明出处

Android 悬浮窗的实现源码

转载请标明出处:http://blog.csdn.net/pcaxb/article/details/48048529 悬浮窗的实现用到了一个Service.自定义View.Activity 效果图 悬浮窗的实现用到的权限: <!-- 仿360浮动插件需要的权限 --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission and