码迷,mamicode.com
首页 > 移动开发 > 详细

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

时间:2015-02-02 13:52:15      阅读:219      评论:0      收藏:0      [点我收藏+]

标签:

原文地址: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;
    }    
}

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

技术分享

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

标签:

原文地址:http://www.cnblogs.com/LoveJulin/p/4267460.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!