Rather than repeating all the previous tutorials, let's just alter the v2 API. Note: In the real world, you should never do that as you need to remain backward compatible. Since I know no one else is using the api, we'll cheat.
First, let's create API/src/main/java/org/eoti/android/test/apkextensions/api/v2/IServerCallback.aidl:
package org.eoti.android.test.apkextensions.api.v2;
oneway interface IServerCallback {
void message(String text);
}
And update our IServer.aidl:
package org.eoti.android.test.apkextensions.api.v2;
import org.eoti.android.test.apkextensions.api.v2.Registration;
import org.eoti.android.test.apkextensions.api.v2.IServerCallback;
interface IServer
{
void register(inout Registration registration, IServerCallback cb);
void unregister(in String registrationName, IServerCallback cb);
String getServerIdentifier();
}
Recompile our API
malachi@onyx:~/work/apkextensions/API$ mvn clean install
Next, we update our server. Replace createV2Binder() with:
final RemoteCallbackList<IServerCallback> callbacks = new RemoteCallbackList<IServerCallback>();
protected void broadcast(String message)
{
final int N = callbacks.beginBroadcast();
for(int i=0; i<N; i++)
{
try {
callbacks.getBroadcastItem(i).message(message);
} catch (RemoteException e) {
// RemoteCallbackList will take care of removing dead objects
}
}
callbacks.finishBroadcast();
}
private IBinder createV2Binder()
{
return new IServer.Stub(){
@Override
public void register(Registration registration, IServerCallback cb) throws RemoteException {
if(registration == null) throw new RemoteException(); // API15 required for 'new RemoteException(string)'
registrations.put(registration.getName(), registration);
if(cb != null)
{
callbacks.register(cb);
cb.message("Registration successful");
}
Log.d(TAG, "Registration received: " + registration.getName() + " v" + registration.getVersion());
broadcast(registration.getName() + " has entered the room");
}
@Override
public void unregister(String registrationName, IServerCallback cb) throws RemoteException {
if(registrationName == null) throw new RemoteException(); // API15 required for 'new RemoteException(string)'
registrations.remove(registrationName);
if(cb != null)
{
cb.message("Unregistration successful");
callbacks.unregister(cb);
}
Log.d(TAG, "Registration removed: " + registrationName);
broadcast(registrationName + " has left the room");
}
@Override
public String getServerIdentifier() throws RemoteException {
return TheServer.class.getName() + "#" + TheServer.this.hashCode();
}
};
}
And compile it
malachi@onyx:~/work/apkextensions/TheServer$ mvn clean install
Next, we'll update our v2 client...
In our Client2/src/main/java/org/eoti/android/test/apkextensions/client2/Client2Activity.java, add:
private IServerCallback callback = new IServerCallback.Stub() {
@Override
public void message(String text) throws RemoteException {
Log.d(TAG, "Message received: " + text);
}
};
change:
server.register(registration);to:
server.register(registration, callback);
and change:
server.unregister(REG_NAME);to:
server.unregister(REG_NAME, callback);
Rebuild it
malachi@onyx:~/work/apkextensions/Client2$ mvn clean install
Run Client1:
I/ActivityManager( 61): Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=org.eoti.android.test.apkextensions.client1/.Client1Activity } from pid 127
I/ActivityManager( 61): Start proc org.eoti.android.test.apkextensions.server for service org.eoti.android.test.apkextensions.server/.TheServer: pid=846 uid=10045 gids={1015}
E/Client1 ( 546): Server bound
I/ActivityManager( 61): Displayed org.eoti.android.test.apkextensions.client1/.Client1Activity: +726ms
D/Client1 ( 546): Server connected
D/TheServer( 846): Registration received from deprecated client: org.eoti.android.test.apkextensions.client1.Client1Activity
D/Client1 ( 546): Registered org.eoti.android.test.apkextensions.client1.Client1Activity
D/Client1 ( 546): Running tests...
D/Client1 ( 546): Tests done...
D/TheServer( 846): Registration removed from deprecated client: org.eoti.android.test.apkextensions.client1.Client1Activity
E/Client1 ( 546): Server unbound
Run Client2:
W/KeyCharacterMap( 546): No keyboard for id 0
W/KeyCharacterMap( 546): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
I/ActivityManager( 61): Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=org.eoti.android.test.apkextensions.client2/.Client2Activity } from pid 127
I/ActivityManager( 61): Start proc org.eoti.android.test.apkextensions.client2 for activity org.eoti.android.test.apkextensions.client2/.Client2Activity: pid=856 uid=10047 gids={1015}
E/Client2 ( 856): Server bound
D/Client2 ( 856): Server connected: org.eoti.android.test.apkextensions.server.TheServer#1079096160
D/Client2 ( 856): Message received: Registration successful
D/TheServer( 846): Registration received: org.eoti.android.test.apkextensions.client2.Client2Activity v1.0alpha
D/Client2 ( 856): Message received: org.eoti.android.test.apkextensions.client2.Client2Activity has entered the room
D/Client2 ( 856): Registered org.eoti.android.test.apkextensions.client2.Client2Activity
D/Client2 ( 856): Running tests...
D/Client2 ( 856): Tests done...
D/TheServer( 846): Registration removed: org.eoti.android.test.apkextensions.client2.Client2Activity
D/Client2 ( 856): Message received: Unregistration successful
E/Client2 ( 856): Server unbound
I/ActivityManager( 61): Displayed org.eoti.android.test.apkextensions.client2/.Client2Activity: +931ms
This all looks good -- but why didn't Client1 announce when Client2 entered the room?
It's because Client1 is still using the old deprecated API.