Android VNC Server New

关于VNC请参见维基百科:http://zh.wikipedia.org/wiki/VNC

关于执行Android VNC Server,请参见前一篇文章:点击链接

一、VNC下载
1)fastdroid-vnc

Android VNC Server开源项目

http://code.google.com/p/fastdroid-vnc/
2)TightVNC
免费的VNC软件(这个都不需要填邮箱^^)
http://www.tightvnc.com/download.php
二、程序执行
这种方式看手机了==。Google HTC上倒是可以,详细的说明看注释了。
1)简易UI
布局一点没变动…
VNCServerNewActivity.java
  1. public class VNCServerNewActivity extends Activity {
  2. private static final String TAG = "VNCServer";
  3. private static final boolean LOGD = true;
  4. /** assets目录下的VNCServer文件名 */
  5. private static final String VNC_SERV_NAME = "fastdroid-vnc";
  6. /** Shell工具类 */
  7. private ShellUtil mShellUtil;
  8. /** dialog基础标识值 */
  9. private static final int DLG_BASE = 0;
  10. /** 获root权限失败的dialog id */
  11. private static final int DLG_ROOT_FAILED = DLG_BASE + 1;
  12. /** 开启VNC服务失败的dialog id */
  13. private static final int DLG_EXEC_FAILED = DLG_BASE + 2;
  14. /** VNC服务端口:5901 */
  15. private static final String VNC_SERV_PORT = "5901";
  16. /** 按钮 */
  17. private Button startBtn, stopBtn;
  18. /** 标签 */
  19. private TextView statusView, connectView;
  20. /** 'ps -l VNC_SERV_NAME'命令 */
  21. private static final String[] PS_VNC_SERVER = new String[] { "ps", "-l",
  22. VNC_SERV_NAME };
  23. /** 执行上述命令获取的pid结果集 */
  24. private ArrayList<String> pidList;
  25. @Override
  26. public void onCreate(Bundle savedInstanceState) {
  27. super.onCreate(savedInstanceState);
  28. setContentView(R.layout.main);
  29. mShellUtil = ShellUtil.getInstance(); // 获取实例
  30. initApp(); // 初始化应用
  31. initViews(); // 初始化组件
  32. }
  33. /** 初始化组件 */
  34. private void initViews() {
  35. startBtn = (Button) findViewById(R.id.startBtn);
  36. stopBtn = (Button) findViewById(R.id.stopBtn);
  37. statusView = (TextView) findViewById(R.id.statusView);
  38. connectView = (TextView) findViewById(R.id.connectView);
  39. updateViews(isServerOn()); // 由服务状态更新界面
  40. }
  41. /** 初始化应用 */
  42. private void initApp() {
  43. boolean result = mShellUtil.root(); // 获取ROOT权限
  44. if (LOGD)
  45. Log.d(TAG, "获取Root权限:" + result);
  46. if (result) {
  47. copyVNCServer(); // 检查VNCServer文件
  48. } else {
  49. showDialog(DLG_ROOT_FAILED); // 提示DLG_ROOT_FAILED对话框
  50. }
  51. }
  52. /** 检查VNCServer文件,不存在时复制进去 */
  53. private void copyVNCServer() {
  54. String filePath = "/data/local/" + VNC_SERV_NAME;
  55. File file = new File(filePath);
  56. /* 文件不存在时,从assets复制进去 */
  57. if (!file.exists()) {
  58. /* /data/local/目录增加所有用户的写权限 */
  59. boolean result = mShellUtil.rootCommand("chmod a+x /data/local/");
  60. if (LOGD)
  61. Log.d(TAG, "/data/local/增加写权限:" + result);
  62. // 避免某些机子new FileOutputStream(file)时报System.err==
  63. result = mShellUtil.rootCommand("touch " + filePath);
  64. if (LOGD)
  65. Log.d(TAG, "创建一个空文件:" + result);
  66. /* VNCServer文件设为777权限 */
  67. result = mShellUtil.rootCommand("chmod 777 " + filePath);
  68. if (LOGD)
  69. Log.d(TAG, "/data/local/设为777权限:" + result);
  70. if (result) {
  71. try {
  72. /* 将VNCServer文件复制入/data/local/ */
  73. InputStream is = getAssets().open(VNC_SERV_NAME);
  74. FileOutputStream fos = new FileOutputStream(file);
  75. byte[] buffer = new byte[4096];
  76. int count = 0;
  77. while ((count = is.read(buffer)) > 0) {
  78. fos.write(buffer, 0, count);
  79. }
  80. fos.close();
  81. is.close();
  82. if (LOGD)
  83. Log.d(TAG, VNC_SERV_NAME + "文件写入/data/local/!");
  84. } catch (IOException e) {
  85. e.printStackTrace();
  86. }
  87. }
  88. } else {
  89. if (LOGD)
  90. Log.d(TAG, VNC_SERV_NAME + "文件已存在/data/目录下!");
  91. }
  92. }
  93. /** startBtn点击事件 */
  94. public void startBtn(View v) {
  95. /* 执行VNCServer文件 */
  96. String cmd = "/data/local/" + VNC_SERV_NAME + " &";
  97. boolean result = mShellUtil.rootCommand(cmd);
  98. if (LOGD)
  99. Log.d(TAG, cmd + ":" + result);
  100. if (isServerOn()) { // 否开启了服务
  101. updateViews(true);
  102. } else {
  103. /**
  104. * 1)有些ROM执行开启不了T^T(ps进程显示Done,再一会就没了)
  105. * 2)用其他VNC文件发现未开启也好提示用户
  106. */
  107. showDialog(DLG_EXEC_FAILED); // 提示DLG_EXEC_FAILED对话框
  108. }
  109. }
  110. /** stopBtn点击事件 */
  111. public void stopBtn(View v) {
  112. boolean result;
  113. /** 直到关闭为止。避免kill进程仅改变了状态(遇到S->Z的情况) */
  114. while (isServerOn()) {
  115. for (String pid : pidList) {
  116. result = mShellUtil.rootCommand("kill " + pid);
  117. if (LOGD)
  118. Log.d(TAG, "kill " + pid + ":" + result);
  119. }
  120. }
  121. updateViews(false); // 更新服务关闭时的界面状态
  122. }
  123. @Override
  124. protected void onDestroy() {
  125. super.onDestroy();
  126. boolean result = mShellUtil.rootRelease(); // 释放占用资源
  127. if (LOGD)
  128. Log.d(TAG, "释放占用资源:" + result);
  129. }
  130. /** 由服务状态更新界面 */
  131. private void updateViews(boolean isServerOn) {
  132. /* 更新按钮状态 */
  133. startBtn.setEnabled(!isServerOn);
  134. stopBtn.setEnabled(isServerOn);
  135. /* 更新标签显示 */
  136. if (isServerOn) {
  137. statusView.setText(R.string.status_run);
  138. connectView.setText(getLocalIpAddress() + ":" + VNC_SERV_PORT);
  139. } else {
  140. statusView.setText(R.string.status_stop);
  141. connectView.setText(R.string.address);
  142. }
  143. }
  144. /** 是否开启了服务,并处理得到pid列表 */
  145. private boolean isServerOn() {
  146. mShellUtil.setFilter(new PsLineFilter()); // 设置过滤器
  147. // 获取ps命令的pid列表
  148. pidList = mShellUtil.execCommand(PS_VNC_SERVER, null, true);
  149. mShellUtil.resetFilter(); // 重置过滤器
  150. boolean result = (null != pidList) && (pidList.size() >= 1);
  151. if (LOGD)
  152. Log.d(TAG, "VNC服务开启状态:" + result);
  153. return result;
  154. }
  155. /** 获取IP地址 */
  156. private String getLocalIpAddress() {
  157. try {
  158. // 遍历网络接口
  159. for (Enumeration<NetworkInterface> en = NetworkInterface
  160. .getNetworkInterfaces(); en.hasMoreElements();) {
  161. NetworkInterface intf = en.nextElement();
  162. // 遍历IP地址
  163. for (Enumeration<InetAddress> enumIpAddr = intf
  164. .getInetAddresses(); enumIpAddr.hasMoreElements();) {
  165. InetAddress inetAddress = enumIpAddr.nextElement();
  166. // 非回传地址时返回
  167. if (!inetAddress.isLoopbackAddress()) {
  168. return inetAddress.getHostAddress().toString();
  169. }
  170. }
  171. }
  172. } catch (SocketException e) {
  173. e.printStackTrace();
  174. }
  175. return null;
  176. }
  177. @Override
  178. protected Dialog onCreateDialog(int id) {
  179. 省略……
  180. }
  181. }
2)Shell工具类
ShellUtil.java
  1. /** Shell工具类 */
  2. public final class ShellUtil {
  3. /** 内部类ShellUtilHolder */
  4. static class ShellUtilHolder {
  5. static ShellUtil instance = new ShellUtil();
  6. }
  7. /** 返回ShellUtil的单例 */
  8. public static ShellUtil getInstance() {
  9. return ShellUtilHolder.instance;
  10. }
  11. /** \link #root()\endlink后的进程 */
  12. private Process process;
  13. /** \link #root()\endlink后的父进程的标准输入 */
  14. private DataOutputStream dos;
  15. /** 标准输出的过滤 */
  16. private IStdoutFilter<String> mIStdoutFilter;
  17. /** 设置标准输出的过滤器 */
  18. public void setFilter(IStdoutFilter<String> filter) {
  19. this.mIStdoutFilter = filter;
  20. }
  21. /** 重置过滤器为空 */
  22. public void resetFilter() {
  23. this.mIStdoutFilter = null;
  24. }
  25. /**
  26. * @brief 切换至ROOT用户
  27. * @details 执行su命令,变更为root用户
  28. * @pre 设备已经破解,否则su不可用
  29. *
  30. * @return 是否成功
  31. */
  32. public boolean root() {
  33. try {
  34. // 执行su变更用户身份为root
  35. process = Runtime.getRuntime().exec("su");
  36. // 转成DataOutputStream方便写入字符串
  37. dos = new DataOutputStream(process.getOutputStream());
  38. } catch (Exception e) {
  39. e.printStackTrace();
  40. return false;
  41. }
  42. return true;
  43. }
  44. /**
  45. * @brief ROOT权限下执行命令
  46. * @pre 执行\link #root()\endlink
  47. *
  48. * @param cmd 命令
  49. */
  50. public boolean rootCommand(String cmd) {
  51. if (null != dos) {
  52. try {
  53. dos.writeBytes(cmd + "\n");
  54. dos.flush();
  55. } catch (IOException e) {
  56. e.printStackTrace();
  57. return false;
  58. }
  59. return true;
  60. }
  61. return false;
  62. }
  63. // /**
  64. // * @brief \link #rootCommand()\endlink后的结果
  65. // * @pre 执行\link #rootCommand()\endlink
  66. // *
  67. // * @warning 不能在stdin流输入命令后再从stdout获输出结果
  68. // * (之前测试版也放在不同位置试过,都不成,死锁?没找到更多资料)
  69. // *
  70. // * @return 输出结果的集合
  71. // */
  72. // public ArrayList<String> getStdout() {
  73. // ArrayList<String> lineArray = new ArrayList<String>();
  74. // try {
  75. // handleStdout(lineArray, process);
  76. // } catch (IOException e) {
  77. // e.printStackTrace();
  78. // }
  79. // return lineArray;
  80. // }
  81. /** 释放占用资源 */
  82. public boolean rootRelease() {
  83. try {
  84. dos.writeBytes("exit\n");
  85. dos.flush();
  86. process.waitFor(); // 等待执行完成
  87. } catch (Exception e) {
  88. e.printStackTrace();
  89. return false;
  90. } finally {
  91. try {
  92. if (null != process) {
  93. process.destroy();
  94. }
  95. if (null != dos) {
  96. dos.close();
  97. }
  98. } catch (Exception e) {
  99. e.printStackTrace();
  100. }
  101. }
  102. return true;
  103. }
  104. /**
  105. * @brief 执行一个shell命令
  106. *
  107. * @param cmd 命令&参数组成的数组
  108. * @param workDir 命令工作目录
  109. * @param isStdout 是否输出结果
  110. * @return 输出结果的集合
  111. */
  112. public ArrayList<String> execCommand(String[] cmd, String workDir,
  113. boolean isStdout) {
  114. ArrayList<String> lineArray = null;
  115. try {
  116. // 创建操作系统进程(也可以由Runtime.exec()启动)
  117. ProcessBuilder builder = new ProcessBuilder(cmd);
  118. // 设置命令工作目录
  119. if (workDir != null) {
  120. builder.directory(new File(workDir));
  121. }
  122. // 合并标准错误和标准输出
  123. builder.redirectErrorStream(true);
  124. // 启动一个新进程
  125. Process process = builder.start();
  126. // 如果输出结果的话
  127. if (isStdout) {
  128. lineArray = new ArrayList<String>(); // 创建对象
  129. handleStdout(lineArray, process);
  130. }
  131. } catch (Exception e) {
  132. e.printStackTrace();
  133. }
  134. return lineArray;
  135. }
  136. /**
  137. * 处理标准输出内容
  138. *
  139. * @throws IOException
  140. */
  141. private void handleStdout(ArrayList<String> lineArray, Process process)
  142. throws IOException {
  143. InputStream is = process.getInputStream(); // 获得标准输出流
  144. if (null != mIStdoutFilter) { // 如果设置了过滤
  145. // 判断是否是行过滤器
  146. if (mIStdoutFilter instanceof AbstractLineFilter) {
  147. // 转成BufferedReader
  148. BufferedReader br = new BufferedReader(
  149. new InputStreamReader(is));
  150. String line;
  151. while (null != (line = br.readLine())) {
  152. /* 如果未被过滤,则将处理后内容加入List */
  153. if (!mIStdoutFilter.filter(line)) {
  154. lineArray.add(mIStdoutFilter.handle());
  155. }
  156. }
  157. if (br != null) {
  158. br.close();
  159. }
  160. } else {
  161. // 默认把流直接转成字符串返回
  162. lineArray.add(inputStream2Str(is));
  163. }
  164. } else {
  165. // 默认把流直接转成字符串返回
  166. lineArray.add(inputStream2Str(is));
  167. }
  168. if (is != null) {
  169. is.close();
  170. }
  171. }
  172. /**
  173. * 输入流转成字符串
  174. *
  175. * @throws IOException
  176. */
  177. public String inputStream2Str(InputStream is) throws IOException {
  178. StringBuffer out = new StringBuffer();
  179. byte[] b = new byte[4096];
  180. for (int n; (n = is.read(b)) != -1;) {
  181. out.append(new String(b, 0, n));
  182. }
  183. return out.toString();
  184. }
  185. }
3)过滤器
IStdoutFilter.java
  1. /** 标准输出过滤接口 */
  2. public interface IStdoutFilter<T> {
  3. /**
  4. * @brief 过滤操作
  5. * @param stdout
  6. *            标准输出的内容
  7. * @return true:过滤;false:保留
  8. */
  9. boolean filter(T stdout);
  10. /**
  11. * @brief 处理操作
  12. * @return 处理后的内容
  13. */
  14. T handle();
  15. }
AbstractLineFilter.java
  1. /**
  2. * @brief 抽象的行过滤器
  3. * @details 以行的方式遍历标准输出,都进行一次过滤判断
  4. */
  5. public abstract class AbstractLineFilter implements IStdoutFilter<String> {
  6. /** 行内容 */
  7. protected String line;
  8. /**
  9. * @brief 行过滤操作
  10. * @param line
  11. *            标准输出的某行内容
  12. * @return true:过滤;false:保留
  13. */
  14. protected abstract boolean lineFilter(String line);
  15. @Override
  16. public boolean filter(String stdout) {
  17. this.line = stdout;
  18. return lineFilter(stdout);
  19. }
  20. @Override
  21. public String handle() {
  22. return line; // 默认返回原行
  23. }
  24. }
PsLineFilter.java(应该加个单例==)
  1. /**
  2. * ps命令的行过滤及处理成pid的实现
  3. */
  4. public final class PsLineFilter extends AbstractLineFilter {
  5. @Override
  6. protected boolean lineFilter(String line) {
  7. // 过滤空行及标题行
  8. if (null == line || "".endsWith(line) || line.startsWith("USER")) {
  9. return true;
  10. }
  11. return false;
  12. }
  13. @Override
  14. public String handle() {
  15. try {
  16. return line.trim().split("\\s+")[1]; // 获取PID列
  17. } catch (Exception e) { // null和越界异常
  18. return line;
  19. }
  20. }
  21. }
三、后记
这个东西貌似还得动手改源码么T^T。小弟告罄了,不想碰那个东西==。
附件工程,随便看看了……
ps:Doxygen简单生成了个chm帮助文件,在docs目录下。

我是不是很无聊了-_-!

转载于:https://blog.51cto.com/vaero/815264

Android VNC Server New相关推荐

  1. Android VNC Server

    近来发现的Android上的原生VNC Server,就是说只要手机上安装并运行这个软件,即可实现电脑上查看并控制手机了. 首先是手机端. 1)下载androidvncserver: http://c ...

  2. 编译Android VNC Server(pc远程控制android)

    1.下载fastdroid-vnc 下载:https://download.csdn.net/download/u010164190/103466602.编译libjpeg.a for fastdro ...

  3. 编译Android VNC Server

    1,在如下地址checkout源代码,我checkout的版本为0.9.7 http://code.google.com/p/android-vnc-server/source/checkout 2, ...

  4. CentOS7.4下 VNC Server的搭建和客户端的连接配置

    CentOS7.4下 VNC Server的搭建和客户端的连接配置 服务器版本:CentOS Linux release 7.4.1708 (Core) yum方式安装VNC server yum i ...

  5. Linux/ubuntu server 18.04 安装远程桌面--vnc server

    此文首发于我的个人博客:Linux/ubuntu server 18.04 安装远程桌面–vnc server - zhang0peter的个人博客 想装桌面端在服务器上的原因是我在终端中开chrom ...

  6. CentOS 6.0安装VNC Server

    2019独角兽企业重金招聘Python工程师标准>>> 环境 服务器:192.168.10.181 系统:CentOS 6.0 安装过程 1.切换至root用户 2.检测系统是否安装 ...

  7. Configuring the VNC server/viewer in Linux.

    VNCServer 配置 及Vncview的使用 1.vncserver服务的启动     redhat 及fedora 一般都自动安装了vncserver了 只要在服务列表中选中启动一下就可以了 2 ...

  8. CentOS Linux下VNC Server远程桌面配置详解

    PS:偶以前基本不用Linux的远程图形桌面,前几天有开发的同事配置CentOS的vnc有问题,找我解决,就顺便记录总结一下,这个总结是比较完整的.下面的配置在CentOS5.x和6.x.SUSE企业 ...

  9. 一章: CentOS6.5 网络配置、修改主机名、添加硬盘、压缩——解压方法、VNC—server配置

    1,配IP ,修改网络配置文件 配置网卡 # vim /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 HWADDR=00:50:56:83: ...

最新文章

  1. 在Substance Designer中创建砖墙视频教程
  2. SpringMvc之@RequestParam详解
  3. python怎么编辑图片_python读取图片并修改格式与大小的方法
  4. 我今天的收获,必备stadio 插件
  5. 使用C语言来实现模块化
  6. Github系列之二:开源 一行代码实现多形式多动画的推送小红点WZLBadge(iOS)
  7. 深度学习初学者必备资料整理
  8. 异步日志系统设计demo
  9. qt鼠标进入窗体后,窗体自动置顶
  10. 训练日志 2019.2.16
  11. 广技师计算机毕业都去哪,广东哪间大学的计算机专业比较好???
  12. anaconda python命令_怎么用anaconda命令行?
  13. CANTest软件安装成功经验
  14. 脑电时频分析-短时傅里叶变换
  15. 安卓自定义Toast的原理及实现
  16. 论文阅读-A decade of social bot detection-Communications of the ACM, 2020(机器人检测的十年综述)
  17. java计算机毕业设计共享充电宝管理系统演示录像2021MyBatis+系统+LW文档+源码+调试部署
  18. 不忘初心,能偷懒就偷懒:C#操作Word文件
  19. MATLAB 字符串数组
  20. 8.Python函数

热门文章

  1. MCGS与PLC通讯不上
  2. 在Win7中怎样打开摄像头?
  3. 路由器笔记 CCNA
  4. Windows Server 2008 R2 之二十一远程桌面服务RD之二
  5. 获取页面可见区域,屏幕区域的尺寸
  6. python调用api应用接口_Python接口测试之urllib2库应用
  7. Factory Method工厂方法
  8. MySql的连接查询
  9. CAP理论与MongoDB一致性、可用性的一些思考
  10. LeetCode: 14. Longest Common Prefix