天天看點

Android VNC Server

 <b>Android VNC Server</b>

         利用shell開啟VNC服務的測試版本==

<b>一、直接開啟</b><b>VNC Server</b>

<b>1</b><b>)下載下傳位址</b>

<b>2</b><b>)參考網址</b>

<b>         </b>1、電腦控制手機的另一選擇——android vnc server

<b>         </b>2、Android vnc server 安裝

<b>3</b><b>)操作簡述</b>

         前提:機子需要是破解的,否則su不可執行。

adb push "F:/androidvncserver" /data/(放進去)

adb shell chmod 755 /data/androidvncserver(加可執行權限)

adb shell /data/androidvncserver(執行androidvncserver)

adb forward tcp:5900 tcp:5901(端口重定向,我沒弄==)

3.1)Q1:adb push

<b>         </b>有些機子破解後adb shell仍是$符,需要su後才是#。不能直接push進入/data/目錄。

<b>         </b>因而可以先adb push "F:/androidvncserver" /sdcard/,之後adb shell-&gt;su-&gt;mv /sdcard/androidvncserver /data/

<b>         </b>/data/目錄可以再建一層,為/data/local。因為如果你要用程式把androidvncserver寫入的話,需要給該目錄加寫權限,這樣涉及到的東西少些。

3.2)Q2:chmod

<b>         </b>755指rwxr-xr-x,是為了增加其可執行權限。和之前一樣,預設是$符需要su才#的破解機子,也隻能一步步來:adb shell-&gt;su-&gt;cd data-&gt;chmod a+x androidvncserver-&gt;./fbvncserver &amp;

<b>         </b>(su:變更使用者身份,不指定時為root;a+x:所有使用者執行權限;&amp;:背景運作)

3.3)Q3:關閉服務

<b>         </b>ps指令檢視pid:ps|grep androidvnc*(這個程式裡執行不過==)、ps -l androidvncserver

<b>         </b>kill &lt;pid&gt;,殺死程序,即可關閉服務。

3.4)Q4:VNC Viewer連接配接不到==

<b>         </b>1、确認android端開了VNC Server的程序

<b>         </b>2、PC端看下能不能ping通android的ip

<b>二、程式執行</b>

<b>1</b><b>)程式截圖</b>

<a target="_blank" href="http://blog.51cto.com/attachment/201203/200658935.png"></a>

<b>2</b><b>)活動類(VNCServerActivity.java</b><b>)</b>

/** 

 * @brief 利用shell開啟VNC服務的測試版本 

 * @detail 

 * Question 

 *  

 * Q1:操作設計不合理,見諒-_-!(應該一直su,不要su後執行個指令就exit) 

 *     另外,有些破解手機,預設是$而非#。現在這種操作方式就不适用了== 

 * Q2:androidvncserver這個,Google HTC開不起來== 

 *     純shell操作,看到提示“cannot get ABS_X info, Invalid argument” 

 * Q3:fbvncserver這個,我的那個Viewer接收到的畫面怎麼花綠的且有擠壓== 

 * Solution 

 * S1:先還是利用shell來開VNC服務,找下有其他的沒且重新改下流程。 

 * S2:難道要下VNCServer源碼麼?要改東西?要加JNI接口?頭疼T^T。 

 * @author Join 

 * @date 2012-3-20 

 */ 

public class VNCServerActivity extends Activity { 

    private static final String TAG = "VNCServerActivity"; 

    private static final boolean LOGD = true; 

    // assets目錄下的VNCServer檔案名 

    private static final String VNC_SERVER_FILENAME = "fbvncserver"; 

    private GlobalUtil globalUtil; // 工具類 

    private Button startBtn, stopBtn; // 按鈕 

    private TextView statusView, connectView; // 标簽 

    /* dialog identifiers */ 

    private static final int DLG_BASE = 0; 

    private static final int DLG_ROOT_FAILED = DLG_BASE + 1; 

    @Override 

    public void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState); 

        setContentView(R.layout.main); 

        startBtn = (Button) findViewById(R.id.startBtn); 

        stopBtn = (Button) findViewById(R.id.stopBtn); 

        statusView = (TextView) findViewById(R.id.statusView); 

        connectView = (TextView) findViewById(R.id.connectView); 

        // 直接獲IP位址了拼接個端口了,本應該從stdout獲的== 

        connectView.setText(getLocalIpAddress() + ":5901"); 

        globalUtil = GlobalUtil.getInstance(); // 擷取工具類 

        if (initApp()) { // 初始化應用權限 

            /* 判斷服務是否開啟了,以改變界面 */ 

            changeViews(globalUtil.getPids(VNC_SERVER_FILENAME).size() &gt;= 1); 

        } 

    } 

    /** 改變界面狀态 */ 

    private void changeViews(boolean isServerOn) { 

        startBtn.setEnabled(!isServerOn); 

        stopBtn.setEnabled(isServerOn); 

        statusView.setText(isServerOn ? R.string.status_run 

                : R.string.status_stop); 

    /** startBtn點選事件 */ 

    public void startBtn(View v) { 

        // 運作VNCServer檔案(&amp;:背景) 

        boolean result = globalUtil.rootCommand("/data/" + VNC_SERVER_FILENAME 

                + " &amp;"); 

        if (LOGD) 

            Log.d(TAG, "/data/" + VNC_SERVER_FILENAME + " &amp;:\n" + result); 

        changeViews(result); // 改變界面狀态 

        connectView.setText(getLocalIpAddress() + ":5901"); // 重設下IP顯示 

    /** stopBtn點選事件 */ 

    public void stopBtn(View v) { 

        ArrayList&lt;String&gt; pidArray = globalUtil.getPids(VNC_SERVER_FILENAME); 

        boolean result; 

        for (String pid : pidArray) { 

            result = globalUtil.rootCommand("kill " + pid); 

            if (LOGD) 

                Log.d(TAG, "kill " + pid + ":" + result); 

        changeViews(false); 

    /** 初始化應用權限 */ 

    private boolean initApp() { 

        boolean result = globalUtil.rootCommand("chmod 777 " 

                + getPackageCodePath()); 

        if (result) { 

            copyVNCServer(); // 檢查vncserver檔案 

        } else { 

            showDialog(DLG_ROOT_FAILED); // 提示退出應用 

        return result; 

    /** 檢查VNCServer檔案,不存在時複制進去 */ 

    private void copyVNCServer() { 

        String filePath = "/data/" + VNC_SERVER_FILENAME; 

        File file = new File(filePath); 

        /* 檔案不存在時,從assets複制進去 */ 

        if (!file.exists()) { 

            try { 

                /* /data/目錄增加所有使用者的寫權限 */ 

                boolean result = globalUtil.rootCommand("chmod a+w /data"); 

                if (LOGD) 

                    Log.d(TAG, "==/data/目錄增加寫權限:" + result + "=="); 

                if (result) { 

                    /* 将VNCServer檔案複制入/data/ */ 

                    InputStream is = getAssets().open(VNC_SERVER_FILENAME); 

                    FileOutputStream fos = new FileOutputStream(file); 

                    byte[] buffer = new byte[2048]; 

                    int count = 0; 

                    while ((count = is.read(buffer)) &gt; 0) { 

                        fos.write(buffer, 0, count); 

                    } 

                    fos.close(); 

                    is.close(); 

                    if (LOGD) 

                        Log.d(TAG, "==" + VNC_SERVER_FILENAME + "檔案寫入/data/!=="); 

                    /* 給VNCServer檔案增加所有使用者的執行權限 */ 

                    result = globalUtil.rootCommand("chmod a+x " + filePath); 

                        Log.d(TAG, "==" + filePath + "增加執行權限:" + result + "=="); 

                } 

            } catch (IOException e) { 

                e.printStackTrace(); 

            } 

                Log.d(TAG, "==" + VNC_SERVER_FILENAME + "檔案已存在/data/目錄下!=="); 

    protected Dialog onCreateDialog(int id) { 

        switch (id) { 

        case DLG_ROOT_FAILED: 

            return new AlertDialog.Builder(this) 

                    .setTitle(R.string.root_title) 

                    .setMessage(R.string.root_failed) 

                    .setCancelable(false) 

                    .setPositiveButton(R.string.dlg_ok, 

                            new DialogInterface.OnClickListener() { 

                                @Override 

                                public void onClick(DialogInterface dialog, 

                                        int which) { 

                                    finish(); 

                                } 

                            }).create(); 

        return super.onCreateDialog(id); 

    /** 擷取IP位址 */ 

    public String getLocalIpAddress() { 

        try { 

            for (Enumeration&lt;NetworkInterface&gt; en = NetworkInterface 

                    .getNetworkInterfaces(); en.hasMoreElements();) { 

                NetworkInterface intf = en.nextElement(); 

                for (Enumeration&lt;InetAddress&gt; enumIpAddr = intf 

                        .getInetAddresses(); enumIpAddr.hasMoreElements();) { 

                    InetAddress inetAddress = enumIpAddr.nextElement(); 

                    if (!inetAddress.isLoopbackAddress()) { 

                        return inetAddress.getHostAddress().toString(); 

        } catch (SocketException e) { 

            e.printStackTrace(); 

        return null; 

<b>3</b><b>)工具類(GlobalUtil.java</b><b>)</b><b></b>

public final class GlobalUtil { 

    /** 内部類GlobalUtilHolder */ 

    static class GlobalUtilHolder { 

        static GlobalUtil instance = new GlobalUtil(); 

    /** 傳回GlobalUtil的單例 */ 

    public static GlobalUtil getInstance() { 

        return GlobalUtilHolder.instance; 

    /** 

     * @brief ROOT權限執行一個shell指令 

     * @detail 裝置必須已破解,否則su不可用 

     *  

     * @param cmd 指令 

     * @return 傳回是否執行成功 

     * @code 

     * 修改應用權限: 

     *   String apkRoot="chmod 777 " + getPackageCodePath(); 

     *   GlobalUtil.getInstance().chmodCommand(apkRoot); 

     * @endcode 

     */ 

    public boolean rootCommand(String cmd) { 

        Process process = null; 

        DataOutputStream os = null; 

            // su變更使用者身份(不指定使用者時,預設root) 

            process = Runtime.getRuntime().exec("su"); 

            // 連接配接到子程序正常輸入的輸出流 

            os = new DataOutputStream(process.getOutputStream()); 

            os.writeBytes(cmd + "\n"); 

            os.writeBytes("exit\n"); 

            os.flush(); 

            process.waitFor(); // 等待執行完成 

        } catch (Exception e) { 

            return false; 

        } finally { 

                if (null != process) { 

                    process.destroy(); 

                if (null != os) { 

                    os.close(); 

            } catch (Exception e) { 

        return true; 

     * @brief 執行一個shell指令 

     * 

     * @param cmd 指令名稱&amp;參數組成的數組 

     * @param workDir 指令工作目錄 

     * @return 指令輸出結果 

    public String execCommand(String[] cmd, String workDir) { 

        StringBuffer result = new StringBuffer(); 

            // 建立作業系統程序(也可以由Runtime.exec()啟動) 

            ProcessBuilder builder = new ProcessBuilder(cmd); 

            // 設定指令工作目錄 

            if (workDir != null) { 

                builder.directory(new File(workDir)); 

            // 合并标準錯誤和标準輸出 

            builder.redirectErrorStream(true); 

            // 啟動一個新程序 

            Process process = builder.start(); 

            /* 獲得運作輸出結果 */ 

            InputStream is = process.getInputStream(); 

            BufferedReader br = new BufferedReader(new InputStreamReader(is)); 

            String line; 

            while (null != (line = br.readLine())) { 

                result.append(line); 

                result.append("\n"); 

            if (is != null) { 

                is.close(); 

                br.close(); 

        return result.toString(); 

     * @brief ps某一執行程式,擷取其pid 

     * @param execFilename 

     * @return pid的list 

    public ArrayList&lt;String&gt; getPids(String execFilename) { 

        ArrayList&lt;String&gt; pidArray = new ArrayList&lt;String&gt;(); 

        String result = execCommand(new String[] { "ps", "-l", execFilename }, 

                null); 

        if (null != result &amp;&amp; !"".endsWith(result)) { 

            String[] resultArray = result.split("\n"); 

            int len = resultArray.length; 

                /* 從第二行開始周遊 */ 

                for (int i = 1; i &lt; len; i++) { 

                    // 空格區分的第二個字元串 

                    pidArray.add(resultArray[i].trim().split("\\s+")[1]); 

            } catch (ArrayIndexOutOfBoundsException e) { 

        return pidArray; 

<b>三、其他參考</b>

         1、linux權限詳解

         2、Linux指令大全(修改版).zip

         3、Android執行shell指令

         4、Google Code的wiki&amp;issues

<b>四、後記</b>

         實作的不好,好多問題啊T^T。(還待完善,請多擔待!)

         ps:fastdroid-vnc這個項目好像也不錯^^

<b>1</b><b>)開啟fastdroid-vnc</b>

<b></b>

<a href="http://blog.51cto.com/attachment/201203/092746892.png" target="_blank"></a>

<b>2</b><b>)關閉fastdroid-vnc</b>

<a href="http://blog.51cto.com/attachment/201203/092746389.png" target="_blank"></a>

<a href="http://down.51cto.com/data/2360106" target="_blank">附件:http://down.51cto.com/data/2360106</a>

     本文轉自winorlose2000 51CTO部落格,原文連結:http://blog.51cto.com/vaero/812967,如需轉載請自行聯系原作者

繼續閱讀