// // _/_/_/ _/ _/_/_/_/_/ // _/ _/_/ _/_/ _/ _/ _/ _/_/ _/_/ // _/ _/_/ _/_/_/_/ _/_/_/_/ _/_/ _/ _/ _/ _/ _/ // _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ // _/_/_/ _/_/_/ _/_/_/ _/ _/ _/_/_/_/_/ _/_/ _/_/ // // // Copyright (c) 2015-2016, Geek Zoo Studio // http://www.geek-zoo.com // // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // package com.BeeFramework.service; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.ActivityManager.MemoryInfo; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.graphics.PixelFormat; import android.os.Debug; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.text.format.Formatter; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.ImageView; import android.widget.TextView; import com.BeeFramework.BeeFrameworkApp; import com.BeeFramework.Utils.LinuxUtils; import com.BeeFramework.model.BeeCallback; import com.insthub.O2OMobile.R; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Timer; import java.util.TimerTask; @SuppressLint("NewApi") public class MemoryService extends Service { private float downX;// 触发MotionEvent.ACTION_DOWN时的x坐标,mWindowManagerLayoutParams中的x的值 private float downY;// 触发MotionEvent.ACTION_DOWN时的y坐标,mWindowManagerLayoutParams中的y的值 private LayoutParams mLayoutParams;// 用于记录修改后的悬浮图标的位置(xy坐标) private float upX;// 触发MotionEvent.ACTION_UP时的x坐标,mWindowManagerLayoutParams中的x的值 private float upY;// 触发MotionEvent.ACTION_UP时的y坐标,mWindowManagerLayoutParams中的y的值 private float moveX;// 触发MotionEvent.ACTION_MOVE时的x坐标,MotionEvent.getRawX() private float moveY;// 触发MotionEvent.ACTION_MOVE时的y坐标,MotionEvent.getRawY() private float actionDownX;// 触发MotionEvent.ACTION_DOWN时通过MotionEvent.getX()函数得到的x坐标 private float actionDownY;// 触发MotionEvent.ACTION_DOWN时通过MotionEvent.getY()函数得到的y坐标 private WindowManager wManager ; private View view; private Timer timer; private ActivityManager mActivityManager = null ; private SharedPreferences mPref;// 用于保存关闭悬浮窗口时悬浮窗口的坐标 private Editor mEditor; private long _memSize; private TextView total; //总内存 private TextView avail; //剩余内存 private TextView low; //是否处于低内存状态 private TextView memSize; //当前程序所占内存 private TextView pid; //进程ID private TextView cpuUsage; //cpu使用量 private TextView processName; //进程名 private TextView networkUsage; private TextView networkWakeupTime; private TextView networkLastSecondUsage; private TextView networkLimitBandwidth; private ImageView logo; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); mPref = getSharedPreferences("sharedPref", Context.MODE_PRIVATE); BeeFrameworkApp.getInstance().currContext = this; wManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); mActivityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE); LayoutParams wmParams = new LayoutParams(); wmParams.type = LayoutParams.TYPE_PHONE; wmParams.format = PixelFormat.RGBA_8888; wmParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE; wmParams.gravity = Gravity.TOP|Gravity.LEFT ; wmParams.x = mPref.getInt("x", 0); wmParams.y = mPref.getInt("y", 0); wmParams.width = LayoutParams.WRAP_CONTENT; wmParams.height = LayoutParams.WRAP_CONTENT; mLayoutParams = wmParams;// 创建对象时需要传入对象的布局参数,本类负责更新布局参数 LayoutInflater inflater = LayoutInflater.from(this); view = inflater.inflate(R.layout.memory, null); total = (TextView) view.findViewById(R.id.f_memory_total); avail = (TextView) view.findViewById(R.id.f_memory_avail); low = (TextView) view.findViewById(R.id.f_memory_low); memSize = (TextView) view.findViewById(R.id.f_memory_memSize); pid = (TextView) view.findViewById(R.id.f_memory_pid); cpuUsage = (TextView) view.findViewById(R.id.f_memory_cpuUsage); processName = (TextView) view.findViewById(R.id.f_memory_processName); networkUsage = (TextView)view.findViewById(R.id.network_usage); networkWakeupTime = (TextView)view.findViewById(R.id.network_wakeuptime); networkLastSecondUsage = (TextView)view.findViewById(R.id.network_lastSecondUsage); networkLimitBandwidth = (TextView)view.findViewById(R.id.network_limit_bandwidth); logo = (ImageView) view.findViewById(R.id.f_logo); logo.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent(); intent.setAction("com.BeeFramework.Ban.MemoryService"); stopService(intent); } }); wManager.addView(view, wmParams); view.setOnTouchListener(new OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub int ea=event.getAction(); switch(ea){ case MotionEvent.ACTION_DOWN: downX = mLayoutParams.x; downY = mLayoutParams.y; actionDownX = event.getX(); actionDownY = event.getY(); break; case MotionEvent.ACTION_MOVE: moveX = event.getRawX(); moveY = event.getRawY() - 25; updateViewPosition(false); break; } return true; } }); timer = new Timer(); TimerTask timerTask = new TimerTask() { @Override public void run() { // TODO Auto-generated method stub Message msg = new Message(); msg.what = 1; handler.sendMessage(msg); } }; timer.schedule(timerTask, 0, 250); } private void updateViewPosition(boolean isActionUp) { if (!isActionUp) {// MotionEvent.ACTION_MOVE // 更新浮动窗口位置参数 mLayoutParams.x = (int) (moveX - actionDownX); mLayoutParams.y = (int) (moveY - actionDownY); } else {// MotionEvent.ACTION_UP if (!(Math.abs(upX - downX) > 50 || Math.abs(upY - downY) > 50)) {// 移动范围太小,返回初始位置 // 更新浮动窗口位置参数,返回触摸前的位置 mLayoutParams.x = (int) (downX); mLayoutParams.y = (int) (downY); } } wManager.updateViewLayout(view, mLayoutParams); // 更新悬浮窗口 } Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); switch(msg.what) { case 1: setContent(); break; case 2: DecimalFormat df = new DecimalFormat("#.##"); cpuUsage.setText("当前进程所占cpu:"+df.format(f)+"%"); break; } } }; public void setContent() { MemoryInfo memoryInfo = new MemoryInfo() ; mActivityManager.getMemoryInfo(memoryInfo) ; total.setText("总内存:"+formateFileSize(memoryInfo.totalMem)); avail.setText("空闲内存:"+formateFileSize(memoryInfo.availMem)); low.setText("是否处于低内存状态:"+memoryInfo.lowMemory); networkUsage.setText("传输速率:"+ BeeCallback.averageBandwidthUsedPerSecond+"bytes"); if (null != BeeCallback.throttleWakeUpTime && BeeCallback.throttleWakeUpTime.after(new Date())) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); networkWakeupTime.setText("唤醒时间:"+format.format(BeeCallback.throttleWakeUpTime)); } else { networkWakeupTime.setText(""); } networkLastSecondUsage.setText("上一秒传输速率:"+BeeCallback.bandwidthUsedInLastSecond+"bytes"); networkLimitBandwidth.setText("限定速率:"+BeeCallback.maxBandwidthPerSecond+"bytes"); getRunningAppProcessInfo(); } private String formateFileSize(long size){ return Formatter.formatFileSize(this, size); } private float f; //进程所占CPU private void getRunningAppProcessInfo() { // 通过调用ActivityManager的getRunningAppProcesses()方法获得系统里所有正在运行的进程 List<ActivityManager.RunningAppProcessInfo> appProcessList = mActivityManager.getRunningAppProcesses(); for(int i=0;i < appProcessList.size();i++) { if(appProcessList.get(i).processName.equals("com.insthub.ban")) { final int _pid = appProcessList.get(i).pid; // 用户ID 类似于Linux的权限不同,ID也就不同 比如 root等 int _uid = appProcessList.get(i).uid; // 进程名,默认是包名或者由属性android:process=""指定 String _processName = appProcessList.get(i).processName; // 获得该进程占用的内存 int[] myMempid = new int[] { _pid }; // 此MemoryInfo位于android.os.Debug.MemoryInfo包中,用来统计进程的内存信息 Debug.MemoryInfo[] memoryInfo = mActivityManager.getProcessMemoryInfo(myMempid); // 获取进程占内存用信息 kb单位 _memSize = memoryInfo[0].dalvikPrivateDirty; pid.setText("进程ID:"+_pid); //uid.setText("进程所在的UID:"+_uid); //memSize.setText("进程占用内存:"+_memSize+"k"); processName.setText("进程名:"+_processName); memSize.setText("进程占用内存:"+formateFileSize(_memSize*1024)); new Thread() { @Override public void run() { // TODO Auto-generated method stub super.run(); LinuxUtils linux = new LinuxUtils(); f = linux.syncGetProcessCpuUsage(_pid); Message msg = new Message(); msg.what = 2; handler.sendMessage(msg); } }.start(); break; } } } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); timer.cancel(); wManager.removeView(view); mEditor = mPref.edit(); mEditor.putInt("x", mLayoutParams.x); mEditor.putInt("y", mLayoutParams.y); mEditor.commit(); } }