Android VOIP application without access to internet

OK so if you are looking for some peer-2-peer communications, I think wifi is the way to go (better distance and speeds). If you can develop for only newer versions of Android then WI-FI Direct is the way to go, but that will only work on Android 4.0 and above

In order to have something run on below 4.0 you are going to have to go with a 3rd party library. I know Qualcomm has a library called alljoyn, but not sure how good it is.


actually SIP clients can talk peer-to-peer, they just need to know their IP addresses and UDP ports where they listen to SIP messages.

You can play around with normal SIP clients on two comuters (X-Lite for Windows, Twinkle for Linux, and some others exist too) and try establishing a call between them without server registration. It's quite possible.

Also you can run a minimalistic SIP server somewhere in local LAN. For example, FreeSWITCH can be minimized to a quite tiny footprint.


Of course it is possible! Why you would need the internet? As long as you are both connected to the same network that is fine! Below is the java and xml for a working app.

On start up it will provide you with your own local port, for example "52022".. this is random every time and unfortunately that can't be helped. We then enter the IP address of the other phone and THEIR randomly generated port number and press connect. They do exactly the same and hooray you're connected! This test app obviously requires you to be close by to exchange port numbers, but in my proper app I was easily able to request each port number before connecting. Hope this helps!

public class MainActivity extends Activity {

AudioGroup m_AudioGroup;
AudioStream m_AudioStream;

@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 {   
          AudioManager audio =  (AudioManager) getSystemService(Context.AUDIO_SERVICE); 
          audio.setMode(AudioManager.MODE_IN_COMMUNICATION);
          m_AudioGroup = new AudioGroup();
          m_AudioGroup.setMode(AudioGroup.MODE_NORMAL);
          m_AudioStream = new AudioStream(InetAddress.getByAddress(getLocalIPAddress ()));
          int localPort = m_AudioStream.getLocalPort();
          m_AudioStream.setCodec(AudioCodec.PCMU);
          m_AudioStream.setMode(RtpStream.MODE_NORMAL);

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

          ((Button) findViewById(R.id.button1)).setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                String remoteAddress = ((EditText)findViewById(R.id.editText2)).getText().toString();
                String remotePort = ((EditText)findViewById(R.id.editText1)).getText().toString();

                  try {
                    m_AudioStream.associate(InetAddress.getByName(remoteAddress), Integer.parseInt(remotePort));
                } catch (NumberFormatException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (UnknownHostException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                  m_AudioStream.join(m_AudioGroup);
            }
        });

          ((Button) findViewById(R.id.button2)).setOnClickListener(new OnClickListener() {

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

      } catch (Exception e) {
       Log.e("----------------------", e.toString());
       e.printStackTrace();
      }
}

public static byte[] getLocalIPAddress () {
    byte ip[]=null;
       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()) {
                    ip= inetAddress.getAddress();
                   }
               }
           }
       } catch (SocketException ex) {
           Log.i("SocketException ", ex.toString());
       }
       return ip;
    }
}

Layout file:

<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/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/connect" />

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

EDIT: The IP address method stopped working at API 22, use below code:

private byte[] getLocalIPAddress() {   
    byte[] bytes = null;

    try {
        // get the string ip
        WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
        String ip = Formatter.formatIpAddress(wm.getConnectionInfo().getIpAddress());

        // convert to bytes
        InetAddress inetAddress = null;
        try {
            inetAddress = InetAddress.getByName(ip);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        bytes = new byte[0];
        if (inetAddress != null) {
            bytes = inetAddress.getAddress();
        }

    } catch (Exception e) {
        e.printStackTrace();
        Toast.makeText(this, R.string.phone_voip_incompatible, Toast.LENGTH_SHORT).show();
    }

    return bytes;
}

Tags:

Android

Voip

Sip