簡體   English   中英

實時Java android流

[英]Real time java android stream

我正在嘗試通過連接服務器(Java)-客戶端(Android)實時進行音頻循環。 服務器(PC / Java)客戶端將數據發送到客戶端(移動/ Android)並返回。

我放了一段代碼來闡明:- 服務器

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * This class implements a TCP Server.<p>
 */
public class GTCPServer {

    public static final int SERVER_PORT = 4444; // Port number
    private boolean running = true; // Boolean to control stream

    private ServerSocket serverSocket;

    // Input-Output streams:
    private DataInputStream dis;
    private DataOutputStream dos;

    // Buffer:
    private byte[] bytes;
    private static final int BUFFER_SIZE = 512 * 4; // Size

    /**
     * Constructor. Starts Server.
     */
    public GTCPServer() {
        bytes = new byte[BUFFER_SIZE]; // Create buffer

        // Put values to test:
        bytes[0] = 3;
        bytes[BUFFER_SIZE - 1] = 7;

        try {
            // Create Server Socket and wait connections.
            serverSocket = new ServerSocket(SERVER_PORT);
            System.out.println("Conecting...");

            // Within accept methode we are waiting connection.
            // When it's ready, create Client Socket:
            Socket client = serverSocket.accept();
            System.out.println("Receiving...");

            try {
                // Streams:
                dis = new DataInputStream(client.getInputStream());
                dos = new DataOutputStream(client.getOutputStream());
            } catch (Exception e) {
                System.out.println("Error.");
                e.printStackTrace();
            } 
        } catch (Exception e) {
            System.out.println("Error.");
            e.printStackTrace();
        }
    } // GTCPServer()

    /**
     * Send (write) a byte[] buffer within TCP.
     * @param buffer - Data.
     * @param offset - Position.
     * @param count - Number of bytes to write.
     */
    public void write(byte[] buffer, int offset, int count) {
        try {
            dos.write(buffer, offset, count); // Write
        } catch (IOException e) {
            e.printStackTrace();
        }
    } // write()

} // GTCPServer
  • 客戶

     import android.util.Log; import java.io.*; import java.net.InetAddress; import java.net.Socket; import com.appacoustic.java.gG; public class GTCPClient_A { public static final String SERVER_IP = "192.168.1.101"; // Server IP (PC) public static final int SERVER_PORT = 4444; // Port number private boolean running = true; // Boolean to control stream // Input-output streams: private DataInputStream dis; private DataOutputStream dos; // Buffer: private byte[] bytes; private static final int BUFFER_SIZE = 512 * 4; // Size /** * Constructor. */ public GTCPClient_A() { bytes = new byte[BUFFER_SIZE]; // Create buffer } // GTCPClient_A() /** * Execute Thread. It isn't override because we are using a subclass (connectTask) wich extends AsyncTask. */ public void run() { try { // Get InetAddress (IPv4 Server) InetAddress serverAddr = InetAddress.getByName(SERVER_IP); Log.e("GTCPClient_A", "Conecting..."); // Create a Socket ti connect with Server: Socket socket = new Socket(serverAddr, SERVER_PORT); try { dis = new DataInputStream(socket.getInputStream()); dos = new DataOutputStream(socket.getOutputStream()); int lap = 0; // Para llevar la cuenta de las vueltas while (running) { dis.read(bytes); // Leemos por TCP System.out.println("IN_ini_["+lap+"]: "+bytes[0]); System.out.println("IN_fin_["+lap+"]: "+bytes[BUFFER_SIZE - 1]); G.toc = System.currentTimeMillis(); G.ticToc(); G.tic = G.toc; dos.write(bytes); // Escribimos por TCP System.out.println("OUT_ini_["+lap+"]: "+bytes[0]); System.out.println("OUT_fin_["+lap+"]: "+bytes[BUFFER_SIZE - 1]); lap++; } } catch (Exception e) { Log.e("GTCP", "SERVIDOR: Error", e); } finally { socket.close(); } } catch (Exception e) { Log.e("GTCP", "CLIENTE: Error", e); } } // run() } // GTCPClient_A 

我已經通過藍牙和TCP對其進行了編程,但效果不佳。 延遲太多(大約5秒)。 我感到驚訝的是,當嘗試使用Java而不是Android部署客戶端時,它確實可以工作(代碼幾乎相同)。 實際上,我從服務器所在的計算機對着麥克風(我預定的JASIOHost ASIO驅動程序)講話,TCP數據傳輸到同一WiFi內的另一台計算機,返回並收聽服務器計算機中的實時揚聲器。

因此,看來問題出在Android。 但是我想要使用智能手機或平板電腦作為客戶端。

我也在Client上使用此行進行了測試:android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); // 優先

查找嘗試失敗的解決方案的Wear個月...

最后,解決方案是UDP。 它比TCP或藍牙更快。 我把代碼放在這里。 現在服務器Android

public class GUDPServer_A {

    private int PORT_NUMBER = 4444; // Nº de puerto de conexión. Usamos el mismo para Servidor y Cliente (para no liar)

    private DatagramSocket serverSocket; // Socket Servidor
    private DatagramPacket inPacket; // Paquete de entrada
    private DatagramPacket outPacket; // Paquete de salida

    private boolean running = true; // Booleano para indicar que se está a la escucha del Cliente

    // Buffers:
    public static final int BUFFER_SIZE = 1024 * 4;
    public static byte[] bytes_in;
    public static byte[] bytes_out;

    public GUDPServer_A() {
        bytes_in = new byte[BUFFER_SIZE];
        bytes_out = new byte[BUFFER_SIZE];
        try {
            serverSocket = new DatagramSocket(PORT_NUMBER); // Sólo se hace una vez ya que siempre estamos mandando por el mismo puerto
            System.out.println("Servidor UDP en marcha.");
        } catch (SocketException e) {
            System.out.println("Socket: "+e.getMessage());
        } catch (IOException e) {
            System.out.println("IO: "+e.getMessage());
        }
    } // GUDPServer_A()

    /**
     * Ejecución del hilo. El método no está sobreescrito porque usamos una subclase (connectTask) que extiende de AsyncTask.
     */
    public void run() {
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); // Le damos prioridad "-19" al Thread (Lo máximo es -20)

        int lap = 0; // Para llevar la cuenta de las vueltas
        while (running) { 
            read(bytes_in); // Recibimos el paquete desde UDP

            // Procesamos (de momento lo dejamos igual, simplemente clonamos):
            bytes_out = bytes_in.clone();

            G.toc = System.currentTimeMillis();
            G.ticToc();
            G.tic = G.toc;

            write(bytes_out); // Enviamos el paquete de vuelta

            Log.d("Vuelta:", ""+lap);
            lap++;
        }
    } // run()

    /**
     * Envía (escribe) un buffer de bytes por UDP.
     * @param buffer - La memoria intermedia donde se almacenan los datos a enviar.
     */
    public void write(byte[] buffer) {
        outPacket = new DatagramPacket(buffer, inPacket.getLength(), inPacket.getAddress(), inPacket.getPort());

        try {
            serverSocket.send(outPacket); // Enviamos el paquete
        } catch (IOException e) {
            e.printStackTrace();
        }
    } // write()

    /**
     * Recibe (lee) un buffer de bytes por UDP.
     * @param buffer - La memoria intermedia donde se almacenan los datos a recibir.
     */
    public void read(byte[] buffer) {
        inPacket = new DatagramPacket(buffer, buffer.length);

        try {
            serverSocket.receive(inPacket); // Recibimos el paquete
        } catch (IOException e) {
            e.printStackTrace();
        }
    } // read()

    /**
     * Cierra la conexión.
     */
    public void stop() {
        if (serverSocket != null) {
            serverSocket.close();
        }
    } // stop()

} // GUDPServer_A

客戶端Java

public class GUDPClient {

    private int PORT_NUMBER = 4444; // Nº de puerto de conexión. Usamos el mismo para Servidor y Cliente (para no liar)

    private DatagramSocket clientSocket; // Socket Cliente
    private DatagramPacket inPacket; // Paquete de entrada
    private DatagramPacket outPacket; // Paquete de salida

    private InetAddress host; // Dirección IP del Servidor (LG L5)
    public static final String IP_LG = "192.168.1.102"; // IP del Servidor (LG L5)
    public static final String IP_TABLET = "192.168.1.105"; // IP del Servidor (Tablet)

    /**
     * Constructor.
     */
    public GUDPClient() {
        try {
            clientSocket = new DatagramSocket(); // No hace falta darle un nº de puerto (se lo damos al paquete)
            host = InetAddress.getByName(IP_LG); // Obtenemos el host del Servidor (LG L5)
            //host = InetAddress.getByName(IP_TABLET); // Obtenemos el host del Servidor (Tablet)

            System.out.println("Cliente UDP conectado.");
        } catch (SocketException e) {
            System.out.println("Socket: "+e.getMessage());
        } catch (IOException e) {
            System.out.println("IO: "+e.getMessage());
        }
    } // GUDPClient()

    /**
     * Envía (escribe) un buffer de bytes por UDP.
     * @param buffer - La memoria intermedia donde se almacenan los datos a enviar.
     */
    public void write(byte[] buffer) {
        outPacket = new DatagramPacket(buffer, buffer.length, host, PORT_NUMBER);

        try {
            clientSocket.send(outPacket); // Enviamos el paquete por UDP
        } catch (IOException e) {
            e.printStackTrace();
        }
    } // write()

    /**
     * Recibe (lee) un buffer de bytes por UDP.
     * @param buffer - La memoria intermedia donde se almacenan los datos a recibir.
     */
    public void read(byte[] buffer) {
        inPacket = new DatagramPacket(buffer, buffer.length);

        try {
            clientSocket.receive(inPacket); // Recibimos el paquete procesado desde UDP
        } catch (IOException e) {
            e.printStackTrace();
        }
    } // read()

    /**
     * Cierra la conexión.
     */
    public void stop() {
        if (clientSocket != null) {
            clientSocket.close();
        }
    } // stop()

} // GUDPClient

重要的一件事是設置快速線程。

Android:android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);

Java:thread.setPriority(Thread.MAX_PRIORITY);

看來您正在為此目的使用tcp / ip。 您應該使用UDP進行音頻。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM