The client-side software of MANES (the MANES client) functions as a virtual interface on each host device. On Android,
ManesService,
		  responsible for communicating with the MANES server
		  and collecting and reporting the data used for
		  topology estimation.
		ManesService
		through ManesInterface.
		  ManesInterface.send(byte[]
		      data) broadcasts a packet to all
		      one-hop neighbors.
		  ManesInterface.receive(long
		      timeout) returns a new broadcast
		      packet, if one arrives before the specified
		      timeout.
		Email questions to the MANES listserv, manes-users@umich.edu. To subscribe to the listserv, send an email with the subject "SUBSCRIBE" to manes-users-requests@umich.edu.
MANES requires (via its dependence on C2DM):
		  ManesService,
		  provided by
		  the ManesClient
		    application, must be installed on any device that
		  runs an application using MANES.  It functions as a
		  virtual interface on the host device, sending and
		  receiving packets over MANES.
		
Currently ManesClient is provided as an unsigned .apk file. To install it on your device, please first enable installing unsigned packets by clicking on settings->applications->unknown sources. Then open an adb shell and simply type "adb install MANESClient-current.apk".
		Note: The following instructions assume some familarity with Android application development in the Eclipse IDE.
 Add maneslib.jar to your
	      classpath.  It
	      provides ManesInterface,
	      the interface for sending and receiving packets with
	      MANES.
	    
	      Specify ManesService
	      in
	      the AndroidManifest.xml.
	    
<application>
<service
    android:enabled="true"
    android:name="org.whispercomm.manes.client.macentity.network.ManesService"
    android:exported="true"
    android:process=":remote" />
</application>
 
	  ManesInterface
	  object:
	      Construct a new ManesInterface using
	      the ManesInterface(int
	      appId, Context context) constructor.
	    
appId
		  is
		  a unique
		  identifier consistent across all instances of
		  the application.  As with
		  an Ethernet
		  protocol number or
		  
		    IP protocol number, it is used to identify to
		  which handler (or application, in our case) incoming
		  packets should be
		  delivered.  ManesInteface.receive()
		  will only receive incoming packets that were sent
		  with the same appId.
		
Like IANA does for Ethernet and IP, we maintain a registry of registered applications ids for MANES. To register an id, please send an email to drbild@umich.edu.
context
		  is the
		  Android Context
		  of your application. For a single-activity application,
		  the context is just the
		  Activity.
		
		  During
		  construction, ManesInterface
		  binds the provided context
		  to ManesService. Construction
		  fails if
		  the MANESClient
		  application that
		  provides ManesService
		  is not installed.
		
import org.whispercomm.manes.client.ManesInterface;
public class MyActivity extends Activity {
    
    private static final int APP_ID = 1234;
    private ManesInterface manes;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        try {
            manes = new ManesInterface(APP_ID, this);
        } catch (RemoteException e) {
            // Handle the failure in a way appropriate for the application.
        }
    }
}
	  
	      Broadcast data to one-hop neighbors using
	      ManesInterface.send(byte[]
		  data).
	    
Note that a send may silently fail at any point between the sender and each potential receiver. As with a real wireless ad hoc system, MANES does not guarantee reliable delivery. If needed, reliable transport must be built on top of MANES, like TCP is built on top of IP.
	      send()
	      will signal some local configuration errors, e.g.,
	      failing to communicate
	      with ManesService,
	      by throwing
	      an IOException.
	      
	    
byte[] data = new byte[]{1,2,3,4,5,6,7,8,9,10};
try {
    manes.send(data);
} catch (IOException e) {
    // Handle the failure in a way appropriate for the application.
}
	  
	      Listen for incoming packets
	      using ManesInterface.receive(int
		  timeout).
	    
	      timeout species the maximum number of
	      milliseconds
	      that receive()
	      should block while waiting for a new packet.  It will
	      return null after timeout
	      milliseconds if no new packet was received.
	    
	      receive()
	      is a blocking call and thus should be called from a
	      separate thread, not the main application thread. See
	      the Hello World example
	      application.
	    
int timeout = 10;
try {
    byte[] received = manes.receive(timeout);
    if (received != null) {
        // Process the packet.
    } else {
        // timeout was reached before a new packet arrived.
    }
} catch (IOException e) {
    // Handle the failure in a way appropriate for the application.
}
	  
	      Before exiting, applications must close
	      the ManesInterface
	      by
	      calling ManesInterfece.unregister().
	      This call unregisters the interface
	      from ManesService.
	    
manes.unregister();
The following sample application broadcasts the message "Hello, World" to all one-hop neighbors (as estimated by the MANES infrastructure) and displays all incoming "Hello, World" messages. Download the full application source as an Eclipse project or install the compiled package by scanning the QR code.
	      package org.whispercomm.manes.apps.helloworld; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.Runnable; import android.app.Activity; import android.os.Bundle; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Toast; import org.whispercomm.manes.client.maclib.ManesInterface; /** * A Hello World sample application for MANES. ** This application broadcasts and receives simple "Hello, World!" messages. */ public class ManesHelloWorld extends Activity implements Runnable { private static final String TAG = "ManesHelloWorld"; private static final int APP_ID = 253; // 253 is available for // experimentation private ManesInterface manes; private Thread receiveThread; private volatile boolean isRunning; /** * Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout layout = new LinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); setContentView(layout); // Add button to screen for sending messages Button button = new Button(this); button.setText("Send \"Hello, World!\""); layout.addView(button); // Configure button to send message when clicked button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { ManesHelloWorld.this.sendMessage(); } }); // Register with MANES try { manes = new ManesInterface(APP_ID, this); } catch (RemoteException e) { this.finish(); return; } // Start receive thread receiveThread = new Thread(this); isRunning = true; receiveThread.start(); } /** * Called when the activity is exiting. */ @Override protected void onDestroy() { isRunning = false; // Stop receive thread; if (receiveThread != null) receiveThread.interrupt(); if (manes != null) manes.unregister(); } /** * Broadcasts a message to all one-hop neighbors. */ public void sendMessage() { try { byte[] data = "Hello, World!".getBytes("UTF-8"); manes.send(data); } catch (UnsupportedEncodingException e) { Log.e(TAG, "Failed to encode message. Unsupported charset.", e); } catch (IOException e) { Log.e(TAG, "Error while sending message.", e); } } /** * Receives and displays incoming messages. */ @Override public void run() { while (isRunning) { byte[] data = null; try { data = manes.receive(500); } catch (IOException e1) { Log.e(TAG, e1.getMessage()); continue; } // Timeout after 500 ms, returning null. if (null != data) { // Debug Log.v(TAG, "Received a new packet!"); try { final String msg = new String(data, "UTF-8"); Log.v(TAG, "Received a packet: " + msg); this.runOnUiThread(new Runnable() { @Override public void run() { Log.v(TAG, "Calling Toast.makeText()."); Toast.makeText(getApplicationContext(), String.format("Received: %s", msg), Toast.LENGTH_SHORT).show(); } }); } catch (UnsupportedEncodingException e) { Log.e(TAG, "Could not decode message. Unsupported charset.", e); } catch (RuntimeException e) { Log.e(TAG, "Failed to decode message.", e); } } } } }
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.whispercomm.manes.apps.helloworld"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="8" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".ManesHelloWorld"
            android:label="@string/app_name" 
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <service
		android:enabled="true"
		android:name="org.whispercomm.manes.client.macentity.network.ManesService"
		android:exported="true"
		android:process=":remote"/>
    </application>
</manifest>