雙向互傳的sample.....
socket_server.....
socket_app (client 傳 bmp pixel 過來)
ByteBuffer.allocate(m_bmp.getRowBytes()*m_bmp.getHeight());
mbuffer = ByteBuffer.wrap(lmessage);
m_bmp.copyPixelsFromBuffer(mbuffer);
重點是 copyPixelsFromBuffer() ... 他會把 mbuffer (ByteBuffer type) copy 到 m_bmp的pixel buffer
但是接收到的packet 的 data type 是 Byte[].... 所以需要 呼叫 mbuffer = ByteBuffer.wrap(lmessage);= 來把 Byte[] 轉成 Bytebuffer...
在 android 4.0 以後..接收socket 要另外用 thread 來實現...不可以放在主程式裡面...不然會產生
exception...
初始化 thread.....放在 onCreate()
myDatagramReceiver = new MyDatagramReceiver(111,109); // image_w, image_h
myDatagramReceiver.start();
myDatagramReceiver 的實作如下:
private class MyDatagramReceiver extends Thread {
// 建構子
MyDatagramReceiver(int w, int h){
Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
m_bmp = Bitmap.createBitmap(w, h, conf); // this creates a MUTABLE bitma
mbuffer = ByteBuffer.allocate(w*h*4);
}
// 會執行的run ()
public void run() {
String message;
byte[] lmessage = new byte[MAX_UDP_DATAGRAM_LEN];
// DatagramPacket 要綁定 Buffer.. 這裡是綁定到 lmessage
DatagramPacket packet = new DatagramPacket(lmessage, lmessage.length);
DatagramSocket socket = null;
try {
// DatagramSocket 要綁定到 port... 由於是接收...所以不需要對方的ip....
socket = new DatagramSocket(UDP_SERVER_PORT);
while(bKeepRunning) {
socket.receive(packet);
Log.i(TAG, "receive: " + packet.getLength() +" bytes\n" );
ByteBuffer.allocate(m_bmp.getRowBytes()*m_bmp.getHeight());
mbuffer = ByteBuffer.wrap(lmessage);
m_bmp.copyPixelsFromBuffer(mbuffer);
runOnUiThread(updateTextMessage);
}
} catch (Throwable e) {
e.printStackTrace();
}
if (socket != null) {
socket.close();
}
}
public Bitmap getbmp() {
return m_bmp;
}
}
private Runnable updateTextMessage = new Runnable() {
public void run() {
if (myDatagramReceiver == null)
return;
mImageView.setImageBitmap(myDatagramReceiver.getbmp());
}
};
傳送 socket ....
設計按下按鈕...可以傳送字串出去
btn1 = (Button)findViewById(R.id.button1);
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
new MyThread("Ack",UDP_CLIENT_PORT,server_ip).start();
}
});
由於是socket 的關係....不能放在主程式....所以也是要另外開thread 來做
class MyThread extends Thread
{
private String m_str;
private int m_port;
private String m_ip;
// 建構子
MyThread(String str, int port, String ip){
m_str = str;
m_port = port;
m_ip = ip;
}
@Override
public void run()
{
UDPSend();
}
void UDPSend()
{
String messageStr = m_str;
try
{
// 先建立一個 DatagramSocket ....
DatagramSocket s = new DatagramSocket();
InetAddress local = null;
// 得到 InetAddress ....這時候要指定對方的ip
local = InetAddress.getByName(m_ip);
int msg_length = messageStr.length();
byte[] message = messageStr.getBytes();
// 綁定 DatagramPacket ..... DatagramPacket(message, msg_length, local, m_port);
DatagramPacket p = new DatagramPacket(message, msg_length, local, m_port);
s.send(p);
android.util.Log.w("UDP", "Works fine!");
}
catch (SocketException e)
{
e.printStackTrace();
}
catch (UnknownHostException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (Exception e)
{
android.util.Log.w("UDP", "Catched here.");
e.printStackTrace();
}
}
}
完整程式碼如下:
==================================================
package com.example.socket_server;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends Activity {
private ImageView mImageView;
public static String server_ip = "192.168.26.67";
private static String TAG = "socket_server";
private boolean listening=true;
private TextView text1;
private Button btn1;
private static final int MAX_UDP_DATAGRAM_LEN = 48396;
private static final int UDP_SERVER_PORT = 7100;
private static final int UDP_CLIENT_PORT = 7001;
private MyDatagramReceiver myDatagramReceiver = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
text1 = (TextView) findViewById(R.id.textView1);
myDatagramReceiver = new MyDatagramReceiver(111,109);
myDatagramReceiver.start();
mImageView = (ImageView) findViewById(R.id.imageView1);
btn1 = (Button)findViewById(R.id.button1);
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
//sendMsg("Hello world");
//flag=1;
//text1.setText(str);
new MyThread("Ack",UDP_CLIENT_PORT,server_ip).start();
}
});
}
class MyThread extends Thread
{
private String m_str;
private int m_port;
private String m_ip;
MyThread(String str, int port, String ip){
m_str = str;
m_port = port;
m_ip = ip;
}
@Override
public void run()
{
UDPSend();
}
void UDPSend()
{
//String messageStr = "Hello Android!";
String messageStr = m_str;
//int server_port = 7001;
try
{
DatagramSocket s = new DatagramSocket();
InetAddress local = null;
local = InetAddress.getByName(m_ip);
int msg_length = messageStr.length();
byte[] message = messageStr.getBytes();
DatagramPacket p = new DatagramPacket(message, msg_length, local, m_port);
s.send(p);
android.util.Log.w("UDP", "Works fine!");
}
catch (SocketException e)
{
e.printStackTrace();
}
catch (UnknownHostException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (Exception e)
{
android.util.Log.w("UDP", "Catched here.");
e.printStackTrace();
}
}
}
private class MyDatagramReceiver extends Thread {
private boolean bKeepRunning = true;
private String lastMessage = "";
private Bitmap m_bmp;
private int receive_bytes=0;
ByteBuffer mbuffer;
MyDatagramReceiver(int w, int h){
Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
m_bmp = Bitmap.createBitmap(w, h, conf); // this creates a MUTABLE bitma
mbuffer = ByteBuffer.allocate(w*h*4);
}
public void run() {
String message;
byte[] lmessage = new byte[MAX_UDP_DATAGRAM_LEN];
DatagramPacket packet = new DatagramPacket(lmessage, lmessage.length);
DatagramSocket socket = null;
try {
socket = new DatagramSocket(UDP_SERVER_PORT);
while(bKeepRunning) {
socket.receive(packet);
Log.i(TAG, "receive: " + packet.getLength() +" bytes\n" );
ByteBuffer.allocate(m_bmp.getRowBytes()*m_bmp.getHeight());
mbuffer = ByteBuffer.wrap(lmessage);
m_bmp.copyPixelsFromBuffer(mbuffer);
runOnUiThread(updateTextMessage);
}
} catch (Throwable e) {
e.printStackTrace();
}
if (socket != null) {
socket.close();
}
}
public void kill() {
bKeepRunning = false;
}
public String getLastMessage() {
return lastMessage;
}
public Bitmap getbmp() {
return m_bmp;
}
}
private Runnable updateTextMessage = new Runnable() {
public void run() {
if (myDatagramReceiver == null)
return;
mImageView.setImageBitmap(myDatagramReceiver.getbmp());
//text1.setText(myDatagramReceiver.getLastMessage());
}
};
@Override
protected void onPause() {
myDatagramReceiver.kill();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
================================================================
main.xml :
================================================================
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.socket_server.MainActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Button
android:id="@+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView1"
android:layout_below="@+id/textView1"
android:layout_marginLeft="49dp"
android:layout_marginTop="90dp"
android:text="Button" />
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_marginTop="20dp"
android:layout_toRightOf="@+id/button1"
android:src="@drawable/ic_launcher" />
</RelativeLayout>
==================================================================
socket app 的原始碼如下:
package com.example.socket_app;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
private Handler mHandler;
private Button btn1;
private Button btn2;
private TextView text1;
boolean listening = true;
private Bitmap m_bmp;
private static Handler hand = new Handler();
private String serverMsgs = "";
private int flag =0;
public static String server_ip = "192.168.26.68";
private int receive_port = 7001;
private static String TAG = "socket_app";
private static final int DATA_LEN = 4096;
byte[] inBuff = new byte[DATA_LEN];
private DatagramPacket inPacket =
new DatagramPacket(inBuff , inBuff.length);
private static DatagramSocket s;
private static final int MAX_UDP_DATAGRAM_LEN = 1500;
private MyDatagramReceiver myDatagramReceiver = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
m_bmp = readbmp("/mnt/sdcard/template.bmp");
btn1 = (Button)findViewById(R.id.button1);
btn2 = (Button)findViewById(R.id.button2);
text1 = (TextView) findViewById(R.id.textView1);
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
//sendMsg("Hello world");
//flag=1;
//text1.setText(str);
new MyThread("Hello").start();
}
});
btn2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
//sendMsg("Hello world");
//flag=1;
//text1.setText(str);
//new MyThread("Android").start();
new MyThread_bmp(m_bmp).start();
}
});
myDatagramReceiver = new MyDatagramReceiver();
myDatagramReceiver.start();
}
public Bitmap readbmp(String filename){
Bitmap bitmap = BitmapFactory.decodeFile(filename);
return bitmap;
}
private class MyDatagramReceiver extends Thread {
private boolean bKeepRunning = true;
private String lastMessage = "";
public void run() {
String message;
byte[] lmessage = new byte[MAX_UDP_DATAGRAM_LEN];
DatagramPacket packet = new DatagramPacket(lmessage, lmessage.length);
DatagramSocket socket = null;
try {
socket = new DatagramSocket(7001);
while(bKeepRunning) {
Log.i(TAG, "receive:\n" );
socket.receive(packet);
Log.i(TAG, "receive: done\n" );
message = new String(lmessage, 0, packet.getLength());
lastMessage = message;
runOnUiThread(updateTextMessage);
}
} catch (Throwable e) {
e.printStackTrace();
}
if (socket != null) {
socket.close();
}
}
public void kill() {
bKeepRunning = false;
}
public String getLastMessage() {
return lastMessage;
}
}
private Runnable updateTextMessage = new Runnable() {
public void run() {
if (myDatagramReceiver == null)
return;
text1.setText(myDatagramReceiver.getLastMessage());
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
class MyThread extends Thread
{
private String m_str;
MyThread(String str){
m_str = str;
}
@Override
public void run()
{
UDPSend();
}
void UDPSend()
{
//String messageStr = "Hello Android!";
String messageStr = m_str;
int server_port = 7100;
try
{
DatagramSocket s = new DatagramSocket();
InetAddress local = null;
local = InetAddress.getByName(server_ip);
int msg_length = messageStr.length();
byte[] message = messageStr.getBytes();
DatagramPacket p = new DatagramPacket(message, msg_length, local, server_port);
s.send(p);
android.util.Log.w("UDP", "Works fine!");
}
catch (SocketException e)
{
e.printStackTrace();
}
catch (UnknownHostException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (Exception e)
{
android.util.Log.w("UDP", "Catched here.");
e.printStackTrace();
}
}
}
class MyThread_bmp extends Thread
{
private Bitmap m_bmp;
MyThread_bmp(Bitmap bmp){
m_bmp = bmp;
Log.i(TAG, "bmp byte_count :" + m_bmp.getByteCount() + "\n" );
}
@Override
public void run()
{
UDPSend();
}
void UDPSend()
{
//String messageStr = "Hello Android!";
//String messageStr = m_str;
int server_port = 7100;
try
{
DatagramSocket s = new DatagramSocket();
InetAddress local = null;
local = InetAddress.getByName(server_ip);
//int msg_length = messageStr.length();
int bytes = m_bmp.getByteCount();
//or we can calculate bytes this way. Use a different value than 4 if you don't use 32bit images.
//int bytes = b.getWidth()*b.getHeight()*4;
ByteBuffer buffer = ByteBuffer.allocate(bytes); //Create a new buffer
m_bmp.copyPixelsToBuffer(buffer); //Move the byte data to the buffer
byte[] array = buffer.array();
DatagramPacket p = new DatagramPacket(array, bytes, local, server_port);
s.send(p);
android.util.Log.w("UDP", "Works fine!");
}
catch (SocketException e)
{
e.printStackTrace();
}
catch (UnknownHostException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (Exception e)
{
android.util.Log.w("UDP", "Catched here.");
e.printStackTrace();
}
}
}
}
================================================================
main.xml :
================================================================<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.socket_app.MainActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Button
android:id="@+id/button2"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/button1"
android:layout_alignBottom="@+id/button1"
android:layout_marginLeft="29dp"
android:layout_toRightOf="@+id/button1"
android:text="Send Android" />
<Button
android:id="@+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="186dp"
android:text="Send hello" />
</RelativeLayout>
沒有留言:
張貼留言