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"); |
+ } |
+} |