RobotRemocon.java
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  * Copyright (c) 2011, Willow Garage, Inc.
00005  * Copyright (c) 2013, OSRF.
00006  * All rights reserved.
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  * * Redistributions of source code must retain the above copyright
00012  * notice, this list of conditions and the following disclaimer.
00013  * * Redistributions in binary form must reproduce the above
00014  * copyright notice, this list of conditions and the following
00015  * disclaimer in the documentation and/or other materials provided
00016  * with the distribution.
00017  * * Neither the name of Willow Garage, Inc. nor the names of its
00018  * contributors may be used to endorse or promote products derived
00019  * from this software without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  * POSSIBILITY OF SUCH DAMAGE.
00033  */
00034 
00035 package com.github.rosjava.android_remocons.robot_remocon;
00036 
00037 import java.net.URI;
00038 import java.net.URISyntaxException;
00039 import java.util.ArrayList;
00040 
00041 import android.app.AlertDialog;
00042 import android.app.Dialog;
00043 import android.app.ProgressDialog;
00044 import android.content.DialogInterface;
00045 import android.content.Intent;
00046 import android.net.wifi.WifiManager;
00047 import android.os.AsyncTask;
00048 import android.os.Bundle;
00049 import android.util.Log;
00050 import android.view.Menu;
00051 import android.view.MenuItem;
00052 import android.view.View;
00053 import android.widget.AdapterView;
00054 import android.widget.AdapterView.OnItemClickListener;
00055 import android.widget.Button;
00056 import android.widget.GridView;
00057 import android.widget.TextView;
00058 
00059 import org.ros.address.InetAddressFactory;
00060 import org.ros.android.NodeMainExecutorService;
00061 import org.ros.exception.RemoteException;
00062 import org.ros.exception.RosRuntimeException;
00063 import org.ros.message.MessageListener;
00064 import org.ros.node.NodeConfiguration;
00065 import org.ros.node.NodeMainExecutor;
00066 import org.ros.node.service.ServiceResponseListener;
00067 import com.github.rosjava.android_apps.application_management.AppManager;
00068 import com.github.rosjava.android_apps.application_management.ControlChecker;
00069 import com.github.rosjava.android_apps.application_management.MasterChecker;
00070 import com.github.rosjava.android_apps.application_management.RobotId;
00071 import com.github.rosjava.android_apps.application_management.RobotDescription;
00072 import com.github.rosjava.android_apps.application_management.WifiChecker;
00073 import com.github.rosjava.android_apps.application_management.rapp_manager.InvitationServiceClient;
00074 
00075 import rocon_app_manager_msgs.App;
00076 import rocon_app_manager_msgs.AppList;
00077 import rocon_app_manager_msgs.StartAppResponse;
00078 import rocon_app_manager_msgs.ErrorCodes;
00079 import rocon_app_manager_msgs.StopAppResponse;
00080 
00081 public class RobotRemocon extends RobotActivity {
00082 
00083     /* startActivityForResult Request Codes */
00084         private static final int ROBOT_MASTER_CHOOSER_REQUEST_CODE = 1;
00085 
00086         private static final int MULTI_RAPP_DISABLED = 1;
00087         private static final int CLOSE_EXISTING = 0;
00088 
00089         private TextView robotNameView;
00090         private ArrayList<App> availableAppsCache;
00091         private ArrayList<App> runningAppsCache;
00092         private Button deactivate;
00093         private Button stopAppsButton;
00094         private Button exchangeButton;
00095         private ProgressDialog progress;
00096         private ProgressDialogWrapper progressDialog;
00097         private AlertDialogWrapper wifiDialog;
00098         private AlertDialogWrapper evictDialog;
00099         private AlertDialogWrapper errorDialog;
00100     protected AppManager listAppsSubscriber = null;
00101         private boolean alreadyClicked = false;
00102         private boolean validatedRobot;
00103         private boolean runningNodes = false;
00104         private long availableAppsCacheTime;
00105 
00106         private void stopProgress() {
00107         Log.i("RobotRemocon", "Stopping the spinner");
00108                 final ProgressDialog temp = progress;
00109                 progress = null;
00110                 if (temp != null) {
00111                         runOnUiThread(new Runnable() {
00112                                 public void run() {
00113                                         temp.dismiss();
00114                                 }
00115                         });
00116                 }
00117         }
00118 
00122         private class AlertDialogWrapper {
00123                 private int state;
00124                 private AlertDialog dialog;
00125                 private RobotActivity context;
00126 
00127                 public AlertDialogWrapper(RobotActivity context,
00128                                 AlertDialog.Builder builder, String yesButton, String noButton) {
00129                         state = 0;
00130                         this.context = context;
00131                         dialog = builder
00132                                         .setPositiveButton(yesButton,
00133                                                         new DialogInterface.OnClickListener() {
00134                                                                 public void onClick(DialogInterface dialog,
00135                                                                                 int which) {
00136                                                                         state = 1;
00137                                                                 }
00138                                                         })
00139                                         .setNegativeButton(noButton,
00140                                                         new DialogInterface.OnClickListener() {
00141                                                                 public void onClick(DialogInterface dialog,
00142                                                                                 int which) {
00143                                                                         state = 2;
00144                                                                 }
00145                                                         }).create();
00146                 }
00147 
00148                 public AlertDialogWrapper(RobotActivity context,
00149                                 AlertDialog.Builder builder, String okButton) {
00150                         state = 0;
00151                         this.context = context;
00152                         dialog = builder.setNeutralButton(okButton,
00153                                         new DialogInterface.OnClickListener() {
00154                                                 public void onClick(DialogInterface dialog, int which) {
00155                                                         state = 1;
00156                                                 }
00157                                         }).create();
00158                 }
00159 
00160                 public void setTitle(String m) {
00161                         dialog.setTitle(m);
00162                 }
00163 
00164                 public void setMessage(String m) {
00165                         dialog.setMessage(m);
00166                 }
00167 
00168                 public boolean show(String m) {
00169                         setMessage(m);
00170                         return show();
00171                 }
00172 
00173                 public boolean show() {
00174                         state = 0;
00175                         context.runOnUiThread(new Runnable() {
00176                                 public void run() {
00177                                         dialog.show();
00178                                 }
00179                         });
00180                         // Kind of a hack. Do we know a better way?
00181                         while (state == 0) {
00182                                 try {
00183                                         Thread.sleep(1L);
00184                                 } catch (Exception e) {
00185                                         break;
00186                                 }
00187                         }
00188                         dismiss();
00189                         return state == 1;
00190                 }
00191 
00192                 public void dismiss() {
00193                         if (dialog != null) {
00194                                 dialog.dismiss();
00195                         }
00196                         dialog = null;
00197                 }
00198         }
00199 
00203         private class ProgressDialogWrapper {
00204                 private ProgressDialog progressDialog;
00205                 private RobotActivity activity;
00206 
00207                 public ProgressDialogWrapper(RobotActivity activity) {
00208                         this.activity = activity;
00209                         progressDialog = null;
00210                 }
00211 
00212                 public void dismiss() {
00213                         if (progressDialog != null) {
00214                                 progressDialog.dismiss();
00215                         }
00216                         progressDialog = null;
00217                 }
00218 
00219                 public void show(String title, String text) {
00220                         if (progressDialog != null) {
00221                                 this.dismiss();
00222                         }
00223                         progressDialog = ProgressDialog.show(activity, title, text, true,
00224                                         true);
00225                         progressDialog.setCancelable(false);
00226                         progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
00227                 }
00228         }
00229 
00230         public RobotRemocon() {
00231                 super("RobotRemocon", "RobotRemocon");
00232                 availableAppsCacheTime = 0;
00233                 availableAppsCache = new ArrayList<App>();
00234                 runningAppsCache = new ArrayList<App>();
00235         }
00236 
00238         @Override
00239         public void onCreate(Bundle savedInstanceState) {
00240                 setDashboardResource(R.id.top_bar);
00241                 setMainWindowResource(R.layout.main);
00242                 super.onCreate(savedInstanceState);
00243 
00244                 robotNameView = (TextView) findViewById(R.id.robot_name_view);
00245                 deactivate = (Button) findViewById(R.id.deactivate_robot);
00246                 deactivate.setVisibility(deactivate.GONE);
00247                 stopAppsButton = (Button) findViewById(R.id.stop_applications);
00248                 stopAppsButton.setVisibility(stopAppsButton.GONE);
00249                 exchangeButton = (Button) findViewById(R.id.exchange_button);
00250                 exchangeButton.setVisibility(deactivate.GONE);
00251         }
00252 
00265         @Override
00266         protected void init(NodeMainExecutor nodeMainExecutor) {
00267 
00268                 super.init(nodeMainExecutor);
00269 
00270         // set up a subscriber to the applist topic so it can check
00271         // status of available and running apps.
00272         listAppsSubscriber = new AppManager("", getRobotNameSpaceResolver());
00273         listAppsSubscriber.setAppListSubscriber(new MessageListener<AppList>() {
00274             @Override
00275             public void onNewMessage(AppList message) {
00276                 availableAppsCache = (ArrayList<App>) message.getAvailableApps();
00277                 runningAppsCache = (ArrayList<App>) message.getRunningApps();
00278                 ArrayList<String> runningAppsNames = new ArrayList<String>();
00279                 int i = 0;
00280                 for (i = 0; i < availableAppsCache.size(); i++) {
00281                     App item = availableAppsCache.get(i);
00282                     ArrayList<String> clients = new ArrayList<String>();
00283                     for (int j = 0; j < item.getPairingClients().size(); j++) {
00284                         clients.add(item.getPairingClients().get(j)
00285                                 .getClientType());
00286                     }
00287                     if (!clients.contains("android")
00288                             && item.getPairingClients().size() != 0) {
00289                         availableAppsCache.remove(i);
00290                     }
00291                     if (item.getPairingClients().size() == 0) {
00292                         Log.i("RobotRemocon",
00293                                 "Item name: " + item.getName());
00294                         runningAppsNames.add(item.getName());
00295                     }
00296                 }
00297                 Log.i("RobotRemocon", "AppList Publication: "
00298                         + availableAppsCache.size() + " apps");
00299                 availableAppsCacheTime = System.currentTimeMillis();
00300                 runOnUiThread(new Runnable() {
00301                     @Override
00302                     public void run() {
00303                         updateAppList(availableAppsCache,
00304                                 runningAppsCache);
00305                     }
00306                 });
00307             }
00308         });
00309         listAppsSubscriber.setFunction("list_apps");
00310         nodeMainExecutor.execute(listAppsSubscriber,
00311                 nodeConfiguration.setNodeName("list_apps_subscriber_node"));
00312     }
00313 
00327     void init(Intent intent) {
00328         URI uri;
00329         try {
00330             robotDescription = (RobotDescription) intent
00331                     .getSerializableExtra(RobotDescription.UNIQUE_KEY);
00332 
00333             robotNameResolver.setRobotName(robotDescription
00334                     .getRobotName());
00335 
00336             validatedRobot = false;
00337             validateRobot(robotDescription.getRobotId());
00338 
00339             uri = new URI(robotDescription.getRobotId()
00340                     .getMasterUri());
00341         } catch (URISyntaxException e) {
00342             throw new RosRuntimeException(e);
00343         }
00344         nodeMainExecutorService.setMasterUri(uri);
00345         // Run init() in a new thread as a convenience since it often
00346         // requires network access. This would be more robust if it
00347         // had a failure handler for uncontactable errors (override
00348         // onPostExecute) that occurred when calling init. In reality
00349         // this shouldn't happen often - only when the connection
00350         // is unavailable inbetween validating and init'ing.
00351         new AsyncTask<Void, Void, Void>() {
00352             @Override
00353             protected Void doInBackground(Void... params) {
00354                 while (!validatedRobot) {
00355                     // should use a sleep here to avoid burnout
00356                 }
00357                 RobotRemocon.this.init(nodeMainExecutorService);
00358                 return null;
00359             }
00360         }.execute();
00361     }
00371         @Override
00372         public void onActivityResult(int requestCode, int resultCode, Intent data) {
00373                 if (resultCode == RESULT_CANCELED) {
00374                         finish();
00375                 } else if (resultCode == RESULT_OK) {
00376                         if (requestCode == ROBOT_MASTER_CHOOSER_REQUEST_CODE) {
00377                 init(data);
00378             } else {
00379                                 // Without a master URI configured, we are in an unusable state.
00380                                 nodeMainExecutorService.shutdown();
00381                                 finish();
00382                         }
00383                 }
00384         }
00385 
00393         @Override
00394         public void startMasterChooser() {
00395                 if (!fromApplication) {
00396                         super.startActivityForResult(new Intent(this,
00397                                         RobotMasterChooser.class),
00398                                         ROBOT_MASTER_CHOOSER_REQUEST_CODE);
00399                 } else {
00400             if (getIntent().hasExtra(RobotDescription.UNIQUE_KEY)) {
00401                 init(getIntent());
00402                 Log.i("RobotRemocon", "closing remocon application and successfully retrieved the robot description via intents.");
00403             } else {
00404                 Log.e("RobotRemocon", "closing remocon application didn't return the robot description - *spank*.");
00405             }
00406         }
00407         }
00408 
00409         public void validateRobot(final RobotId id) {
00410                 wifiDialog = new AlertDialogWrapper(this, new AlertDialog.Builder(this)
00411                                 .setTitle("Change Wifi?").setCancelable(false), "Yes", "No");
00412                 evictDialog = new AlertDialogWrapper(this,
00413                                 new AlertDialog.Builder(this).setTitle("Evict User?")
00414                                                 .setCancelable(false), "Yes", "No");
00415                 errorDialog = new AlertDialogWrapper(this,
00416                                 new AlertDialog.Builder(this).setTitle("Could Not Connect")
00417                                                 .setCancelable(false), "Ok");
00418                 progressDialog = new ProgressDialogWrapper(this);
00419                 final AlertDialogWrapper wifiDialog = new AlertDialogWrapper(this,
00420                                 new AlertDialog.Builder(this).setTitle("Change Wifi?")
00421                                                 .setCancelable(false), "Yes", "No");
00422 
00423                 // Run a set of checkers in series.
00424                 // The last step - ensure the master is up.
00425                 final MasterChecker mc = new MasterChecker(
00426                                 new MasterChecker.RobotDescriptionReceiver() {
00427                                         public void receive(RobotDescription robotDescription) {
00428                                                 runOnUiThread(new Runnable() {
00429                                                         public void run() {
00430                                                                 final ProgressDialogWrapper p = progressDialog;
00431                                                                 if (p != null) {
00432                                                                         p.dismiss();
00433                                                                 }
00434                                                         }
00435                                                 });
00436                         if(!fromApplication) {
00437                             // Check that it's not busy
00438                             if ( robotDescription.getConnectionStatus() == RobotDescription.UNAVAILABLE ) {
00439                                 errorDialog.show("Robot is unavailable : busy serving another remote controller.");
00440                                 errorDialog.dismiss();
00441                                 startMasterChooser();
00442                             } else {
00443                                 // Invitation checker - should reconstruct the control/master/invitation checkers
00444                                 // Note the control checker is doing user control checking, not used by turtlebots, but by pr2?
00445                                 NodeMainExecutorService nodeMainExecutorService = new NodeMainExecutorService();
00446                                 NodeConfiguration nodeConfiguration;
00447                                 try {
00448                                     URI uri = new URI(robotDescription.getMasterUri());
00449                                     nodeConfiguration = NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress(), uri);
00450                                 } catch (URISyntaxException e) {
00451                                     return; // should handle this
00452                                 }
00453                                 InvitationServiceClient client = new InvitationServiceClient(robotDescription.getGatewayName(), robotDescription.getRobotName());
00454                                 nodeMainExecutorService.execute(client, nodeConfiguration.setNodeName("send_invitation_node"));
00455                                 Boolean result = client.waitForResponse();
00456                                 nodeMainExecutorService.shutdownNodeMain(client);
00457                                 if ( !result ) {
00458                                     errorDialog.show("Timed out trying to invite the robot for pairing mode.");
00459                                     errorDialog.dismiss();
00460                                     startMasterChooser();
00461                                 } else {
00462                                     if ( client.getInvitationResult().equals(Boolean.TRUE) ) {
00463                                         validatedRobot = true;
00464                                     } else {
00465                                         startMasterChooser();
00466                                     }
00467                                 }
00468                             }
00469                         } else { // fromApplication
00470                             // Working on the lovely assumption that we're already controlling the rapp manager
00471                             // since we come from a running app. Note that this code is run after platform info
00472                             // checks have been made (see MasterChecker).
00473                             validatedRobot = true;
00474                         }
00475                                         }
00476                                 }, new MasterChecker.FailureHandler() {
00477                                         public void handleFailure(String reason) {
00478                                                 final String reason2 = reason;
00479                         // Kill the connecting to ros master dialog.
00480                                                 runOnUiThread(new Runnable() {
00481                                                         public void run() {
00482                                                                 final ProgressDialogWrapper p = progressDialog;
00483                                                                 if (p != null) {
00484                                                                         p.dismiss();
00485                                                                 }
00486                                                         }
00487                                                 });
00488                                                 errorDialog.show("Cannot contact ROS master: "
00489                                                                 + reason2);
00490                                                 errorDialog.dismiss();
00491                         // TODO : gracefully abort back to the robot master chooser instead.
00492                         finish();
00493                                         }
00494                                 });
00495 
00496                 // Ensure the robot is in a good state
00497                 final ControlChecker cc = new ControlChecker(
00498                                 new ControlChecker.SuccessHandler() {
00499                                         public void handleSuccess() {
00500                                                 runOnUiThread(new Runnable() {
00501                                                         public void run() {
00502                                                                 final ProgressDialogWrapper p = progressDialog;
00503                                                                 if (p != null) {
00504                                                                         p.dismiss();
00505                                                                         p.show("Connecting...",
00506                                                                                         "Connecting to ROS master");
00507                                                                 }
00508                                                         }
00509                                                 });
00510                                                 mc.beginChecking(id);
00511                                         }
00512                                 }, new ControlChecker.FailureHandler() {
00513                                         public void handleFailure(String reason) {
00514                                                 final String reason2 = reason;
00515                                                 runOnUiThread(new Runnable() {
00516                                                         public void run() {
00517                                                                 final ProgressDialogWrapper p = progressDialog;
00518                                                                 if (p != null) {
00519                                                                         p.dismiss();
00520                                                                 }
00521                                                         }
00522                                                 });
00523                                                 errorDialog.show("Cannot connect to control robot: "
00524                                                                 + reason2);
00525                                                 errorDialog.dismiss();
00526                                                 finish();
00527 
00528                                         }
00529                                 }, new ControlChecker.EvictionHandler() {
00530                                         public boolean doEviction(String current, String message) {
00531                                                 runOnUiThread(new Runnable() {
00532                                                         public void run() {
00533                                                                 final ProgressDialogWrapper p = progressDialog;
00534                                                                 if (p != null) {
00535                                                                         p.dismiss();
00536                                                                 }
00537                                                         }
00538                                                 });
00539                                                 String m = "";
00540                                                 if (message != null) {
00541                                                         m = " The user says: \"" + message + "\"";
00542                                                 }
00543                                                 evictDialog
00544                                                                 .setMessage(current
00545                                                                                 + " is running custom software on this robot. Do you want to evict this user?"
00546                                                                                 + m);
00547                                                 runOnUiThread(new Runnable() {
00548                                                         public void run() {
00549                                                                 final ProgressDialogWrapper p = progressDialog;
00550                                                                 if (p != null) {
00551                                                                         p.show("Connecting...",
00552                                                                                         "Deactivating robot");
00553                                                                 }
00554                                                         }
00555                                                 });
00556                                                 return evictDialog.show();
00557                                         }
00558 
00559                                         @Override
00560                                         public boolean doEviction(String user) {
00561                                                 // TODO Auto-generated method stub
00562                                                 return false;
00563                                         }
00564                                 }, new ControlChecker.StartHandler() {
00565                                         public void handleStarting() {
00566                                                 runOnUiThread(new Runnable() {
00567                                                         public void run() {
00568                                                                 final ProgressDialogWrapper p = progressDialog;
00569                                                                 if (p != null) {
00570                                                                         p.dismiss();
00571                                                                         p.show("Connecting...", "Starting robot");
00572                                                                 }
00573                                                         }
00574                                                 });
00575                                         }
00576                                 });
00577 
00578                 // Ensure that the correct WiFi network is selected.
00579                 final WifiChecker wc = new WifiChecker(
00580                                 new WifiChecker.SuccessHandler() {
00581                                         public void handleSuccess() {
00582                                                 runOnUiThread(new Runnable() {
00583                                                         public void run() {
00584                                                                 final ProgressDialogWrapper p = progressDialog;
00585                                                                 if (p != null) {
00586                                                                         p.dismiss();
00587                                                                         p.show("Connecting...",
00588                                                                                         "Checking robot state");
00589                                                                 }
00590                                                         }
00591                                                 });
00592                                                 cc.beginChecking(id);
00593                                         }
00594                                 }, new WifiChecker.FailureHandler() {
00595                                         public void handleFailure(String reason) {
00596                                                 final String reason2 = reason;
00597                                                 runOnUiThread(new Runnable() {
00598                                                         public void run() {
00599                                                                 final ProgressDialogWrapper p = progressDialog;
00600                                                                 if (p != null) {
00601                                                                         p.dismiss();
00602                                                                 }
00603                                                         }
00604                                                 });
00605                                                 errorDialog.show("Cannot connect to robot WiFi: "
00606                                                                 + reason2);
00607                                                 errorDialog.dismiss();
00608                                                 finish();
00609                                         }
00610                                 }, new WifiChecker.ReconnectionHandler() {
00611                                         public boolean doReconnection(String from, String to) {
00612                                                 runOnUiThread(new Runnable() {
00613                                                         public void run() {
00614                                                                 final ProgressDialogWrapper p = progressDialog;
00615                                                                 if (p != null) {
00616                                                                         p.dismiss();
00617                                                                 }
00618                                                         }
00619                                                 });
00620                                                 if (from == null) {
00621                                                         wifiDialog
00622                                                                         .setMessage("To use this robot, you must connect to a wifi network. You are currently not connected to a wifi network. Would you like to connect to the correct wireless network?");
00623                                                 } else {
00624                                                         wifiDialog
00625                                                                         .setMessage("To use this robot, you must switch wifi networks. Do you want to switch from "
00626                                                                                         + from + " to " + to + "?");
00627                                                 }
00628                                                 runOnUiThread(new Runnable() {
00629                                                         public void run() {
00630                                                                 final ProgressDialogWrapper p = progressDialog;
00631                                                                 if (p != null) {
00632                                                                         p.show("Connecting...",
00633                                                                                         "Switching wifi networks");
00634                                                                 }
00635                                                         }
00636                                                 });
00637                                                 return wifiDialog.show();
00638                                         }
00639                                 });
00640                 progressDialog.show("Connecting...", "Checking wifi connection");
00641                 wc.beginChecking(id, (WifiManager) getSystemService(WIFI_SERVICE));
00642         }
00643 
00644         public void onAppClicked(final App app, final boolean isClientApp) {
00645 
00646                 boolean running = false;
00647                 for (App i : runningAppsCache) {
00648                         if (i.getName().equals(app.getName())) {
00649                                 running = true;
00650                         }
00651                 }
00652 
00653                 if (!running && alreadyClicked == false) {
00654                         alreadyClicked = true;
00655 
00656                         AppManager appManager = new AppManager(app.getName(),
00657                                         getRobotNameSpaceResolver());
00658                         appManager.setFunction("start");
00659 
00660                         stopProgress();
00661                         runOnUiThread(new Runnable() {
00662                                 @Override
00663                                 public void run() {
00664                                         stopProgress();
00665                                         progress = ProgressDialog.show(RobotRemocon.this,
00666                                                         "Starting Rapp",
00667                                                         "Starting " + app.getDisplayName() + "...", true,
00668                                                         false);
00669                                         progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
00670                                 }
00671                         });
00672 
00673                         appManager
00674                                         .setStartService(new ServiceResponseListener<StartAppResponse>() {
00675                                                 @Override
00676                                                 public void onSuccess(StartAppResponse message) {
00677                                                         if (message.getStarted()) {
00678                                                                 Log.i("RobotRemocon", "Rapp started successfully [" + app.getDisplayName() + "]");
00679                                                                 alreadyClicked = false;
00680                                                                 // safeSetStatus("Started");
00681                                                         } else if (message.getErrorCode() == ErrorCodes.MULTI_RAPP_NOT_SUPPORTED) {
00682                                                                 runOnUiThread(new Runnable() {
00683                                                                         @Override
00684                                                                         public void run() {
00685                                                                                 showDialog(MULTI_RAPP_DISABLED);
00686                                                                         }
00687                                                                 });
00688 
00689                                                         } else {
00690                                                                 Log.w("RobotRemocon", message.getMessage());
00691                                                                 // safeSetStatus(message.getMessage());
00692                                                         }
00693                                                         stopProgress();
00694                                                 }
00695 
00696                                                 @Override
00697                                                 public void onFailure(RemoteException e) {
00698                                                         // safeSetStatus("Failed: " + e.getMessage());
00699                                                         stopProgress();
00700                                                 }
00701                                         });
00702 
00703                         nodeMainExecutor.execute(appManager,
00704                                         nodeConfiguration.setNodeName("start_app"));
00705 
00706                 }
00707         }
00708 
00709         protected void updateAppList(final ArrayList<App> apps,
00710                         final ArrayList<App> runningApps) {
00711                 Log.d("RobotRemocon", "updating app list gridview");
00712                 GridView gridview = (GridView) findViewById(R.id.gridview);
00713                 AppAdapter appAdapter = new AppAdapter(RobotRemocon.this, apps,
00714                                 runningApps);
00715                 gridview.setAdapter(appAdapter);
00716                 registerForContextMenu(gridview);
00717                 gridview.setOnItemClickListener(new OnItemClickListener() {
00718                         @Override
00719                         public void onItemClick(AdapterView<?> parent, View v,
00720                                         int position, long id) {
00721 
00722                                 App app = availableAppsCache.get(position);
00723 
00724                                 if (runningAppsCache.size() > 0) {
00725                                         runningNodes = true;
00726                                         Log.i("RobotRemocon", "RunningAppsCache greater than zero.");
00727                                 }
00728 
00729                                 if (AppLauncher.launch(RobotRemocon.this, apps.get(position),
00730                                                 getMasterUri(), robotDescription, runningNodes) == true) {
00731                                         if (progress != null) {
00732                                                 progress.dismiss();
00733                                         }
00734                                         finish();
00735                                 } else
00736                                         onAppClicked(app, true);
00737                         }
00738                 });
00739                 if (runningApps != null) {
00740                         if (runningApps.toArray().length != 0) {
00741                                 stopAppsButton.setVisibility(stopAppsButton.VISIBLE);
00742                         } else {
00743                                 stopAppsButton.setVisibility(stopAppsButton.GONE);
00744                         }
00745                 }
00746                 Log.d("RobotRemocon", "app list gridview updated");
00747         }
00748 
00749         public void chooseNewMasterClicked(View view) {
00750         // uninvite ourselves
00751         InvitationServiceClient client = new InvitationServiceClient(robotDescription.getGatewayName(), robotDescription.getRobotName(), Boolean.TRUE);
00752         nodeMainExecutorService.execute(client, nodeConfiguration.setNodeName("send_uninvitation_node"));
00753         Boolean result = client.waitForResponse();
00754         nodeMainExecutorService.shutdownNodeMain(client);
00755         if ( !result ) {
00756             errorDialog.show("Timed out trying to invite the robot for pairing mode.");
00757             errorDialog.dismiss();
00758         }
00759         returnToRobotMasterChooser();
00760         }
00761 
00767     private void returnToRobotMasterChooser() {
00768         if (pairingApplicationNamePublisher != null) {
00769             nodeMainExecutor.shutdownNodeMain(pairingApplicationNamePublisher);
00770         }
00771         if (listAppsSubscriber != null) {
00772             nodeMainExecutor.shutdownNodeMain(listAppsSubscriber);
00773         }
00774         releaseRobotNameResolver();
00775         releaseDashboardNode(); // TODO this work costs too many times
00776         availableAppsCache.clear();
00777         runningAppsCache.clear();
00778         startActivityForResult(new Intent(this, RobotMasterChooser.class),
00779                 ROBOT_MASTER_CHOOSER_REQUEST_CODE);
00780     }
00781 
00782         public void exchangeButtonClicked(View view) {
00783         }
00784 
00785         public void deactivateRobotClicked(View view) {
00786         }
00787 
00793     public void stopRobotApplication() {
00794         // Should find a way to stop the application without using *, i.e. keep
00795         // the previously rapp-initialised AppManager around and stop that from here.
00796         // Can we use just one AppManager?
00797         AppManager appManager = new AppManager("*", getRobotNameSpaceResolver());
00798         appManager.setFunction("stop");
00799         appManager
00800                 .setStopService(new ServiceResponseListener<StopAppResponse>() {
00801                     @Override
00802                     public void onSuccess(StopAppResponse message) {
00803                         Log.i("RobotRemocon", "app stopped successfully");
00804                         availableAppsCache = new ArrayList<App>();
00805                         runningAppsCache = new ArrayList<App>();
00806                         runOnUiThread(new Runnable() {
00807                             @Override
00808                             public void run() {
00809                                 updateAppList(availableAppsCache,
00810                                         runningAppsCache);
00811                             }
00812                         });
00813                         progressDialog.dismiss();
00814 
00815                     }
00816 
00817                     @Override
00818                     public void onFailure(RemoteException e) {
00819                         Log.e("RobotRemocon", "app failed to stop!");
00820                     }
00821                 });
00822         nodeMainExecutor.execute(appManager,
00823                 nodeConfiguration.setNodeName("stop_app"));
00824     }
00825 
00834         public void stopApplicationsClicked(View view) {
00835 
00836         /* Why trying to launch again? */
00837                 /*
00838                 for (App i : runningAppsCache) {
00839                         Log.i("RobotRemocon", "sending intent to stop app to the app launcher [" + i.getName() + "]");
00840                         AppLauncher
00841                                         .launch(this, i, getMasterUri(), robotDescription, false);
00842                 }
00843         */
00844 
00845                 progressDialog = new ProgressDialogWrapper(this);
00846                 progressDialog.show("Stopping Applications",
00847                                 "Stopping all applications...");
00848         stopRobotApplication();
00849         }
00850 
00851         @Override
00852         public boolean onCreateOptionsMenu(Menu menu) {
00853                 menu.add(0, 0, 0, R.string.exit);
00854                 return super.onCreateOptionsMenu(menu);
00855         }
00856 
00857         @Override
00858         public boolean onOptionsItemSelected(MenuItem item) {
00859                 super.onOptionsItemSelected(item);
00860                 switch (item.getItemId()) {
00861                 case 0:
00862                         finish();
00863                         break;
00864                 }
00865                 return true;
00866         }
00867 
00868         @Override
00869         protected Dialog onCreateDialog(int id) {
00870                 // readRobotList();
00871                 final Dialog dialog;
00872                 Button button;
00873                 AlertDialog.Builder builder = new AlertDialog.Builder(this);
00874                 switch (id) {
00875                 case CLOSE_EXISTING:
00876                         builder.setTitle("Stop Current Application?");
00877                         builder.setMessage("There is an application already running. You cannot run two applications at once. Would you like to stop the current application?");
00878                         // builder.setPositiveButton("Stop Current",
00879                         // new DialogButtonClickHandler());
00880                         // builder.setNegativeButton("Don't Stop",
00881                         // new DialogButtonClickHandler());
00882                         dialog = builder.create();
00883                         break;
00884                 case MULTI_RAPP_DISABLED:
00885                         builder.setTitle("Multi-App Disabled on Robot");
00886                         builder.setMessage("The mode for running multiple apps is disabled on the robot. If you would like to enable it then you can change the arguments that the App Manager gets in its launch file.");
00887                         // builder.setNeutralButton("Okay", new DialogButtonClickHandler());
00888                         dialog = builder.create();
00889                         break;
00890                 default:
00891                         dialog = null;
00892 
00893                 }
00894                 return dialog;
00895         }
00896 
00897     @Override
00898     public void onBackPressed() {
00899         // this takes too long to complete and gets in the way of quickly shutting down.
00900         // returnToRobotMasterChooser();
00901         finish();
00902     }
00903 }


android_remocons
Author(s): Daniel Stonier , Kazuto Murase
autogenerated on Wed Aug 26 2015 10:40:28