2016年7月7日 星期四

socket sample


雙向互傳的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>




沒有留言:

張貼留言