Chromium Code Reviews| Index: examples/android/App.java |
| diff --git a/examples/android/App.java b/examples/android/App.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..cf6e52034e9c33caa9fa57facd00be0be1213ea3 |
| --- /dev/null |
| +++ b/examples/android/App.java |
| @@ -0,0 +1,174 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.examples.android; |
| + |
| +import android.content.Context; |
| +import android.util.Log; |
| + |
| +import org.chromium.mojo.bindings.Interface; |
| +import org.chromium.mojo.bindings.Interface.Proxy; |
| +import org.chromium.mojo.bindings.InterfaceRequest; |
| +import org.chromium.mojo.system.Core; |
| +import org.chromium.mojo.system.MessagePipeHandle; |
| +import org.chromium.mojo.system.MojoException; |
| +import org.chromium.mojo.system.RunLoop; |
| +import org.chromium.mojom.mojo.Application; |
| +import org.chromium.mojom.mojo.ExampleService; |
| +import org.chromium.mojom.mojo.ServiceProvider; |
| +import org.chromium.mojom.mojo.Shell; |
| + |
| +import java.lang.reflect.Field; |
| +import java.lang.reflect.InvocationTargetException; |
| +import java.util.ArrayList; |
| +import java.util.HashMap; |
| +import java.util.List; |
| +import java.util.Map; |
| + |
| +/** |
| + * App holds all the code for this example application. |
| + */ |
| +class App { |
| + private static String sTAG = "AndroidTestApp"; |
|
qsr
2015/02/05 16:50:07
We usually name this just TAG.
etiennej
2015/02/06 16:22:29
Done. We should remove the presubmit error that re
|
| + |
| + public static class ApplicationImpl implements Application { |
| + private Shell mShell; |
| + private List<ServiceProvider> mProviders = new ArrayList<ServiceProvider>(); |
| + |
| + public ApplicationImpl(MessagePipeHandle applicationRequest) { |
| + ApplicationImpl.MANAGER.bind(this, applicationRequest); |
| + } |
| + |
| + @Override |
| + public void initialize(Shell shell, String[] args) { |
| + mShell = shell; |
| + } |
| + |
| + @Override |
| + public void acceptConnection(String requestorUrl, |
| + InterfaceRequest<ServiceProvider> services, ServiceProvider exposedServices) { |
| + ServiceProviderImpl serviceProvider = new ServiceProviderImpl(services); |
| + serviceProvider.addService(ExampleServiceImpl.class); |
| + ServiceProvider.MANAGER.bind(serviceProvider, services); |
| + mProviders.add(serviceProvider); |
|
qsr
2015/02/05 16:50:07
If you are not using exposedServices, you should c
etiennej
2015/02/06 16:22:29
Done.
|
| + }; |
| + |
| + @Override |
| + public void requestQuit() {} |
|
qsr
2015/02/05 16:50:07
This should stop the runloop.
etiennej
2015/02/06 16:22:29
Done.
|
| + |
| + @Override |
| + public void close() {} |
|
qsr
2015/02/05 16:50:07
This should probably close mShell.
etiennej
2015/02/06 16:22:29
Done.
|
| + |
| + @Override |
| + public void onConnectionError(MojoException e) {} |
| + } |
| + |
| + public static class ServiceProviderImpl implements ServiceProvider { |
| + /** |
| + * ServiceFactoryBinder holds the necessary information to bind a service interface to a |
| + * message pipe. |
| + */ |
| + private static class ServiceFactoryBinder { |
| + private final Class<Interface> mServiceClass; |
| + private final Manager<Interface, ? extends Proxy> mManager; |
| + |
| + public ServiceFactoryBinder(Class<Interface> serviceClass) { |
| + mServiceClass = serviceClass; |
| + Field managerField; |
| + try { |
| + managerField = serviceClass.getField("MANAGER"); |
| + } catch (NoSuchFieldException e) { |
| + throw new RuntimeException(e); |
| + } |
| + try { |
| + // localManager is used to limit the scope of |
| + // @SuppressWarnings. |
| + @SuppressWarnings("unchecked") |
| + Manager<Interface, ? extends Proxy> localManager = |
| + (Manager<Interface, ? extends Proxy>) managerField.get(null); |
| + this.mManager = localManager; |
| + } catch (IllegalAccessException e) { |
| + throw new RuntimeException(e); |
| + } |
| + } |
| + |
| + public void bindNewInstanceToMessagePipe(MessagePipeHandle pipe) { |
| + try { |
| + mManager.bind(mServiceClass.getConstructor().newInstance(), pipe); |
|
qsr
2015/02/05 16:50:07
Can you not to use reflection? You can define an
etiennej
2015/02/06 16:22:29
Done.
|
| + } catch (NoSuchMethodException e) { |
| + throw new RuntimeException(e); |
| + } catch (InstantiationException e) { |
| + throw new RuntimeException(e); |
| + } catch (IllegalAccessException e) { |
| + throw new RuntimeException(e); |
| + } catch (InvocationTargetException e) { |
| + throw new RuntimeException(e); |
| + } |
| + } |
| + |
| + public String getInterfaceName() { |
| + return mManager.getName(); |
| + } |
| + } |
| + |
| + private InterfaceRequest<ServiceProvider> mProvider; |
|
qsr
2015/02/05 16:50:07
You do not need to keep this object alive.
etiennej
2015/02/06 16:22:29
Done.
|
| + private Map<String, ServiceFactoryBinder> mNameToServiceMap = |
| + new HashMap<String, ServiceFactoryBinder>(); |
| + |
| + public ServiceProviderImpl(InterfaceRequest<ServiceProvider> provider) { |
| + mProvider = provider; |
| + } |
| + |
| + /** |
| + * AddService adds a new service to the list of services provided by this application. |
| + */ |
| + public void addService(Class serviceImpl) { |
| + @SuppressWarnings("unchecked") |
| + ServiceFactoryBinder binder = new ServiceFactoryBinder(serviceImpl); |
| + mNameToServiceMap.put(binder.getInterfaceName(), binder); |
| + } |
| + |
| + @Override |
| + public void connectToService(String interfaceName, MessagePipeHandle pipe) { |
| + if (mNameToServiceMap.containsKey(interfaceName)) { |
| + mNameToServiceMap.get(interfaceName).bindNewInstanceToMessagePipe(pipe); |
| + } |
|
qsr
2015/02/05 16:50:07
You and to close the pipe if you do not bind it.
etiennej
2015/02/06 16:22:29
Done.
|
| + } |
| + |
| + @Override |
| + public void close() {} |
| + |
| + @Override |
| + public void onConnectionError(MojoException e) {} |
| + } |
| + |
| + public static class ExampleServiceImpl implements ExampleService { |
| + public ExampleServiceImpl() {} |
| + |
| + @Override |
| + public void ping(short pingValue, ExampleService.PingResponse callback) { |
| + callback.call(pingValue); |
| + } |
| + |
| + @Override |
| + public void close() {} |
| + |
| + @Override |
| + public void onConnectionError(MojoException e) {} |
| + } |
| + |
| + public static void mojoMain(Context context, Core core, int applicationRequestHandle) { |
| + Log.i(sTAG, "App.MojoMain called"); |
| + RunLoop runLoop = core.createDefaultRunLoop(); |
| + Log.i(sTAG, "Run loop created"); |
| + |
| + MessagePipeHandle handle = |
| + core.acquireNativeHandle(applicationRequestHandle).toMessagePipeHandle(); |
| + Application application = new ApplicationImpl(handle); |
| + |
| + Log.i(sTAG, "Setup done, starting run loop"); |
| + runLoop.run(); |
| + Log.i(sTAG, "Run loop exited"); |
| + } |
| +} |