关于如何在同一台电脑上的两个安卓模拟器之间的socket通信(图片传输)

来源:互联网 发布:电脑手写板软件下载 编辑:程序博客网 时间:2024/04/28 11:19

最近课程学习中,遇到了这个问题。 网上搜了一大堆,基本都是抄来抄去的。 即使自己写的,说的也不是很完全。自己第一次用安卓开发,也走了很多弯路。所以写下这篇博客,希望初学者可以少走弯路。本文讲的都是很基础的东西。保证初学者按照步骤来,可以run成功。

开发环境使用的Eclispe,Android SDK 4.2. 开发环境如何搭建就不赘述了。网上太多了。。

课程要求的是在同一台电脑上运行两个AVD(安卓虚拟机), 实现图片传输。从client端传输到server端。


1. 建立一个新的安卓project做为server

Application Name 、Project Name、Package Name 可以随便取。 这里就叫AndroidSocketServer了, 下面的 target SDK

以及 Compile with 都选择 api 17. 如果没有,就选择你自己的sdk. 不一定要api 17. 只是我电脑太老了, 跑Android 6.0的话

太卡了,AVD 都起不来。 然后就一直next。就可以了。

2.设置main里的参数

layout中找到main.xml(高版本里好像不叫这个名字),按照如下图设置:


因为在server中我们只需要一个现实一个图片,所以这里控件我们这要加一个ImageView就可以了,注意下

@+id/imageViewServer这个参数, 在后面的server端的程序里会有体现。

3. 在AndroidManifest.xml设置下权限

如下图设置即可,这里我们主要加了五个权限:

4.Server端的代码

</pre><pre name="code" class="java">package com.javacodegeeks.android.androidsocketserver;import java.io.DataInputStream;import java.io.IOException;import java.io.InputStream;import java.net.ServerSocket;import java.net.Socket;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.os.Handler;import android.widget.ImageView;public class Server extends Activity {private ServerSocket serverSocket;Handler updateConversationHandler;Thread serverThread = null;private ImageView imageView;public static final int SERVERPORT = 6000;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);imageView=(ImageView) findViewById(R.id.imageViewServer);updateConversationHandler = new Handler();this.serverThread = new Thread(new ServerThread());this.serverThread.start();}@Overrideprotected void onStop() {super.onStop();try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}class ServerThread implements Runnable {public void run() {Socket socket = null;try {serverSocket = new ServerSocket(SERVERPORT);} catch (IOException e) {e.printStackTrace();}while (!Thread.currentThread().isInterrupted()) {try {socket = serverSocket.accept();CommunicationThread commThread = new CommunicationThread(socket);new Thread(commThread).start();} catch (IOException e) {e.printStackTrace();}}}}class CommunicationThread implements Runnable {private Socket clientSocket;private DataInputStream input;public CommunicationThread(Socket clientSocket) {this.clientSocket = clientSocket;try {InputStream in = this.clientSocket.getInputStream();                this.input = new DataInputStream(in);   } catch (IOException e) {e.printStackTrace();}}public void run() {while (!Thread.currentThread().isInterrupted()) {try {byte[] data;//String read = input.readLine();                    int len= this.input.readInt();                                      data = new byte[len];                                       if (len > 0) {                        this.input.readFully(data,0,data.length);                    }   updateConversationHandler.post(new updateUIThread(data));} catch (IOException e) {e.printStackTrace();}}}}class updateUIThread implements Runnable {private byte[] byteArray;public updateUIThread(byte[] byteArray) {this.byteArray = byteArray;}@Overridepublic void run() {Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray , 0, byteArray .length);            imageView.setImageBitmap(bitmap);}}}

5.建一个client端的project

同server端。


6.main里的参数


这里需要注意的在client端 我们需要两个控件, 一个button 一个 ImageView。因为client端是需要穿图片过去的

所以我们需要指定image的source。我们需要把文件名为image1的图片res-> drawable-hdpi:


7.设置同样的permission


8.client端code

package com.javacodegeeks.android.androidsocketclient;import java.io.ByteArrayOutputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.Bitmap.CompressFormat;import android.graphics.drawable.BitmapDrawable;import android.os.Bundle;import android.view.View;import android.widget.ImageView;public class Client extends Activity {private Socket socket;private static final int SERVERPORT = 5000;private static final String SERVER_IP = "10.0.2.2";@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);new Thread(new ClientThread()).start();}public void onClick(View view) {try {ImageView imageView=(ImageView) findViewById(R.id.imageView1);           Bitmap bmp=((BitmapDrawable)imageView.getDrawable()).getBitmap();             ByteArrayOutputStream bos = new ByteArrayOutputStream();             bmp.compress(CompressFormat.PNG, 0 /*ignored for PNG*/, bos);             byte[] array = bos.toByteArray();            OutputStream out = socket.getOutputStream();             DataOutputStream dos = new DataOutputStream(out);            dos.writeInt(array.length);            dos.write(array, 0, array.length);} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}class ClientThread implements Runnable {@Overridepublic void run() {try {InetAddress serverAddr = InetAddress.getByName(SERVER_IP);socket = new Socket(serverAddr, SERVERPORT);} catch (UnknownHostException e1) {e1.printStackTrace();} catch (IOException e1) {e1.printStackTrace();}}}}

9. 启一个AVD做为server端

然后在server的project那右键 Run As -> run configurations. 选择当前的project 以及 server端的AVD。


然后把server端的程序运行在这个AVD上。

10. 重新建一个client端的AVD

和server端一样。 再把client端的程序跑在这个AVD上。注意启动AVD的时候速度会比较慢,如果出现android字样

就说明在启动了,慢慢等就好了。


11. 重定向

在mac终端中输入telnet localhost 5554. 注意这个端口号, 这个是server端的端口号,然后输入 redir add tcp:5000:6000. 对应server端程序和client端程序的端口号,如果提示失败,则说明需要权限。退出来之后,输入

nano ~/.emulator_console_auth_token, 把对应设备的序列号拷贝下来(我的是 kmg2cnUgI2evYbc9),然后进入

之后 auth 加上你的设备序列号即可。 再运行redir add tcp:5000:6000.



12 运行测试


成功。 

13. 总结

主要的几个点:

1. 要设置两个main.xml里的控件, 并且控件名称要与程序中的对应。具体的参照我给的程序。

2.在client端中要把图片放到指定的目录下面,并且在client的main.xml中的ImageView中指定相同的文件名。

3.要启动两个AVD,把两个project运行在不同的AVD上面。

4.重定向的端口号要和程序里的对应。

应该没有其他大的问题了,祝大家成功!


0 0