0

I want to create a VoIP system which works using AudioStream/AudioGroup and can function using only a local WiFi Hotspot. I create a WiFi-Hotspot on android device1 and connect device2 to it. When I fill in the local IP Address of device1, which I get via getLocalIPAddress(), and the IP Address of device2, which I get via the fetchIPs() method on device1, and click on 'Connect' on both devices, the code doesn't throw any exceptions, but I do not hear the microphone audio of either device.

Note1: This code is taken from this answer by @murphybro2 and is slightly changed. Note2: When using the getLocalIPAddress() on device1 (the host), the ip Address comes back as 115.163.242.10 while the fetched IP from device2 has the form 192.168.xxx.yyy

I put android.permission.INTERNET, android.permission.ACCESS_WIFI_STATE and android.permission.RECORD_AUDIO into the Manifest file

MainActivity.java:

package com.applications.fihdi.testapp487623;

import android.content.Context;
import android.media.AudioManager;
import android.net.rtp.*;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
import android.widget.*;

import java.io.*;
import java.net.*;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);


        try {
            String ip = getLocalIPAddress();
            Log.d("VOIP","String ip: " + ip);

            AudioManager audio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
            audio.setMode(AudioManager.MODE_IN_COMMUNICATION);
            final AudioGroup m_AudioGroup = new AudioGroup();
            m_AudioGroup.setMode(AudioGroup.MODE_NORMAL);
            final AudioStream m_AudioStream = new AudioStream(InetAddress.getByName(ip));
            Log.d("VOIP","localhost (same as ip??): = " + InetAddress.getLocalHost());

            int localPort = m_AudioStream.getLocalPort();

            Log.d("VOIP","Local Port: "+ Integer.toString(localPort));
            m_AudioStream.setCodec(AudioCodec.PCMU);
            m_AudioStream.setMode(RtpStream.MODE_NORMAL);

            ((TextView) findViewById(R.id.lblLocalPort)).setText(String.valueOf(localPort));

            ((TextView) findViewById(R.id.statusLabel)).setText("Status: local port number generated");

            findViewById(R.id.connectButton).setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    Log.d("VOIP","ConnectButton pressed");
                    String remoteAddress;
                    String remotePort;

                         remoteAddress = ((EditText) findViewById(R.id.editText2)).getText().toString();
                        //String remoteAddress = fetchIPs().get(0);
                         remotePort = ((EditText) findViewById(R.id.editText1)).getText().toString();

                    //Log.d("VOIP", fetchIPs().get(0));

                    try {
                        m_AudioStream.associate(InetAddress.getByName(remoteAddress), Integer.parseInt(remotePort));
                        Log.d("VOIP","AudioStream associated");
                        ((TextView) findViewById(R.id.statusLabel)).setText("Status: connected to: " + fetchIPs().get(0));
                        m_AudioStream.join(m_AudioGroup);
                        Log.d("VOIP","AudioStream joined");
                    } catch (Exception e) {
                        ((TextView) findViewById(R.id.statusLabel)).setText("Couldn't connect");
                        Log.d("VOIP","Exception with associating");
                    }

                }
            });

            findViewById(R.id.DisconnectButton).setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    m_AudioStream.release();
                }
            });

        } catch (Exception e) {
            Log.e("VOIP", "Exception when setting up the Audiostream!");
            e.printStackTrace();
        }
        findViewById(R.id.fetchButtons).setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {

                Log.d("VOIP","FetchIp Button pressed");
                ArrayList<String> connectedIPs = fetchIPs();
                ((EditText) findViewById(R.id.editText2)).setText(connectedIPs.get(0));

                for(int i = 0; i<connectedIPs.size(); i++){
                    Log.d("VOIP", "connectedIps[" + i + "]: " + connectedIPs.get(i));
                }
            }
        });

    }

    public String getLocalIPAddress() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()) {
                        String ip = Formatter.formatIpAddress(inetAddress.hashCode());
                        Log.d("VOIP", "***** IP="+ ip);
                        return ip;
                    }
                }
            }
        } catch (SocketException ex) {
            Log.e("VOIP", ex.toString());
        }
        return null;
    }

    public ArrayList<String> fetchIPs() {
        BufferedReader bufRead = null;
        ArrayList<String> result = null;

        try {
            result = new ArrayList<String>();
            bufRead = new BufferedReader(new FileReader("/proc/net/arp"));
            String fileLine;
            while ((fileLine = bufRead.readLine()) != null) {


                String[] splitted = fileLine.split(" +");

                if ((splitted != null) && (splitted.length >= 4)) {

                    String mac = splitted[3];
                    if (mac.matches("..:..:..:..:..:..")) {
                        try {
                            String ping = "ping  -c 1 -W 1 " + splitted[0];
                            Runtime run = Runtime.getRuntime();
                            Process pro = run.exec(ping);
                            try {
                                pro.waitFor();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            int exit = pro.exitValue();
                            if (exit == 0) {
                                result.add(splitted[0]);
                            } else {
                                throw new Exception();
                            }
                        } catch (Exception e) {
                            Log.d("MainActivity", "Something went wrong with pinging the adress: " + splitted[0]);
                            Log.d("MainActivity", e.getMessage());
                        }
                    }
                }
            }
        } catch (Exception e) {

        }
            try {
                bufRead.close();
            } catch (Exception e) {

            }



        return result;
    }
}

main_activity.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    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=".MainActivity" >

    <TextView
        android:id="@+id/lblLocalPort"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/localPort" />

    <EditText
        android:id="@+id/editText2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:ems="10"
        android:hint="@string/iPHint"
        android:inputType="phone" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:ems="10"
        android:hint="@string/portHint"
        android:inputType="number" >

        <requestFocus />
    </EditText>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp">

        <Button
            android:id="@+id/connectButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/connect" />

        <Button
            android:id="@+id/DisconnectButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/Disconnect" />

        <Button
            android:id="@+id/fetchButtons"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Fetch IPs" />
    </LinearLayout>

    <TextView
        android:id="@+id/statusLabel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView" />
</LinearLayout>

dimens.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="activity_vertical_margin">8dp</dimen>
<dimen name="activity_horizontal_margin">8dp</dimen>
</resources>
fihdi
  • 145
  • 1
  • 1
  • 12

1 Answers1

1

getLocalIPAddress() should return you the IP address of the Wifi Network Interface.

In the current code , you are return the first IP address of the network interface in your list.

You should check the netInterface.getName() and compare with the wifi interface Name and return the IP address.

Once your IP address is proper you can proceed further.

mail2subhajit
  • 1,106
  • 5
  • 16
  • so the ip address of device1 (the one hosting the hotspot) needs to return something in the form 192.168.xxx.yyy too? Would [this piece of code by @ajma](https://stackoverflow.com/a/15060411/3731391) do the trick? – fihdi Nov 06 '19 at 21:39
  • similar code should do the trick , you are not using the wlan, check the hotspot network interface. you can print all interface first in loop and then check it. – mail2subhajit Nov 07 '19 at 10:47
  • Do both devices run the same code with the exception that, device2 initializes their AudioStream with the address of the wlan network interface (wlan0) while device1 initializes their AudioStream with the address of the hotspot (ap0)? My teacher, who hasn't worked with AudioStream/AudioGroup at all, said that the host and the client need different code. – fihdi Nov 16 '19 at 10:45
  • I am taking about the network interface, both the device should be in same network (192.168.xxx.yyy). For Audio Processing has both the side should have transmit and receive logic implemented. transmit part will have Audio record and receiver should have Audio Playback. – mail2subhajit Nov 18 '19 at 10:41
  • I retrieved the IP addresses of both devices and they are in the same network. Pinging each other works. But do both devices run the same code to have real time communication? I kinda don't want to comment here for every little question, can you reach out to me on Discord (dieomgkatze#7368) or something so we can chat? (it's kinda important that I get this working) – fihdi Nov 19 '19 at 13:57
  • you can accept the current answer and then raise a separate question, with your code details and observation. – mail2subhajit Nov 20 '19 at 08:34
  • I just did, please check it out! I explained in more detail and posted a picture on how I tried to connect the two devices together. I'm sure you can help! – fihdi Nov 22 '19 at 13:53
  • Please share the link of your issue . – mail2subhajit Nov 24 '19 at 12:50