2011年12月26日 星期一

自製 Android 測速 app

這程式是依照我之前寫的如何測試sdcard速度來完成的,其中包括呼叫ProgressDialog來表達處理中,在Thread中使用runOnUiThread來更新UI元件跟呼叫shell來執行dd程式。


1.首先是按下button啟動測試並開啟progressDialog最後更新測試結果

    private String write;
    private String read;
    public void onClickStart (View v) {
        new Thread() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {

                    write = execCommand("dd if=/dev/zero of=/sdcard/tmp.dd bs=1024 count=512000");
                    read = execCommand("dd of=/dev/zero if=/sdcard/tmp.dd bs=1024 count=512000");
                    
                    runOnUiThread(new Runnable() {
                        
                        @Override
                        public void run() {
                            // TODO Auto-generated method stub
                            textView2.setText(String.format("%.02f",(Double.parseDouble(getSpeedString(write))/1024/1024))+"MB/s");  
                            textView4.setText(String.format("%.02f",(Double.parseDouble(getSpeedString(read))/1024/1024))+"MB/s");  
                        }
                    });
                    
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                progressDialog.dismiss();
                progressDialog = null;
            }
        }.start();
        
        progressDialog = ProgressDialog.show(this, "", 
                "Testing. Please wait...", true);
    }


2.這邊主要是寫execCommand如何呼叫shell並接收stdout跟stderr並回傳,在這邊要注意當stdout或stderr超過平台的接收buffer時,可能造成程式阻塞,此時必須改用額外thread去接收stdout 或stderr,而此時最後的waitfor則是必要的,否則程式會直接結束。
    public String execCommand(String command) throws IOException {

        // start the ls command running
        // String[] args = new String[]{"sh", "-c", command};
        Runtime runtime = Runtime.getRuntime();
        Process proc = runtime.exec(command); // 呼叫linux shell

        // 輸出stderr 跟 stdout, 此方法有可能堵塞,若發生則必須用額外thread 去收stderr跟stdout
        BufferedReader errorStream = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
        BufferedReader outputStream = new BufferedReader(new InputStreamReader(proc.getInputStream()));

        String line = "";
        StringBuilder sb = new StringBuilder(line);
        while ((line = errorStream.readLine()) != null) {
            System.err.println(line);
            sb.append("stderr: ").append(line).append('\n');
        }
        while ((line = outputStream.readLine()) != null) {
            System.out.println(line);
            sb.append("stdout: ").append(line).append('\n');
        }
       
        // 使用wairFor()可以等待命令執行完成以後才返回
        // 不過因為上面已有接收stderr, 他本身就會等回傳命令全部結束才繼續,所以其實可以不用waitfor()
        try {
            System.out.println("exit value = " + proc.waitFor());

        } catch (InterruptedException e) {
            System.err.println(e);
        }
        return sb.toString();
    }


3.最後這段就是把得到的回傳資料,擷取出必要部份,在這邊就是測試出來的速度。
    private String getSpeedString (String str) {
        int end = str.lastIndexOf("bytes");
        int start = str.lastIndexOf("(");
        return str.substring(start+1, end);
    }

執行完成的圖:

沒有留言:

張貼留言