Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 package com.github.rosjava.android_remocons.common_tools.apps;
00019
00020 import android.app.AlertDialog;
00021 import android.content.DialogInterface;
00022 import android.content.Intent;
00023 import android.os.AsyncTask;
00024 import android.os.Bundle;
00025 import android.util.Log;
00026 import android.view.Window;
00027 import android.view.WindowManager;
00028 import android.widget.LinearLayout;
00029
00030 import com.github.robotics_in_concert.rocon_rosjava_core.rocon_interactions.InteractionMode;
00031 import com.github.rosjava.android_remocons.common_tools.dashboards.Dashboard;
00032 import com.github.rosjava.android_remocons.common_tools.master.MasterDescription;
00033 import com.github.rosjava.android_remocons.common_tools.rocon.Constants;
00034
00035 import org.ros.address.InetAddressFactory;
00036 import org.ros.android.RosActivity;
00037 import org.ros.exception.RosRuntimeException;
00038 import org.ros.namespace.NameResolver;
00039 import org.ros.node.NodeConfiguration;
00040 import org.ros.node.NodeMainExecutor;
00041 import org.yaml.snakeyaml.Yaml;
00042
00043 import java.io.Serializable;
00044 import java.net.URI;
00045 import java.net.URISyntaxException;
00046 import java.util.LinkedHashMap;
00047
00055 public abstract class RosAppActivity extends RosActivity {
00056
00057
00058
00059
00060
00061
00062 private InteractionMode appMode = InteractionMode.STANDALONE;
00063 private String masterAppName = null;
00064 private String defaultMasterAppName = null;
00065 private String defaultMasterName = "";
00066 private String androidApplicationName;
00067 private String remoconActivity = null;
00068
00069 private Serializable remoconExtraData = null;
00070
00071 private int dashboardResourceId = 0;
00072 private int mainWindowId = 0;
00073 private Dashboard dashboard = null;
00074 private NodeConfiguration nodeConfiguration;
00075 private NodeMainExecutor nodeMainExecutor;
00076 protected MasterNameResolver masterNameResolver;
00077 protected MasterDescription masterDescription;
00078
00079
00080 protected AppParameters params = new AppParameters();
00081 protected AppRemappings remaps = new AppRemappings();
00082
00083 protected void setDashboardResource(int resource) {
00084 dashboardResourceId = resource;
00085 }
00086
00087 protected void setMainWindowResource(int resource) {
00088 mainWindowId = resource;
00089 }
00090
00091 protected void setDefaultMasterName(String name) {
00092 defaultMasterName = name;
00093 }
00094
00095 protected void setDefaultAppName(String name) {
00096 defaultMasterAppName = name;
00097 }
00098
00099 protected void setCustomDashboardPath(String path) {
00100 dashboard.setCustomDashboardPath(path);
00101 }
00102
00103 protected RosAppActivity(String notificationTicker, String notificationTitle) {
00104 super(notificationTicker, notificationTitle);
00105 this.androidApplicationName = notificationTitle;
00106 }
00107
00108 @Override
00109 public void onCreate(Bundle savedInstanceState) {
00110 super.onCreate(savedInstanceState);
00111
00112 if (mainWindowId == 0) {
00113 Log.e("RosApp",
00114 "You must set the dashboard resource ID in your RosAppActivity");
00115 return;
00116 }
00117 if (dashboardResourceId == 0) {
00118 Log.e("RosApp",
00119 "You must set the dashboard resource ID in your RosAppActivity");
00120 return;
00121 }
00122
00123 requestWindowFeature(Window.FEATURE_NO_TITLE);
00124 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
00125 WindowManager.LayoutParams.FLAG_FULLSCREEN);
00126 setContentView(mainWindowId);
00127
00128 masterNameResolver = new MasterNameResolver();
00129
00130 if (defaultMasterName != null) {
00131 masterNameResolver.setMasterName(defaultMasterName);
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00153
00154
00155
00156
00157 for (InteractionMode mode : InteractionMode.values()) {
00158
00159 masterAppName = getIntent().getStringExtra(Constants.ACTIVITY_SWITCHER_ID + "." + mode + "_app_name");
00160 if (masterAppName != null) {
00161 appMode = mode;
00162 break;
00163 }
00164 }
00165
00166 if (masterAppName == null) {
00167
00168 Log.e("RosApp", "We are running as standalone :(");
00169 masterAppName = defaultMasterAppName;
00170 appMode = InteractionMode.STANDALONE;
00171 }
00172 else
00173 {
00174
00175
00176
00177
00178 Yaml yaml = new Yaml();
00179
00180 String paramsStr = getIntent().getStringExtra("Parameters");
00181 String remapsStr = getIntent().getStringExtra("Remappings");
00182
00183 Log.d("RosApp", "Parameters: " + paramsStr);
00184 Log.d("RosApp", "Remappings: " + remapsStr);
00185
00186 try {
00187 if ((paramsStr != null) && (! paramsStr.isEmpty())) {
00188 LinkedHashMap<String, Object> paramsList = (LinkedHashMap<String, Object>)yaml.load(paramsStr);
00189 if (paramsList != null) {
00190 params.putAll(paramsList);
00191 Log.d("RosApp", "Parameters: " + paramsStr);
00192 }
00193 }
00194 } catch (ClassCastException e) {
00195 Log.e("RosApp", "Cannot cast parameters yaml string to a hash map (" + paramsStr + ")");
00196 throw new RosRuntimeException("Cannot cast parameters yaml string to a hash map (" + paramsStr + ")");
00197 }
00198
00199 try {
00200 if ((remapsStr != null) && (! remapsStr.isEmpty())) {
00201 LinkedHashMap<String, String> remapsList = (LinkedHashMap<String, String>)yaml.load(remapsStr);
00202 if (remapsList != null) {
00203 remaps.putAll(remapsList);
00204 Log.d("RosApp", "Remappings: " + remapsStr);
00205 }
00206 }
00207 } catch (ClassCastException e) {
00208 Log.e("RosApp", "Cannot cast parameters yaml string to a hash map (" + remapsStr + ")");
00209 throw new RosRuntimeException("Cannot cast parameters yaml string to a hash map (" + remapsStr + ")");
00210 }
00211
00212 remoconActivity = getIntent().getStringExtra("RemoconActivity");
00213
00214
00215 if (getIntent().hasExtra(MasterDescription.UNIQUE_KEY)) {
00216
00217
00218 remoconExtraData = getIntent().getSerializableExtra(MasterDescription.UNIQUE_KEY);
00219
00220 try {
00221 masterDescription =
00222 (MasterDescription) getIntent().getSerializableExtra(MasterDescription.UNIQUE_KEY);
00223 } catch (ClassCastException e) {
00224 Log.e("RosApp", "Master description expected on intent on " + appMode + " mode");
00225 throw new RosRuntimeException("Master description expected on intent on " + appMode + " mode");
00226 }
00227 }
00228 else {
00229
00230 Log.e("RosApp", "Master description missing on intent on " + appMode + " mode");
00231 throw new RosRuntimeException("Master description missing on intent on " + appMode + " mode");
00232 }
00233 }
00234
00235 if (dashboard == null) {
00236 dashboard = new Dashboard(this);
00237 dashboard.setView((LinearLayout) findViewById(dashboardResourceId),
00238 new LinearLayout.LayoutParams(
00239 LinearLayout.LayoutParams.WRAP_CONTENT,
00240 LinearLayout.LayoutParams.WRAP_CONTENT));
00241 }
00242 }
00243
00244 @Override
00245 protected void init(NodeMainExecutor nodeMainExecutor) {
00246 this.nodeMainExecutor = nodeMainExecutor;
00247 nodeConfiguration = NodeConfiguration.newPublic(InetAddressFactory
00248 .newNonLoopback().getHostAddress(), getMasterUri());
00249
00250 if (appMode == InteractionMode.STANDALONE) {
00251 dashboard.setRobotName(masterNameResolver.getMasterName());
00252 }
00253 else {
00254 masterNameResolver.setMaster(masterDescription);
00255 dashboard.setRobotName(masterDescription.getMasterName());
00256
00257 if (appMode == InteractionMode.PAIRED) {
00258 dashboard.setRobotName(masterDescription.getMasterType());
00259 }
00260 }
00261
00262
00263 nodeMainExecutor.execute(masterNameResolver, nodeConfiguration.setNodeName("masterNameResolver"));
00264 masterNameResolver.waitForResolver();
00265
00266 nodeMainExecutor.execute(dashboard, nodeConfiguration.setNodeName("dashboard"));
00267 }
00268
00269 protected NameResolver getMasterNameSpace() {
00270 return masterNameResolver.getMasterNameSpace();
00271 }
00272
00273 protected void onAppTerminate() {
00274 RosAppActivity.this.runOnUiThread(new Runnable() {
00275 @Override
00276 public void run() {
00277 new AlertDialog.Builder(RosAppActivity.this)
00278 .setTitle("App Termination")
00279 .setMessage(
00280 "The application has terminated on the server, so the client is exiting.")
00281 .setCancelable(false)
00282 .setNeutralButton("Exit",
00283 new DialogInterface.OnClickListener() {
00284 public void onClick(DialogInterface dialog,
00285 int which) {
00286 RosAppActivity.this.finish();
00287 }
00288 }).create().show();
00289 }
00290 });
00291 }
00292
00293 @Override
00294 public void startMasterChooser() {
00295 if (appMode == InteractionMode.STANDALONE) {
00296 super.startMasterChooser();
00297 } else {
00298 try {
00299 nodeMainExecutorService.setMasterUri(new URI(masterDescription.getMasterUri()));
00300 new AsyncTask<Void, Void, Void>() {
00301 @Override
00302 protected Void doInBackground(Void... params) {
00303 RosAppActivity.this.init(nodeMainExecutorService);
00304 return null;
00305 }
00306 }.execute();
00307 } catch (URISyntaxException e) {
00308
00309 throw new RosRuntimeException(e);
00310 }
00311 }
00312 }
00313
00314 protected void releaseMasterNameResolver() {
00315 nodeMainExecutor.shutdownNodeMain(masterNameResolver);
00316 }
00317
00318 protected void releaseDashboardNode() {
00319 nodeMainExecutor.shutdownNodeMain(dashboard);
00320 }
00321
00332 private boolean managePairedRobotApplication() {
00333 return ((appMode == InteractionMode.STANDALONE) && (masterAppName != null));
00334 }
00335
00336 @Override
00337 protected void onDestroy() {
00338 super.onDestroy();
00339 }
00340
00341 @Override
00342 public void onBackPressed() {
00343 if (appMode != InteractionMode.STANDALONE) {
00344 Log.i("RosApp", "app terminating and returning control to the remocon.");
00345
00346 Intent intent = new Intent();
00347 intent.putExtra(Constants.ACTIVITY_SWITCHER_ID + "." + appMode + "_app_name", "AppChooser");
00348 intent.putExtra(MasterDescription.UNIQUE_KEY, remoconExtraData);
00349 intent.setAction(remoconActivity);
00350 intent.addCategory("android.intent.category.DEFAULT");
00351 startActivity(intent);
00352 finish();
00353 } else {
00354 Log.i("RosApp", "backpress processing for RosAppActivity");
00355 }
00356 super.onBackPressed();
00357 }
00358 }