您的位置:首页 > 移动开发 > Android开发

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

2016-10-13 07:33 507 查看
最近课程学习中,遇到了这个问题。 网上搜了一大堆,基本都是抄来抄去的。 即使自己写的,说的也不是很完全。自己第一次用安卓开发,也走了很多弯路。所以写下这篇博客,希望初学者可以少走弯路。本文讲的都是很基础的东西。保证初学者按照步骤来,可以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;

@Override
public 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();

}

@Override
protected 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);
}

updateConversationHa
c51e
ndler.post(new updateUIThread(data));

} catch (IOException e) {
e.printStackTrace();
}
}
}

}

class updateUIThread implements Runnable {
private byte[] byteArray;

public updateUIThread(byte[] byteArray) {
this.byteArray = byteArray;
}

@Override
public 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";

@Override
public 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 {

@Override
public 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.重定向的端口号要和程序里的对应。

应该没有其他大的问题了,祝大家成功!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息