TomP2P on Android

TomP2P has been tested and used on Anroid in a couple of academic projects. To install Android, please read the Quick Start. For any kind of development it is useful to use logcat for the error messages.

Extra Work

Although, the Android API is very similar to Java 1.5, you need to do some extra work.

Example

The following example code has been tested on Android 4.0.3 with TomP2P 4.0.7 (newer TomP2P versions have a slighly different API). Please note that the current TomP2P does not work with Android 2.3 or 2.2:

public class TestP2P extends Activity {
  final private static Random rnd = new Random(42L);
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
      
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        System.setProperty("java.net.preferIPv6Addresses", "false");
        Peer master = null;
        try
        {
                master = new Peer(new Number160(rnd));
                Bindings bindings=new Bindings();
                bindings.addProtocol(Protocol.IPv4);
                master.listen(4001, 4001, bindings);
                Peer[] nodes = createAndAttachNodes(master, 10);
                bootstrap(master, nodes);
                examplePutGet(nodes);
                exampleAddGet(nodes);
        }
        catch (Throwable e)
        {
          Log.wtf("tomp2p", e);
          e.printStackTrace();
        }
        finally
        {
                master.shutdown();
        }
        
    }
    private static void bootstrap(Peer master, Peer[] nodes)
    {
            List<FutureBootstrap> futures = new ArrayList<FutureBootstrap>();
            for (int i = 1; i < nodes.length; i++)
            {
                    FutureBootstrap tmp = nodes[i].bootstrap(master.getPeerAddress());
                    futures.add(tmp);
            }
            for (FutureBootstrap future : futures)
                    future.awaitUninterruptibly();
    }

    public static void examplePutGet(Peer[] nodes) throws IOException
    {
            Number160 nr = new Number160(rnd);
            String toStore = "hallo";
            Data data = new Data(toStore.getBytes());
            FutureDHT futureDHT = nodes[3].put(nr, data);
            futureDHT.awaitUninterruptibly();
            System.out.println("stored: " + toStore + " (" + futureDHT.isSuccess() + ")");
            futureDHT = nodes[7].get(nr);
            futureDHT.awaitUninterruptibly();
            //there are easier ways to get it, but this is for demonstration
            Data d1=futureDHT.getRawData().values().iterator().next().values().iterator().next();
            System.out.println("got: "
                            + new String(d1.getData(),d1.getOffset(),d1.getLength()) + " (" + futureDHT.isSuccess() + ")");
    }

    private static void exampleAddGet(Peer[] nodes) throws IOException
    {
            Number160 nr = new Number160(rnd);
            String toStore1 = "hallo1";
            String toStore2 = "hallo2";
            Data data1 = new Data(toStore1.getBytes());
            Data data2 = new Data(toStore2.getBytes());
            FutureDHT futureDHT = nodes[3].add(nr, data1);
            futureDHT.awaitUninterruptibly();
            System.out.println("added: " + toStore1 + " (" + futureDHT.isSuccess() + ")");
            futureDHT = nodes[5].add(nr, data2);
            futureDHT.awaitUninterruptibly();
            System.out.println("added: " + toStore2 + " (" + futureDHT.isSuccess() + ")");
            futureDHT = nodes[7].getAll(nr);
            futureDHT.awaitUninterruptibly();
            System.out.println("size " + futureDHT.getData().size());
            Iterator<Data> iterator = futureDHT.getData().values().iterator();
            Data d1=iterator.next();
            Data d2=iterator.next();
            System.out.println("got: " + new String(d1.getData(),d1.getOffset(),d1.getLength()) + " ("
                            + futureDHT.isSuccess() + ")");
            System.out.println("got: " + new String(d2.getData(),d2.getOffset(),d2.getLength()) + " ("
                            + futureDHT.isSuccess() + ")");
    }

    private static Peer[] createAndAttachNodes(Peer master, int nr) throws Exception
    {
            Peer[] nodes = new Peer[nr];
            nodes[0] = master;
            for (int i = 1; i < nr; i++)
            {
                    nodes[i] = new Peer(new Number160(rnd));
                    nodes[i].listen(master);
            }
            return nodes;
    }
}

The output of this example is for examplePutGet

stored: hallo (true)
got: hallo (true)

and for exampleAddGet

added: hallo2 (true)
size 2
got: hallo2 (true)
got: hallo1 (true)

The Eclispe workspace for TomP2P_Android is available for download: TomP2P-4.0.7_Android.zip (works with Android 4.0.3). An older version (works with Android 2.3) can be found here TomP2P-3.2.9_Android.zip.

Running and Connecting TomP2P on Two Emulators

To connect two TomP2P_Android applications and make them talk to each other, one has to setup port redirecting in Android. I’m not sure if this is needed, but I created two Android Virtual Devices (AVD): TomP2P-15 and TomP2P-15-1. Before setting up the port redirection, both AVD needs to be running (your-path-to-android-sdk/tools/emulator -avd TomP2P-15 and your-path-to-android-sdk/tools/emulator -avd TomP2P-15-1). The port redirection is set up by connecting to the device (telnet localhost 5554 and telnet localhost 5556) and run the commands redir add udp:5001:4001 and redir add tcp:5001:4001 for the emulator on port 5554 and redir add udp:6001:4001 / redir add tcp:6001:4001 for the emulator listening on port 5556. Now with the test application TestP2P, you should be able to connect from one emulator to the other by using the IP 10.0.2.2. The screenshot shows how the input (GUI) and output (console) should look like.

There is also a thread @stackoverflow.

Newest Versions of TomP2P on Android

The newest versions of TomP2P use logback, which could cause problems on Android. If you see an error such as:

Error:[TomP2P_Android] EXCEPTION FROM SIMULATION:
Error:[TomP2P_Android] local variable type mismatch: attempt to set or access a value of type java.lang.Object using a local variable of type java.lang.Object[]. This is symptomatic of .class transformation tools that ignore local variable information.
Error:[TomP2P_Android] ...at bytecode offset 000000c7
Error:[TomP2P_Android] locals[0000]: Lch/qos/logback/classic/gaffer/ComponentDelegate;

Then you should try the following library instead