hi all,
i create full duplex application to transmit voice using udp protocol , i use AudioRecord to record voice and AudioTrack to play it but i hear echo

local app sends sound
remote app plays it
remote microphone hears sound being played
remote app sends what it hears back to you
you hear an echo

thanks for answering but i hear the echo in the local app first before it is played in the remote app

In that case it's probably a problem in your code, so without seeing it there's nothing more we can do.

here is the code :

package com.example.israa.modified_call;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;

import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

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.util.Arrays;


public class MainActivity extends ActionBarActivity {
    private EditText ip;
    private TextView streamingLabel;
    private Button Call,Answer,End;
    private int sendingport=50005;
    private int recievingport=50006;
    AudioRecord recorder;
    private int sampleRate = 32000 ;    
    private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    AudioTrack speaker;
    private boolean status = true;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ip = (EditText) findViewById (R.id.editText);
        streamingLabel = (TextView) findViewById(R.id.textView);
        Call = (Button) findViewById (R.id.button);
        Answer = (Button) findViewById (R.id.button2);
        End = (Button) findViewById (R.id.button3);
        streamingLabel.setText("Press Start! to begin");
        Call.setOnClickListener (startListener);
        End.setOnClickListener (stopListener);
        Answer.setOnClickListener(receiveListener);
    }

    private final View.OnClickListener stopListener = new View.OnClickListener() {

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

    };
    private final View.OnClickListener receiveListener = new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            status = true;
           Log.d("Note","RecordAudio");
            startReceiving();
         RecordAudio t=new RecordAudio();
            t.execute();
        }

    };

    private final View.OnClickListener startListener = new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            status = true;
            startStreaming();
            PlayAudio a=new PlayAudio();
            a.execute();

        }

    };

    public void startStreaming() {


        Thread streamThread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {


                    int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
                    Log.d("VS", "Socket Created");
                    byte[] buffer = new byte[32000];
                    Log.d("VS","Buffer created of size " + buffer.length);
                    DatagramPacket packet;
                    final InetAddress destination = InetAddress.getByName(ip.getText().toString());
                    Log.d("VS", "Address retrieved");
                    DatagramSocket socket = new DatagramSocket(sendingport);
                    recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,sampleRate,channelConfig,audioFormat,32000);
                    Log.d("VS", "Recorder initialized");
                    recorder.startRecording();
                    while(status == true) {
                        minBufSize = recorder.read(buffer, 0, buffer.length);
                        Log.d("VS", "Reading");

                        packet = new DatagramPacket (buffer,buffer.length,destination,sendingport);
                        Log.d("VS", "creating packet minbuffer="+minBufSize +"         buffer="+buffer.length);
                        socket.send(packet);

                    }



                } catch(UnknownHostException e) {
                    Log.e("VS", "UnknownHostException");
                }
                catch (Throwable t) {
                    Log.e("AudioTrack", "Playback Failed");
                }
           /*    catch (IOException e) {
                Log.e("VS", "IOException");
               }*/


            }

        });
        streamThread.start();
    }
    private class PlayAudio extends AsyncTask<Void, Integer, Void> {
        @Override
        protected Void doInBackground(Void... params) {

                try {

                    DatagramSocket recievingsocket = new DatagramSocket(recievingport);
                    Log.d("VR", "Socket Created");

                    int minBufSize1 = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat);

                    byte[] buffer1 = new byte[32000];

                    speaker = new AudioTrack(AudioManager.STREAM_VOICE_CALL,sampleRate,channelConfig,audioFormat,32000,AudioTrack.MODE_STREAM);
                DatagramPacket packet1 = new DatagramPacket(buffer1,buffer1.length);
                    speaker.play();
                   while(status == true) {
                        try {
                           recievingsocket.receive(packet1);
                            Log.d("VR", "Packet Received");
                            //reading content from packet
                            buffer1=packet1.getData();
                            Log.d("VR", "Packet data read into buffer    minbuffer="+minBufSize1 +"         buffer="+buffer1.length);

                            speaker.write(buffer1, 0, buffer1.length);
                            Log.d("VR", "Writing buffer content to speaker");

                        } catch(IOException e) {
                            Log.e("VR","IOException");
                        }
                        catch(Throwable t){
                            Log.e("AudioTrack", "Playback Failed");
                        }
                    }


                } catch (SocketException e) {
                    Log.e("VR", "SocketException"+e.getMessage());
                }

                return null;
            }

    }

    public void startReceiving() {

        Thread receiveThread = new Thread (new Runnable() {

            @Override
            public void run() {

                try {

                    DatagramSocket socket = new DatagramSocket(sendingport);
                    Log.d("VR", "Socket Created");

                    int minBufSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat);

                    byte[] buffer = new byte[32000];


                    speaker = new AudioTrack(AudioManager.STREAM_VOICE_CALL,sampleRate,channelConfig,audioFormat,32000,AudioTrack.MODE_STREAM);
                    DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
                   speaker.play();
                    while(status == true) {
                        try {



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


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


                            speaker.write(buffer, 0, buffer.length);
                            Log.d("VR", "Writing buffer content to speaker");

                        } catch(IOException e) {
                            Log.e("VR","IOException");
                        }
                        catch(Throwable t){
                            Log.e("AudioTrack", "Playback Failed");
                        }
                    }


                } catch (SocketException e) {
                    Log.e("VR", "SocketException"+e.getMessage());
                }


            }

        });
        receiveThread.start();
    }
    private class RecordAudio extends AsyncTask<Void, Integer, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            try {


                int minBufSize1 = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);

                Log.d("VS", "Socket Created");
                byte[] buffer1 = new byte[32000];

                Log.d("VS", "Buffer created of size " + minBufSize1);
                DatagramPacket packet1;

                final InetAddress destination = InetAddress.getByName(ip.getText().toString());
                Log.d("VS", "Address retrieved");
                DatagramSocket sendingsocket = new DatagramSocket(recievingport);

                recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelConfig, audioFormat,32000);
                Log.d("VS", "Recorder initialized");

                recorder.startRecording();


                while (status == true) {

                    //reading data from MIC into buffer
                    minBufSize1 = recorder.read(buffer1, 0, buffer1.length);
                    Log.d("VS", "Reading");
                    //putting buffer in the packet
                    packet1 = new DatagramPacket(buffer1, buffer1.length,destination,recievingport);
                    Log.d("VS", "creating packet minbuffer= "+minBufSize1 +"         buffer="+buffer1.length);

                    sendingsocket.send(packet1);



                }


            } catch (UnknownHostException e) {
                Log.e("VS", "UnknownHostException");
            } catch (Throwable t) {
                Log.e("AudioTrack", "Playback Failed");
            }
           /*    catch (IOException e) {
                Log.e("VS", "IOException");
               }*/

            return null;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.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();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}