android开发之内存CPU监控

cpu,内存监控作为android性能测试的一部分,在日常工作中使用也比较频繁,一般测试人员都是直接adb命令输出结果或者android studio上查看内存,Cpu的趋势,再深入一点就是性能分析定位了。由于本人水平有限,就先分享个android apk 监控指定应用的cpu和内存。先附上两张效果图:

android开发之内存CPU监控_第1张图片

android开发之内存CPU监控_第2张图片

原理如下

输入需要监控的应用包名,输入监控的间隔时间,输入监控的总时间,点击监控就会执行监控命令,点击监控统计会在图标显示各项参数的最大值,最小值,平局值。点击监控详情会跳转到新的界面,展示详细的监控参数

代码如下

1.先在manifest文件加上如下权限

 
    
2.MainActivity代码如下
package com.example.monitor;

import android.content.Intent;
import android.os.CountDownTimer;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {
    EditText editText_times,editText_min,editText_package;
    Button button_top,button_reporte,cpu_btn,start_app,start_time;
    TextView countDown,cpu_max,cpu_min,cpu_ave,rss_max,rss_min,rss_ave,vss_max,vss_min,vss_ave;
    TextView total_time,wait_time,completa_time;
    FileUtils fu=new FileUtils();
    List cpu,rss,vss=new ArrayList();

    ListUtils lu=new ListUtils();

    private Handler handler = new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
   //监控详情按钮,点击后通过intent传值到新的activity
        cpu_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    cpu= fu.readcpu("/mnt/sdcard/topInfo.txt",editText_package);
                    rss= fu.readrss("/mnt/sdcard/topInfo.txt",editText_package);
                    vss=fu.readvss("/mnt/sdcard/topInfo.txt",editText_package);

                    String times=fu.read("/mnt/sdcard/totime.csv");
                    String totalTime=fu.read("/mnt/sdcard/totaltime.csv");

                    Intent intent = new Intent(MainActivity.this,TopDetailActivity.class);



                    intent.putExtra("times",times);
                    intent.putExtra("totalTime",totalTime);

                    intent.putStringArrayListExtra("cpu", (ArrayList) cpu);//key就是自己定义一个String的字符串就行了
                    intent.putStringArrayListExtra("vss", (ArrayList) vss);
                    intent.putStringArrayListExtra("rss", (ArrayList) rss);
                    startActivity(intent);
                } catch (Exception e) {
                    Toast toast=Toast.makeText(MainActivity.this, "监控文件被删除", Toast.LENGTH_SHORT);
                    toast.show();
                }
            }
        });


//监控报告按钮
        button_reporte.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread() {
                    @Override
                    public void run() {//在run()方法实现业务逻辑;
                        //...

                        //更新UI操作;
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                Liststr_cpu= null;
                                Liststr_vss= null;
                                Liststr_rss= null;
                                try {
                                    str_cpu = fu.readcpu("/mnt/sdcard/topInfo.txt",editText_package);
                                    str_rss=fu.readrss("/mnt/sdcard/topInfo.txt",editText_package);
                                    str_vss=fu.readvss("/mnt/sdcard/topInfo.txt",editText_package);

                                    List cpu_info=lu.StrToInt(str_cpu);
                                    List rss_info=lu.StrToInt(str_rss);
                                    List vss_info=lu.StrToInt(str_vss);
                                    double ave=lu.listAverage(cpu_info);
                                    double ave1=lu.listAverage(rss_info);
                                    double ave2=lu.listAverage(vss_info);


                                    Log.i("cpuinfo", Collections.max(str_cpu));
                                    Log.i("cpuinfo", Collections.min(str_cpu));
                                    Log.i("cpuinfo", cpu_info+"");
                                    Log.i("cpuinfo", ave+"");
                                    cpu_max.setText(Collections.max(str_cpu)+"%");
                                    cpu_min.setText(Collections.min(str_cpu)+"%");
                                    cpu_ave.setText(ave+"%");

                                    rss_max.setText(Collections.max(str_rss)+"K");
                                    rss_min.setText(Collections.min(str_rss)+"K");
                                    rss_ave.setText(ave1+"K");

                                    vss_max.setText(Collections.max(str_vss)+"K");
                                    vss_min.setText(Collections.min(str_vss)+"K");
                                    vss_ave.setText(ave2+"K");


                                } catch (IOException e) {
                                    Toast toast=Toast.makeText(MainActivity.this, "监控失败", Toast.LENGTH_SHORT);
                                    toast.show();
                                }catch (NoSuchElementException elementException){
                                    Toast toast=Toast.makeText(MainActivity.this, "监控应用未启动", Toast.LENGTH_SHORT);
                                    toast.show();
                                }
                            }
                        });

                    }
                }.start();
            }
        });

        //监控按钮
        button_top.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if(editText_times.getText().toString().equals("")||editText_min.getText().toString().equals("")){
                    Toast toast=Toast.makeText(MainActivity.this, "监控总时间和监控时间是必填参数", Toast.LENGTH_SHORT);
                    toast.show();
                }
                else{
                    String total=editText_min.getText().toString();


                    threadpool(5);
                    //timer.start();
                    int totalTime=Integer.parseInt(total);
                    new CountDownTimer(totalTime*1000*60, 1000) {

                        @Override
                        public void onTick(long millisUntilFinished) {
                            button_top.setEnabled(false);
                            button_top.setText("监控中");
                            countDown.setText((millisUntilFinished/1000)+"S");
                        }

                        @Override
                        public void onFinish() {
                            button_top.setEnabled(true);
                            button_top.setText("启动监控");
                            countDown.setEnabled(true);
                            countDown.setText("ok");
                        }
                    }.start();
                }


            }
        });


    }

    private void initView() {
        editText_min=(EditText) findViewById(R.id.ed_topmin);
        editText_times=(EditText)findViewById(R.id.ed_toptimes);
        editText_package=(EditText)findViewById(R.id.ed_package);
        button_top=(Button)findViewById(R.id.button_topbegin);
        button_reporte=(Button) findViewById(R.id.button_reporte);
        cpu_btn=(Button)findViewById(R.id.cpu_btn);



        countDown=(TextView)findViewById(R.id.timer);
        cpu_max=(TextView)findViewById(R.id.cpu_max);
        cpu_min=(TextView)findViewById(R.id.cpu_min);
        cpu_ave=(TextView) findViewById(R.id.cpu_ave);
        rss_max=(TextView) findViewById(R.id.rss_max);
        rss_min=(TextView)findViewById(R.id.rss_min);
        rss_ave=(TextView) findViewById(R.id.rss_ave);

        vss_max=(TextView) findViewById(R.id.vss_max);
        vss_min=(TextView) findViewById(R.id.vss_min);
        vss_ave=(TextView)findViewById(R.id.vss_ave);

    }

    public void threadpool(int case_num) {
        ExecutorService cacheThreadPool = Executors.newFixedThreadPool(5);
        if (case_num == 5) {
            cacheThreadPool.execute(new Runnable() {
                // final int index =1;
                @Override
                public void run() {
                    // String times=editText_times.getText().toString();
                    String times = editText_times.getText().toString();
                    //监控间隔时间
                    int times_num = Integer.parseInt(times);
                    String min = editText_min.getText().toString();
                    //监控总时间
                    int min_num = Integer.parseInt(min);
                    //次数
                    int n = min_num * 60 / times_num;

                    //如果监控文件不存在则创建文件
                    if (fu.topfileIsExists("/mnt/sdcard/totaltime.csv") == false) {
                        ShellUtils.execCommand("touch /mnt/sdcard/totaltime.csv", true);
                    }
                    if (fu.topfileIsExists("/mnt/sdcard/totime.csv") == false) {
                        ShellUtils.execCommand("touch /mnt/sdcard/totime.csv", false);
                    }

                    fu.writeTofile("/mnt/sdcard/totaltime.csv", min);
                    fu.writeTofile("/mnt/sdcard/totime.csv", times);
                    ShellUtils.execCommand("top -m 5 -d " + times + " -n " + n + " >/mnt/sdcard/topInfo.txt", false);

                }
            });

        }

    }

}
3.MainActivity布局代码如下


    
        
        

        
    

    

        
4.String转list工具类
package com.example.monitor;

import android.util.Log;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017/9/6.
 */

public class ListUtils {

    public List StrToInt(List str){
        List cpu_num=new ArrayList();
        for(int i = 0;i list){
       int sum=0;
        double average;
        for (int i = 0; i < list.size(); i++) {
            sum+=list.get(i);
        }
        if(list.size()==0){
            average=0;

        }
        else{
            average = sum / list.size();

        }
        Log.i("ave","======"+average);

       return average;

    }
}
5.文件处理工具类
package com.example.monitor;

import android.widget.EditText;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017/8/9.
 */

public class FileUtils {

    // 判断文件是否存在
    public static void judeDirExists(File file) {

        if (file.exists()&&file.isDirectory()) {
                System.out.println("dir exists");

        } else {
            System.out.println("dir not exists, create it ...");
            file.mkdir();
        }

    }


    public boolean topfileIsExists(String path){
        try{
            File f=new File(path);
            if(!f.exists()){
                return false;
            }

        }catch (Exception e) {
            // TODO: handle exception
            return false;
        }
        return true;
    }
    //写入到csv中
    public void writeTofile(String filepath, String content){
        String path=filepath;
        File writepath=new File(path);
        FileWriter writer=null;
        try {
            //"E:\\YallaTest\\YallaResult.csv"
            // 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
            writer = new FileWriter(writepath,false);
            writer.write(content);
            //\r\n表示换行
            //,表示换一格
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(writer != null){
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    public String read(String path) throws IOException{
        BufferedReader br = new BufferedReader(new FileReader(path));
        StringBuffer sb = new StringBuffer();
        String line = null;
        while((line= br.readLine()) != null) {
            sb.append(line);
        }

        System.out.println(sb.toString()); //sb包含所有文本内容
        return sb.toString();
    }
    public List readcpu(String path,EditText editText) throws IOException{
        String aa=editText.getText().toString();
        BufferedReader br = new BufferedReader(new FileReader(path));
        List list_str=new ArrayList();
        String line = null;
        while((line= br.readLine()) != null) {

            if(line.contains(aa)){
                String m=line.substring(line.indexOf("%")-2, line.indexOf("%"));
                //System.out.println(m);
                list_str.add(m);
            }

        }

       // System.out.println(sb.toString()); //sb包含所有文本内容
        return list_str;
    }

    public List readvss(String path,EditText editText) throws IOException{
        String aa=editText.getText().toString();
        BufferedReader br = new BufferedReader(new FileReader(path));
        List list_str=new ArrayList();
        String line = null;
        while((line= br.readLine()) != null) {
            if(line.contains(aa)){
                String q=line.substring(line.indexOf("K")-7, line.indexOf("K"));
                list_str.add(q);
            }

        }

        // System.out.println(sb.toString()); //sb包含所有文本内容
        return list_str;
    }

    public List readrss(String path,EditText editText) throws IOException{
        String aa=editText.getText().toString();
        BufferedReader br = new BufferedReader(new FileReader(path));
        List list_str=new ArrayList();
        String line = null;
        while((line= br.readLine()) != null) {
            if(line.contains(aa)){
                String g=line.substring(line.indexOf("K",line.indexOf("K")+1 )-6, line.indexOf("K",line.indexOf("K")+1 ));
                list_str.add(g);
            }

        }

        // System.out.println(sb.toString()); //sb包含所有文本内容
        return list_str;
    }


}
6.shell工具类
package com.example.monitor;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

/**
 * Created by Administrator on 2017/7/13.
 * 有效启动shell类
 */

public class ShellUtils {

    public static final String COMMAND_SU       = "su";
    public static final String COMMAND_SH       = "sh";
    public static final String COMMAND_EXIT     = "exit\n";
    public static final String COMMAND_LINE_END = "\n";

    private ShellUtils() {
        throw new AssertionError();
    }

    /**
     * check whether has root permission
     *
     * @return
     */
    public static boolean checkRootPermission() {
        return execCommand("echo root", true, false).result == 0;
    }

    /**
     * execute shell command, default return result msg
     *
     * @param command command
     * @param isRoot whether need to run with root
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(String command, boolean isRoot) {
        return execCommand(new String[] {command}, isRoot, true);
    }

    /**
     * execute shell commands, default return result msg
     *
     * @param commands command list
     * @param isRoot whether need to run with root
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(List commands, boolean isRoot) {
        return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, true);
    }

    /**
     * execute shell commands, default return result msg
     *
     * @param commands command array
     * @param isRoot whether need to run with root
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(String[] commands, boolean isRoot) {
        return execCommand(commands, isRoot, true);
    }

    /**
     * execute shell command
     *
     * @param command command
     * @param isRoot whether need to run with root
     * @param isNeedResultMsg whether need result msg
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) {
        return execCommand(new String[] {command}, isRoot, isNeedResultMsg);
    }

    /**
     * execute shell commands
     *
     * @param commands command list
     * @param isRoot whether need to run with root
     * @param isNeedResultMsg whether need result msg
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(List commands, boolean isRoot, boolean isNeedResultMsg) {
        return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, isNeedResultMsg);
    }

    /**
     * execute shell commands
     *
     * @param commands command array
     * @param isRoot whether need to run with root
     * @param isNeedResultMsg whether need result msg
     * @return 
    *
  • if isNeedResultMsg is false, {@link CommandResult#successMsg} is null and * {@link CommandResult#errorMsg} is null.
  • *
  • if {@link CommandResult#result} is -1, there maybe some excepiton.
  • *
*/ public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) { int result = -1; if (commands == null || commands.length == 0) { return new CommandResult(result, null, null); } Process process = null; BufferedReader successResult = null; BufferedReader errorResult = null; StringBuilder successMsg = null; StringBuilder errorMsg = null; DataOutputStream os = null; try { process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH); os = new DataOutputStream(process.getOutputStream()); for (String command : commands) { if (command == null) { continue; } // donnot use os.writeBytes(commmand), avoid chinese charset error os.write(command.getBytes()); os.writeBytes(COMMAND_LINE_END); os.flush(); } os.writeBytes(COMMAND_EXIT); os.flush(); result = process.waitFor(); // get command result if (isNeedResultMsg) { successMsg = new StringBuilder(); errorMsg = new StringBuilder(); successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); String s; while ((s = successResult.readLine()) != null) { successMsg.append(s); } while ((s = errorResult.readLine()) != null) { errorMsg.append(s); } } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (os != null) { os.close(); } if (successResult != null) { successResult.close(); } if (errorResult != null) { errorResult.close(); } } catch (IOException e) { e.printStackTrace(); } if (process != null) { process.destroy(); } } return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null : errorMsg.toString()); } /** * result of command *
    *
  • {@link CommandResult#result} means result of command, 0 means normal, else means error, same to excute in * linux shell
  • *
  • {@link CommandResult#successMsg} means success message of command result
  • *
  • {@link CommandResult#errorMsg} means error message of command result
  • *
* * @author Trinea 2013-5-16 */ public static class CommandResult { /** result of command **/ public int result; /** success message of command result **/ public String successMsg; /** error message of command result **/ public String errorMsg; public CommandResult(int result) { this.result = result; } public CommandResult(int result, String successMsg, String errorMsg) { this.result = result; this.successMsg = successMsg; this.errorMsg = errorMsg; } } }
7.新建一个activity命名为TopDetailActivity
package com.example.monitor;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;



import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TopDetailActivity extends AppCompatActivity {

    private TextView textView_title;
    ArrayList cpuList,rssList,vssList = new ArrayList();
    String title;
    ListView listView_detail;
    List> mapList=new ArrayList<>();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().hide();
        setContentView(R.layout.activity_top_detail);
        textView_title=(TextView) findViewById(R.id.monitor_title);
        listView_detail=(ListView) findViewById(R.id.listview_monitor);

        cpuList = getIntent().getStringArrayListExtra("cpu");
        vssList = getIntent().getStringArrayListExtra("vss");
        rssList = getIntent().getStringArrayListExtra("rss");
        // title=getIntent().getStringExtra("title");
        String times=getIntent().getStringExtra("times");
        String totalTime=getIntent().getStringExtra("totalTime");
        textView_title.setText("监控总时间为"+totalTime+"分钟,监控间隔时间为"+times+"S");


        for(int i=0;i items=new HashMap();
            if(i==0){
                items.put("cpuinfo","CPU            ");
                items.put("rssinfo","RSS                     ");
                items.put("vssinfo","VSS            ");
            }
            else{
                items.put("cpuinfo",cpuList.get(i)+"%            ");
                items.put("rssinfo",rssList.get(i)+"K            ");
                items.put("vssinfo",vssList.get(i)+"K            ");
            }

            mapList.add(items);
        }
        SimpleAdapter simplead = new SimpleAdapter(this, mapList,
                R.layout.monitor_item, new String[] { "cpuinfo", "rssinfo","vssinfo"},
                new int[] {R.id.monitor_cpuitem,R.id.monitor_rssitem,R.id.monitor_vssitem});
        listView_detail.setAdapter(simplead);


    }
}
8.TopDetailActivity布局代码如下


    

    

9.新建一个布局文件monitor_item.xml


    
    
    


10.在drawable目录下新建edittext_border.xml


    
    
11.在drawable目录下新建textview_border.xml


    
    









你可能感兴趣的:(android开发之内存CPU监控)