|
@@ -16,183 +16,72 @@
|
|
|
|
|
|
package org.ros.android;
|
|
|
|
|
|
-import com.google.common.base.Preconditions;
|
|
|
-
|
|
|
import android.app.Activity;
|
|
|
-import android.content.ComponentName;
|
|
|
import android.content.Intent;
|
|
|
-import android.content.ServiceConnection;
|
|
|
-import android.os.AsyncTask;
|
|
|
-import android.os.IBinder;
|
|
|
-import org.ros.address.InetAddressFactory;
|
|
|
-import org.ros.exception.RosRuntimeException;
|
|
|
-import org.ros.node.NodeMain;
|
|
|
+
|
|
|
import org.ros.node.NodeMainExecutor;
|
|
|
|
|
|
-import java.net.NetworkInterface;
|
|
|
-import java.net.SocketException;
|
|
|
import java.net.URI;
|
|
|
-import java.net.URISyntaxException;
|
|
|
-import java.util.concurrent.ExecutionException;
|
|
|
|
|
|
/**
|
|
|
* @author damonkohler@google.com (Damon Kohler)
|
|
|
*/
|
|
|
public abstract class RosActivity extends Activity {
|
|
|
|
|
|
- private static final int MASTER_CHOOSER_REQUEST_CODE = 0;
|
|
|
-
|
|
|
- private final ServiceConnection nodeMainExecutorServiceConnection;
|
|
|
- private final String notificationTicker;
|
|
|
- private final String notificationTitle;
|
|
|
+ private final RosActivityComponent rosActivityComponent;
|
|
|
|
|
|
protected NodeMainExecutorService nodeMainExecutorService;
|
|
|
|
|
|
- private final class NodeMainExecutorServiceConnection implements ServiceConnection {
|
|
|
+ private class RosActivityEventsHandler implements RosActivityComponent.RosActivityEvents {
|
|
|
@Override
|
|
|
- public void onServiceConnected(ComponentName name, IBinder binder) {
|
|
|
- nodeMainExecutorService = ((NodeMainExecutorService.LocalBinder) binder).getService();
|
|
|
- nodeMainExecutorService.addListener(new NodeMainExecutorServiceListener() {
|
|
|
- @Override
|
|
|
- public void onShutdown(NodeMainExecutorService nodeMainExecutorService) {
|
|
|
- // We may have added multiple shutdown listeners and we only want to
|
|
|
- // call finish() once.
|
|
|
- if (!RosActivity.this.isFinishing()) {
|
|
|
- RosActivity.this.finish();
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- if (getMasterUri() == null) {
|
|
|
- startMasterChooser();
|
|
|
- } else {
|
|
|
- init();
|
|
|
- }
|
|
|
+ public void initialize(final NodeMainExecutor nodeMainExecutor) {
|
|
|
+ init(nodeMainExecutor);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void onServiceDisconnected(ComponentName name) {
|
|
|
+ public void onNodeMainExecutorServiceConnected(final NodeMainExecutorService
|
|
|
+ nodeMainExecutorService) {
|
|
|
+ RosActivity.this.nodeMainExecutorService = nodeMainExecutorService;
|
|
|
}
|
|
|
- };
|
|
|
|
|
|
- protected RosActivity(String notificationTicker, String notificationTitle) {
|
|
|
- super();
|
|
|
- this.notificationTicker = notificationTicker;
|
|
|
- this.notificationTitle = notificationTitle;
|
|
|
- nodeMainExecutorServiceConnection = new NodeMainExecutorServiceConnection();
|
|
|
+ @Override
|
|
|
+ public void onNodeMainExecutorServiceDisconnected() {
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- protected void onStart() {
|
|
|
- super.onStart();
|
|
|
- bindNodeMainExecutorService();
|
|
|
+ public RosActivity(String notificationTicker, String notificationTitle) {
|
|
|
+ rosActivityComponent = new RosActivityComponent(this, notificationTicker, notificationTitle,
|
|
|
+ new RosActivityEventsHandler());
|
|
|
}
|
|
|
|
|
|
- private void bindNodeMainExecutorService() {
|
|
|
- Intent intent = new Intent(this, NodeMainExecutorService.class);
|
|
|
- intent.setAction(NodeMainExecutorService.ACTION_START);
|
|
|
- intent.putExtra(NodeMainExecutorService.EXTRA_NOTIFICATION_TICKER, notificationTicker);
|
|
|
- intent.putExtra(NodeMainExecutorService.EXTRA_NOTIFICATION_TITLE, notificationTitle);
|
|
|
- startService(intent);
|
|
|
- Preconditions.checkState(
|
|
|
- bindService(intent, nodeMainExecutorServiceConnection, BIND_AUTO_CREATE),
|
|
|
- "Failed to bind NodeMainExecutorService.");
|
|
|
+ public void startMasterChooser() {
|
|
|
+ rosActivityComponent.startMasterChooser();
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- protected void onDestroy() {
|
|
|
- unbindService(nodeMainExecutorServiceConnection);
|
|
|
- super.onDestroy();
|
|
|
+ public URI getMasterUri() {
|
|
|
+ return rosActivityComponent.getMasterUri();
|
|
|
}
|
|
|
|
|
|
- private void init() {
|
|
|
- // Run init() in a new thread as a convenience since it often requires
|
|
|
- // network access.
|
|
|
- new AsyncTask<Void, Void, Void>() {
|
|
|
- @Override
|
|
|
- protected Void doInBackground(Void... params) {
|
|
|
- RosActivity.this.init(nodeMainExecutorService);
|
|
|
- return null;
|
|
|
- }
|
|
|
- }.execute();
|
|
|
+ public String getRosHostname() {
|
|
|
+ return rosActivityComponent.getRosHostname();
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * This method is called in a background thread once this {@link Activity} has
|
|
|
- * been initialized with a master {@link URI} via the {@link MasterChooser}
|
|
|
- * and a {@link NodeMainExecutorService} has started. Your {@link NodeMain}s
|
|
|
- * should be started here using the provided {@link NodeMainExecutor}.
|
|
|
- *
|
|
|
- * @param nodeMainExecutor
|
|
|
- * the {@link NodeMainExecutor} created for this {@link Activity}
|
|
|
- */
|
|
|
protected abstract void init(NodeMainExecutor nodeMainExecutor);
|
|
|
|
|
|
- public void startMasterChooser() {
|
|
|
- Preconditions.checkState(getMasterUri() == null);
|
|
|
- // Call this method on super to avoid triggering our precondition in the
|
|
|
- // overridden startActivityForResult().
|
|
|
- super.startActivityForResult(new Intent(this, MasterChooser.class), 0);
|
|
|
- }
|
|
|
-
|
|
|
- public URI getMasterUri() {
|
|
|
- Preconditions.checkNotNull(nodeMainExecutorService);
|
|
|
- return nodeMainExecutorService.getMasterUri();
|
|
|
- }
|
|
|
-
|
|
|
- public String getRosHostname() {
|
|
|
- Preconditions.checkNotNull(nodeMainExecutorService);
|
|
|
- return nodeMainExecutorService.getRosHostname();
|
|
|
+ @Override
|
|
|
+ protected void onStart() {
|
|
|
+ super.onStart();
|
|
|
+ rosActivityComponent.onStart();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void startActivityForResult(Intent intent, int requestCode) {
|
|
|
- Preconditions.checkArgument(requestCode != MASTER_CHOOSER_REQUEST_CODE);
|
|
|
- super.startActivityForResult(intent, requestCode);
|
|
|
+ protected void onDestroy() {
|
|
|
+ rosActivityComponent.onDestroy();
|
|
|
+ super.onDestroy();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
|
- super.onActivityResult(requestCode, resultCode, data);
|
|
|
- if (resultCode == RESULT_OK) {
|
|
|
- if (requestCode == MASTER_CHOOSER_REQUEST_CODE) {
|
|
|
- String host;
|
|
|
- String networkInterfaceName = data.getStringExtra("ROS_MASTER_NETWORK_INTERFACE");
|
|
|
- // Handles the default selection and prevents possible errors
|
|
|
- if (networkInterfaceName == null || networkInterfaceName.equals("")) {
|
|
|
- host = InetAddressFactory.newNonLoopback().getHostAddress();
|
|
|
- } else {
|
|
|
- try {
|
|
|
- NetworkInterface networkInterface = NetworkInterface.getByName(networkInterfaceName);
|
|
|
- host = InetAddressFactory.newNonLoopbackForNetworkInterface(networkInterface).getHostAddress();
|
|
|
- } catch (SocketException e) {
|
|
|
- throw new RosRuntimeException(e);
|
|
|
- }
|
|
|
- }
|
|
|
- nodeMainExecutorService.setRosHostname(host);
|
|
|
- if (data.getBooleanExtra("ROS_MASTER_CREATE_NEW", false)) {
|
|
|
- nodeMainExecutorService.startMaster(data.getBooleanExtra("ROS_MASTER_PRIVATE", true));
|
|
|
- } else {
|
|
|
- URI uri;
|
|
|
- try {
|
|
|
- uri = new URI(data.getStringExtra("ROS_MASTER_URI"));
|
|
|
- } catch (URISyntaxException e) {
|
|
|
- throw new RosRuntimeException(e);
|
|
|
- }
|
|
|
- nodeMainExecutorService.setMasterUri(uri);
|
|
|
- }
|
|
|
- // Run init() in a new thread as a convenience since it often requires network access.
|
|
|
- new AsyncTask<Void, Void, Void>() {
|
|
|
- @Override
|
|
|
- protected Void doInBackground(Void... params) {
|
|
|
- RosActivity.this.init(nodeMainExecutorService);
|
|
|
- return null;
|
|
|
- }
|
|
|
- }.execute();
|
|
|
- } else {
|
|
|
- // Without a master URI configured, we are in an unusable state.
|
|
|
- nodeMainExecutorService.forceShutdown();
|
|
|
- }
|
|
|
- }
|
|
|
- super.onActivityResult(requestCode, resultCode, data);
|
|
|
+ rosActivityComponent.onActivityResult(requestCode, resultCode, data);
|
|
|
}
|
|
|
}
|