<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->su->mv /sdcard/androidvncserver /data/
<b> </b>/data/目錄可以再建一層,為/data/local。因為如果你要用程式把androidvncserver寫入的話,需要給該目錄加寫權限,這樣涉及到的東西少些。
3.2)Q2:chmod
<b> </b>755指rwxr-xr-x,是為了增加其可執行權限。和之前一樣,預設是$符需要su才#的破解機子,也隻能一步步來:adb shell->su->cd data->chmod a+x androidvncserver->./fbvncserver &
<b> </b>(su:變更使用者身份,不指定時為root;a+x:所有使用者執行權限;&:背景運作)
3.3)Q3:關閉服務
<b> </b>ps指令檢視pid:ps|grep androidvnc*(這個程式裡執行不過==)、ps -l androidvncserver
<b> </b>kill <pid>,殺死程序,即可關閉服務。
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() >= 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檔案(&:背景)
boolean result = globalUtil.rootCommand("/data/" + VNC_SERVER_FILENAME
+ " &");
if (LOGD)
Log.d(TAG, "/data/" + VNC_SERVER_FILENAME + " &:\n" + result);
changeViews(result); // 改變界面狀态
connectView.setText(getLocalIpAddress() + ":5901"); // 重設下IP顯示
/** stopBtn點選事件 */
public void stopBtn(View v) {
ArrayList<String> 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)) > 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<NetworkInterface> en = NetworkInterface
.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> 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 指令名稱&參數組成的數組
* @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<String> getPids(String execFilename) {
ArrayList<String> pidArray = new ArrayList<String>();
String result = execCommand(new String[] { "ps", "-l", execFilename },
null);
if (null != result && !"".endsWith(result)) {
String[] resultArray = result.split("\n");
int len = resultArray.length;
/* 從第二行開始周遊 */
for (int i = 1; i < 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&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,如需轉載請自行聯系原作者