<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,如需转载请自行联系原作者