Search This Blog

18 February 2012

AIDL Step 5: Upgrading the Service

Let's update our service to handle an additional intent...

First, in the AndroidManifest.xml it should now read:
        <service android:name=".TheServer">
            <intent-filter>
                <action android:name="org.eoti.android.test.apkextensions.api.v1.IServer"/>
                <action android:name="org.eoti.android.test.apkextensions.api.v2.IServer"/>
            </intent-filter>
        </service>

Then, let's update TheServer.java to handle both old and new clients:
package org.eoti.android.test.apkextensions.server;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import org.eoti.android.test.apkextensions.api.v2.IServer;
import org.eoti.android.test.apkextensions.api.v2.Registration;

import java.util.concurrent.ConcurrentHashMap;

public class TheServer extends Service
{
    private static final String TAG = TheServer.class.getSimpleName();
    private ConcurrentHashMap<String, IBinder> binders = new ConcurrentHashMap<String, IBinder>();
    private ConcurrentHashMap<String, Registration> registrations = new ConcurrentHashMap<String, Registration>();

    private IBinder createV2Binder()
    {
        return new IServer.Stub(){
            @Override
            public void register(Registration registration) throws RemoteException {
                if(registration == null) throw new RemoteException(); // API15 required for 'new RemoteException(string)'
                registrations.put(registration.getName(), registration);
                Log.d(TAG, "Registration received:  " + registration.getName() + " v" + registration.getVersion());
            }

            @Override
            public void unregister(String registrationName) throws RemoteException {
                if(registrationName == null)  throw new RemoteException(); // API15 required for 'new RemoteException(string)'
                registrations.remove(registrationName);
                Log.d(TAG, "Registration removed: " + registrationName);            }

            @Override
            public String getServerIdentifier() throws RemoteException {
                return TheServer.class.getName() + "#" + TheServer.this.hashCode();
            }
        };
    }

    private IBinder createV1Binder()
    {
        return new org.eoti.android.test.apkextensions.api.v1.IServer.Stub(){
            @Override
            public void register(org.eoti.android.test.apkextensions.api.v1.Registration registration) throws RemoteException {
                if(registration == null) throw new RemoteException(); // API15 required for 'new RemoteException(string)'
                registrations.put(registration.getName(), new Registration(registration));
                Log.d(TAG, "Registration received from deprecated client:  " + registration.getName());
            }

            @Override
            public void unregister(String registrationName) throws RemoteException {
                if(registrationName == null)  throw new RemoteException(); // API15 required for 'new RemoteException(string)'
                registrations.remove(registrationName);
                Log.d(TAG, "Registration removed from deprecated client: " + registrationName);
            }
        };
    }
  
    public IBinder onBind(Intent intent) {
        if(intent == null) return null;
        String action = intent.getAction();
        if(action == null) return null;
        IBinder binder = binders.get(action);
        if(binder != null)
            return binder;
      
        if(org.eoti.android.test.apkextensions.api.v1.IServer.class.getName().equals(action))
            binder = createV1Binder();

        if(IServer.class.getName().equals(action))
            binder = createV2Binder();

        if(binder != null)
            binders.put(action, binder);
      
        return binder;
    }

    @Override
    public void onDestroy() {
        registrations.clear();
        super.onDestroy();
    }
}


Make sure it all compiles...
malachi@onyx:~/work/apkextensions$ cd TheServer/
malachi@onyx:~/work/apkextensions/TheServer$ mvn clean install


And make sure the now deprecated client can still connect:
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=605 uid=10045 gids={1015}
E/Client1 (  546): Server bound
I/ActivityManager(   61): Displayed org.eoti.android.test.apkextensions.client1/.Client1Activity: +671ms
D/Client1 (  546): Server connected
D/TheServer(  605): 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(  605): Registration removed from deprecated client: org.eoti.android.test.apkextensions.client1.Client1Activity
E/Client1 (  546): Server unbound


Next up, AIDL Step 6: Creating an updated client

No comments:

Post a Comment