Android

昨天正式开始 Android 编程学习与实践,由于 Android 模拟器在 WinXP 下一直未安装成功(见帖子: http://www.cnblogs.com/91program/p/5190888.html),所在将闲置很久的 Android 手机: 联想 A750 找到用于调试。
A750 是 Android 版本是: 2.3.6,在手机 上打开 USB 调试功能后,就可以通过 USB 线与 PC 连接进行调试了。
调试的主要功能是 Socket 通讯,手机做为服务器端。先用 PC 做为客户端。后期的客户端是车机,车机的系统可能是 WinCE 或 Android。
开始之前,先了解了一下 Android 编程的基本知识(后附个人学习记录的知识点),然后学习了如下链接:http://www.cnblogs.com/lknlfy/archive/2012/03/04/2379628.html 关于 Socket 编程的知识。

其中 一个关键的知识点是线程与主进程之间的消息传递机制,主要是线程中的消息传递到主进程。例如:

mHandler.sendMessage(msg); 

手机端代码如下(XML就不提供了,很简单,大家看图就知识的):
/*
 * 通过  WIFI 网络进行 Socket 通讯成功, 手机的 IP: 172.25.103.4(随个人网络环境变化)
 * 测试使用 360 随身 WIFI, PC 机的 IP: 172.25.103.1
 * */

  1 package com.jia.leozhengfirstapp;
  2 
  3 
  4 import java.io.IOException;
  5 import java.io.InputStream;
  6 import java.io.UnsupportedEncodingException;
  7 import java.net.ServerSocket;
  8 import java.net.Socket;
  9 
 10 
 11 import android.support.v7.app.ActionBarActivity;
 12 import android.annotation.SuppressLint;
 13 import android.os.Bundle;
 14 import android.os.Handler;
 15 import android.os.Message;
 16 import android.util.Log;
 17 import android.view.Menu;
 18 import android.view.MenuItem;
 19 import android.widget.TextView;
 20 import android.widget.Toast;
 21 
 22 
 23 
 24 
 25 public class MainActivity extends ActionBarActivity {
 26 
 27 
 28     private Socket clientSocket = null;
 29     private ServerSocket mServerSocket = null;
 30 
 31 
 32     private Handler mHandler = null;
 33 
 34 
 35     private AcceptThread mAcceptThread = null;
 36     private ReceiveThread mReceiveThread = null;
 37     private boolean stop = true;
 38 
 39     private TextView ipText;
 40     private TextView rcvText;
 41     private TextView ConnectStatusText;
 42 
 43     @SuppressLint("HandlerLeak")
 44     @Override
 45     protected void onCreate(Bundle savedInstanceState) {
 46         super.onCreate(savedInstanceState);
 47         setContentView(R.layout.activity_main);
 48 
 49         ipText = (TextView)findViewById(R.id.textView1);
 50         rcvText = (TextView)findViewById(R.id.textView3);
 51         ConnectStatusText = (TextView)findViewById(R.id.textView4);
 52 
 53         ConnectStatusText.setText("连接状态: 未连接");
 54 
 55         // 消息处理
 56         mHandler = new Handler()
 57         {
 58             @Override
 59             public void handleMessage(Message msg)
 60             {
 61                 switch(msg.what)
 62                 {
 63                     case 0:
 64                     {
 65                         String strAddress = (msg.obj).toString();
 66                         ipText.setText("IP地址: " + strAddress);
 67                         Log.v("Leo: IP: ", strAddress);
 68                         ConnectStatusText.setText("连接状态: 已连接");
 69                         // 显示客户端IP
 70                         // ipTextView.setText((msg.obj).toString());
 71                         // 使能发送按钮
 72                         // sendButton.setEnabled(true);
 73                         break;
 74                     }
 75                     case 1:
 76                     {
 77                         String strRcv = (msg.obj).toString();
 78                         rcvText.setText("接收到数据: " + strRcv);
 79                         Log.v("Leo: Rcv: ", strRcv);
 80                         // 显示接收到的数据
 81                         // mTextView.setText((msg.obj).toString());
 82                         break;
 83                     }
 84                 }
 85 
 86             }
 87         };
 88 
 89         mAcceptThread = new AcceptThread();
 90         // 开启监听线程
 91         mAcceptThread.start();
 92     }
 93 
 94 
 95 
 96 
 97     @Override
 98     public boolean onCreateOptionsMenu(Menu menu) {
 99         // Inflate the menu; this adds items to the action bar if it is present.
100         getMenuInflater().inflate(R.menu.main, menu);
101         return true;
102     }
103 
104 
105     @Override
106     public boolean onOptionsItemSelected(MenuItem item) {
107         // Handle action bar item clicks here. The action bar will
108         // automatically handle clicks on the Home/Up button, so long
109         // as you specify a parent activity in AndroidManifest.xml.
110         int id = item.getItemId();
111         if (id == R.id.action_settings) {
112             return true;
113         }
114         return super.onOptionsItemSelected(item);
115     }
116 
117     // 显示Toast函数
118     private void displayToast(String s)
119     {
120         Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
121     }
122 
123     private class AcceptThread extends Thread
124     {
125         @Override
126         public void run()
127         {
128             try {
129                 // 实例化ServerSocket对象并设置端口号为 12589
130                 mServerSocket = new ServerSocket(12589);
131             } catch (IOException e) {
132                 // TODO Auto-generated catch block
133                 e.printStackTrace();
134             }
135 
136             try {
137                 // 等待客户端的连接(阻塞)
138                 clientSocket = mServerSocket.accept();
139             } catch (IOException e) {
140                 // TODO Auto-generated catch block
141                 e.printStackTrace();
142             }
143 
144             mReceiveThread = new ReceiveThread(clientSocket);
145             stop = false;
146             // 开启接收线程
147             mReceiveThread.start();
148 
149             Message msg = new Message();
150             msg.what = 0;
151             // 获取客户端IP
152             msg.obj = clientSocket.getInetAddress().getHostAddress();
153             // 发送消息
154             mHandler.sendMessage(msg);
155         }
156     }
157 
158 
159 
160 
161     private class ReceiveThread extends Thread
162     {
163         private InputStream mInputStream = null;
164         private byte[] buf;
165         private String str = null;
166 
167         ReceiveThread(Socket s)
168         {
169             try {
170                 // 获得输入流
171                 this.mInputStream = s.getInputStream();
172             } catch (IOException e) {
173                 // TODO Auto-generated catch block
174                 e.printStackTrace();
175             }
176         }
177 
178         @Override
179         public void run()
180         {
181             while(!stop)
182             {
183                 this.buf = new byte[512];
184 
185                 // 读取输入的数据(阻塞读)
186                 try {
187                     this.mInputStream.read(buf);
188                 } catch (IOException e1) {
189                     // TODO Auto-generated catch block
190                     e1.printStackTrace();
191                 }
192 
193                 // 字符编码转换
194                 try {
195                     this.str = new String(this.buf, "GB2312").trim();
196                 } catch (UnsupportedEncodingException e) {
197                     // TODO Auto-generated catch block
198                     e.printStackTrace();
199                 }
200 
201                 Message msg = new Message();
202                 msg.what = 1;
203                 msg.obj = this.str;
204                 // 发送消息
205                 mHandler.sendMessage(msg);
206             }
207         }
208     }
209 }

1) 先通过 WIFI 进行 Socket 通讯
运行后,在手机上显示的未连接界面如下图:

在 PC 上运行类似于 SocketTool.exe 的工具,SocketTool.exe 的显示界面如下:

Socket 连接后,手机上显示的界面如下图:

2) 通过 USB 实现 PC 与手机的通讯
在 PC 上实现一个 Java 小应用,应用的主要代码如下:

 1 try
 2 {
 3     Runtime.getRuntime().exec("adb forward tcp:12581 tcp:12589");
 4 }
 5 catch (IOException e)
 6 {
 7     e.printStackTrace();
 8 }
 9 
10 
11 Socket socket = null;
12 try
13 {
14     InetAddress serverAddr = null;
15     OutputStream outStream = null;
16     byte[] msgBuffer = null;
17 
18     serverAddr = InetAddress.getByName("127.0.0.1");
19     System.out.println("TCP 1" + "C: Connecting...");
20 
21 
22     socket = new Socket(serverAddr, 12581); // 12581 是 PC 的端口,已重定向到 Device 的 12589 端口
23 
24     String message = "PC ADB,send message";
25     msgBuffer = message.getBytes("GB2312");
26 
27     outStream = socket.getOutputStream();
28     outStream.write(msgBuffer);
29     Thread.sleep(10000);
30 }
31 catch (UnknownHostException e1)
32 {
33     System.out.println("TCP 2" + "ERROR: " + e1.toString());
34 }
35 catch (IOException e2)
36 {
37     System.out.println("TCP 3" + "ERROR: " + e2.toString());
38 } catch (InterruptedException e3)
39 {
40     // Thread.sleep(1000); 增加的异常处理
41     e3.printStackTrace();
42 }
43 finally
44 {
45     try
46     {
47         if (socket != null)
48         {
49             socket.close();     // 关闭时会导致接收到的数据被清空,所以延时 10 秒显示
50         }
51     }
52     catch (IOException e)
53     {
54         System.out.println("TCP 4" + "ERROR: " + e.toString());
55     }
56 }

运行后,在手机上显示的界面如下图:

原文地址:https://www.cnblogs.com/91program/p/5190888.html