android - 在android中的服务器和客户端之间流式传输语音

标签 android sockets

我正在开发两个 Android 设备之间的语音聊天。客户端运行良好,但服务器端崩溃。

我已经更改了采样率数组大小,但它仍然崩溃。客户端一连接到服务器,服务器就崩溃了。

客户端:

package com.example.client;

import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.Menu;
import android.view.MenuItem;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;

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 android.content.Context;
import android.content.DialogInterface;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;


@TargetApi(Build.VERSION_CODES.GINGERBREAD) @SuppressLint("NewApi") public class MainActivity extends Activity {

private EditText target,target_port;
private TextView streamingLabel;
private Button startButton,stopButton;

public byte[] buffer;
public static DatagramSocket socket;
private int port=50005;        
AudioRecord recorder;

//AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);

private int sampleRate =8000;//Integer.parseInt(audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE));
private int channelConfig = AudioFormat.CHANNEL_IN_MONO;    
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;       

private boolean status = true;



@SuppressLint("NewApi") @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (android.os.Build.VERSION.SDK_INT > 9) {
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
    }


    target = (EditText) findViewById (R.id.target_IP);
    streamingLabel = (TextView) findViewById(R.id.streaming_label);
    startButton = (Button) findViewById (R.id.start_button);
    stopButton = (Button) findViewById (R.id.stop_button);
    target_port=(EditText) findViewById(R.id.target_Port);
    streamingLabel.setText("Press Start! to begin");

    startButton.setOnClickListener (startListener);
    stopButton.setOnClickListener (stopListener);
    target.setText("192.168.1.100");
    target_port.setText("50005");

   // AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
  //  String rate = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
  //  String size = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
  //  Log.d("Buffer Size and sample rate", "Size :" + size + " & Rate: " + rate);
}

private final OnClickListener stopListener = new OnClickListener() {

    @Override
    public void onClick(View arg0) {
                status = false;
                recorder.release();
                Log.d("VS","Recorder released");
    }

};

private final OnClickListener startListener = new OnClickListener() {

    @Override
    public void onClick(View arg0) {
                status = true;
                startStreaming();           
    }

};

public void startStreaming() {


    Thread streamThread = new Thread(new Runnable() {

        @Override
        public void run() {
            try {


                int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
                DatagramSocket socket = new DatagramSocket();
                Log.d("VS", "Socket Created");

                byte[] buffer = new byte[512];

                Log.d("VS","Buffer created of size " + minBufSize);
                DatagramPacket packet;

                final InetAddress destination = InetAddress.getByName(target.getText().toString());
                Log.d("VS", "Address retrieved");

                if (minBufSize != AudioRecord.ERROR_BAD_VALUE) {
                    recorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT,sampleRate,channelConfig,audioFormat,minBufSize);
                Log.d("VS", "Recorder initialized");
                if (recorder.getState() == AudioRecord.STATE_INITIALIZED)
                    recorder.startRecording();}


                while(status == true) {


                    //reading data from MIC into buffer
                    minBufSize = recorder.read(buffer, 0, buffer.length);

                    //encoding to base64
                 // String buffer1= Base64.encodeToString(buffer, Base64.DEFAULT);

                    //putting buffer in the packet
                    port=Integer.parseInt(target_port.getText().toString());
                    packet = new DatagramPacket (buffer,buffer.length,destination,port);
                    System.out.print(buffer);
                    Log.d("", "BUFERRRR");
                    socket.send(packet);


                }

            } catch(UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                Log.e("IOException message:",e.getMessage().toString());


            } 


        }

    });
    streamThread.start();
 }
 }

服务器:

package com.example.server;

import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;


@TargetApi(Build.VERSION_CODES.GINGERBREAD) @SuppressLint("NewApi") public class MainActivity extends Activity {


private Button receiveButton,stopButton;
private TextView recive;
private EditText port;
public static DatagramSocket socket;
private AudioTrack speaker;
private int port_num=50005;



private int sampleRate =44100;//Integer.parseInt(audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE));   
private int channelConfig =  AudioFormat.CHANNEL_OUT_MONO;    
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;       
int minBufSize =AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
byte[] buffer;  //256

private boolean status = true;



@SuppressLint("NewApi") @TargetApi(Build.VERSION_CODES.GINGERBREAD) @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    setContentView(R.layout.activity_main);
    if (android.os.Build.VERSION.SDK_INT > 9) {
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
    }


    receiveButton = (Button) findViewById (R.id.receive_button);
    stopButton = (Button) findViewById (R.id.stop_button);
    recive= (TextView) findViewById(R.id.receive_label);
    receiveButton.setOnClickListener(receiveListener);
    stopButton.setOnClickListener(stopListener);
    port=(EditText) findViewById(R.id.editText1);

   //AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
  //  sampleRate =Integer.parseInt( audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE));
}


private final OnClickListener stopListener = new OnClickListener() {

    @Override
    public void onClick(View v) {
        status = false;

        speaker.release();
        Log.d("VR","Speaker released");

    }

};


private final OnClickListener receiveListener = new OnClickListener() {

    @Override
    public void onClick(View arg0) {
        status = true;


        startReceiving();

    }

};

public void startReceiving() {

    Thread receiveThread = new Thread (new Runnable() {

        @Override
        public void run() {



                       buffer= new byte[1024];
                        DatagramSocket socket = null;

                        try {
                            socket = new DatagramSocket(50005);
                            Log.d("VR", "Socket Created");

                            if (minBufSize != AudioRecord.ERROR_BAD_VALUE) {
                            speaker = new AudioTrack(AudioManager.STREAM_MUSIC,sampleRate,channelConfig,audioFormat,1024,AudioTrack.MODE_STREAM);
                            if (speaker.getState() == AudioRecord.STATE_INITIALIZED)
                            speaker.play();}
                            while(status == true) {

                                DatagramPacket packet = new DatagramPacket(buffer,buffer.length);

                                socket.receive(packet);
                                Log.d("VR", "Packet Received");


                                buffer=packet.getData();
                                Log.d("VR", "Packet data read into buffer");

                               buffer= Base64.decode(buffer, Base64.DEFAULT);
                                speaker.write(buffer, 0, minBufSize);
                                Log.d("VR", "Writing buffer content to speaker");
                        }

                        } catch (SocketException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }




                }

    });
    receiveThread.start();
}}

请帮我解决这个问题。

最佳答案

问题是缓冲区大小和 while 循环

关于android - 在android中的服务器和客户端之间流式传输语音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31212651/

相关文章:

android - 我在 Android Q 中获取的 IMEI 为空?

java - 在 for 循环中嵌套 string.splits - 分配时内部 split 得到 NPE

java - 通过套接字发送 XMLEncoded SOAP 请求导致无法创建信封

c++ - 绑定(bind)套接字失败,errno 88

android - 播放Mediaplayer一定时间

android - Android Studio 3.0卡在刷新项目中

java - 通过另一个类中的列表输出数据库信息 - Eclipse Android SQLite

java - 使用移动平台的套接字在java中实现实时聊天应用程序好吗?

多线程应用程序的多个线程可以打开到同一服务器的套接字吗?

c - 为什么使用 AF_UNIX 系列的文件描述符会导致 accept() 出现 "invalid argument"错误?