Hallo Community!
//EDIT: Das Problem scheint gelöst zu sein. Ich habe dem Clienten einfach einen anderen Port gegeben, auf einmal gings. Ist aber nicht schlimm, damit kann ich leben^^ Jetzt ist aber ein neues Problem entstanden womit ich hätte rechnen sollen... Da ich das Bytearray als komplettes immer von einer Klasse zur anderen übertrage auf dem Mainserver hört man alles abgehackt. Gibt es eine Möglichkeit, dass ich es dort auch "streamen" kann? Gemeint ist die "SendData()"-Methode fast ganz unten in der Klasse "AudioServerClient". Dankeschön nochmal!
Ich hoffe ihr könnt mir ein wenig weiterhelfen... Ich programmiere noch nicht sehr lange Java und ich stehe irgendwie mal wieder auf dem Schlauch^^
Ich weiß, dass das einiges an Text ist womit ich euch zubombe, aber ihr
würdet mir wirkliche helfen wenn ihr mal drüberschaut. Ich drehe bald
durch hier^^
Zum Problem:
Ich möchte von Gerät A zu Gerät B Audio streamen. Zum testen habe ich hier das MIC als Audioquelle genommen. Das funktioniert auch wunderbar, allerdings nur wenn Gerät B (also der Empfänger) mit W-LAN verbunden ist und der Port (auf dem der SocketServer läuft) freigeschaltet ist. Also habe ich mir gedacht, dass die Audiodaten einen Zwischenstopp bei einem Server bei mir Zuhause einlegen, damit ich auch von unterwegs aus jederzeit Audio übertragen und empfangen kann. Der Code der bereits funktionierte habe ich mir aus einigen Tutorials und Codefetzen zusammengebastelt die ich im Netz gefunden habe. Nennen wir im weiteren Verlauf das Gerät welches Audio empfängt "Client", und das Gerät welches Audio sendet "Server". Den Zwischenstopp bei mir Zuhause "Mainserver".
Hier einmal der Teil vom Client:
public class MediaStreamClient {
public static final String LOG_TAG = "Tag";
static final int frequency = 44100;
static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
boolean isPlaying;
int playBufSize;
ServerSocket sockfd;
Socket connfd;
AudioTrack audioTrack;
public MediaStreamClient(final Context ctx, final int port) {
playBufSize=AudioTrack.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
audioTrack = new AudioTrack(AudioManager.STREAM_VOICE_CALL, frequency, channelConfiguration, audioEncoding, playBufSize, AudioTrack.MODE_STREAM);
audioTrack.setStereoVolume(1f, 1f);
new Thread() {
public void run() {
byte[] buffer = new byte[playBufSize];
try {
connfd = new Socket("{meineIP}",1338);
}catch(IOException e) {
e.printStackTrace();
}
audioTrack.play();
isPlaying = true;
while (isPlaying) {
int readSize = 0;
try { readSize = connfd.getInputStream().read(buffer); }
catch (Exception e) {
e.printStackTrace();
}
audioTrack.write(buffer, 0, readSize);
}
audioTrack.stop();
try { connfd.close();}
catch (Exception e) { e.printStackTrace(); }
}
}.start();
}
public void stop() {
isPlaying = false;
}
public void setVolume(float lvol, float rvol) {
audioTrack.setStereoVolume(lvol, rvol);
}
}
Alles anzeigen
Dieser hatte vorher anstatt eine Verbindung aufzubauen immer auf einem Port gelauscht mittels *.accept()
Und hier der Code vom Server:
public class MediaStreamServer {
public static final String LOG_TAG = "Tag2";
static final int frequency = 44100;
static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
boolean isRecording;
int recBufSize;
Socket connfd;
AudioRecord audioRecord;
Context context;
public MediaStreamServer(final Context ctx, final int port,final String ip,final String status) {
this.context = ctx;
if(status.equals("start")) {
recBufSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency, channelConfiguration, audioEncoding, recBufSize);
new Thread() {
byte[] buffer = new byte[recBufSize];
public void run() {
try {
connfd = new Socket(ip,port);
}catch(IOException e) {
e.printStackTrace();
}
audioRecord.startRecording();
isRecording = true;
Log.d(LOG_TAG,"Sende Daten...");
while (isRecording) {
int readSize = audioRecord.read(buffer, 0, recBufSize);
try { connfd.getOutputStream().write(buffer, 0, readSize);}
catch (Exception e) {
e.printStackTrace();
}
}
audioRecord.stop();
try { connfd.close(); }
catch (Exception e) { e.printStackTrace(); }
}
}.start();
}
}
public void stop() {
isRecording = false;
}
}
Alles anzeigen
An beiden Klassen habe ich soweit nichts verändert außer beim CLienten anstatt einen ServerSocket zu erstellen, eine Verbindung zu meinem Mainserver aufzubauen.
Auf dem Mainserver lauscht ein Programm auf Port x, ob der Client eine Verbindung möchte. Falls dies der Fall ist führt er das für den Server aus:
public class AudioServer {
ServerSocket sockfd;
Socket connfd;
int recBufSize;
boolean isRecording;
AudioServerClient asc;
Socket mainsocket;
BufferedWriter out;
public AudioServer(final int Port,final Socket mainsocket) {
this.mainsocket = mainsocket;
recBufSize = 8466;
new Thread() {
byte[] buffer = new byte[recBufSize];
public void run() {
asc = new AudioServerClient(1338,sockfd);
try {
sockfd = new ServerSocket(Port);
}catch(IOException e) {
e.printStackTrace();
}
try {
connfd = sockfd.accept();
}catch(IOException e) {
e.printStackTrace();
}
isRecording = true;
while (isRecording) {
int readSize = 0;
try { readSize = connfd.getInputStream().read(buffer);}
catch (Exception e) {
e.printStackTrace();
}
asc.sendData(buffer);
}
try { connfd.close();
out.close();}
catch (Exception e) { e.printStackTrace(); }
}
}.start();
}
public void stop() {
asc.stop();
try {
wait();
}catch(InterruptedException e) {
e.printStackTrace();
}
isRecording = false;
}
}
Alles anzeigen
Nachdem diese Klasse ausgeführt worden ist startet er diese Klasse für den Clienten:
public class AudioServerClient {
//ServerSocket sockfd;
Socket connfd;
boolean isPlaying = true,sending = false;
int playBufSize = 8466;
byte[] play = new byte[8466];
public AudioServerClient(final int Port,final ServerSocket sockfd) {
new Thread() {
public void run() {
try {
connfd = sockfd.accept();
}catch(IOException e) {
e.printStackTrace();
}
while (isPlaying) {
int readSize = play.length;
try { connfd.getOutputStream().write(play, 0, readSize);}
catch (Exception e) {
e.printStackTrace();
}
}
try {
connfd.close();
}catch(IOException e) {
e.printStackTrace();
}
try {
notifyAll();
}catch(IllegalMonitorStateException e) {
e.printStackTrace();
}
try {
sockfd.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}.start();
}
public void sendData(byte[] buff) {
play = buff;
}
public void stop() {
isPlaying = false;
}
}
Alles anzeigen
Diese Klasse bekommt das volle Bufferarray aus "AudioServer" über die Methode "sendData()" und soll sie weiter streamen, allerdings klappt das aus irgendwelchen unbekannten Gründen nicht so... Sobald ich die Übertragung starte erhalte ich auf der Seite des Clienten eine Nullpointerexception für die Zeile:
Und die App auf der Serverseite stürzt ab, allerdings kann ich nicht die genaue Exception die er wirft einsehen, weil mir nichts angezeigt wird... aus was für Gründen auch immer... (recht altes Handy vielleicht?^^). Die Nullpointer lässt sich aber durch das nicht Empfangen der Daten erklären. Aber warum sendet mein Mainserver denn nichts?
Auf der Seite des Mainservers läuft alles normal... Nur wenn ich die Übertragung stoppe und wieder starte sagt er mir, dass die Adresse bereits genutzt wird. aber durch einen Neustart des Programmes auf dem Mainserver ist das auch temporär behoben.
Ich danke nochmal fürs Lesen, und hoffe, dass mir der eine oder andere helfen kann.
mfg
Barny