AppLauncher.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  * Copyright (c) 2013, Yujin Robot.
00007  *
00008  * All rights reserved.
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  *
00013  * * Redistributions of source code must retain the above copyright
00014  * notice, this list of conditions and the following disclaimer.
00015  * * Redistributions in binary form must reproduce the above
00016  * copyright notice, this list of conditions and the following
00017  * disclaimer in the documentation and/or other materials provided
00018  * with the distribution.
00019  * * Neither the name of Willow Garage, Inc. nor the names of its
00020  * contributors may be used to endorse or promote products derived
00021  * from this software without specific prior written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  * POSSIBILITY OF SUCH DAMAGE.
00035  */
00036 
00037 package com.github.rosjava.android_remocons.common_tools;
00038 
00039 import android.app.Activity;
00040 import android.content.ActivityNotFoundException;
00041 import android.content.Intent;
00042 import android.net.Uri;
00043 import android.os.AsyncTask;
00044 import android.util.Log;
00045 import android.util.Patterns;
00046 
00047 import com.github.rosjava.android_apps.application_management.AppManager;
00048 import com.github.rosjava.android_apps.application_management.ConcertDescription;
00049 import com.github.rosjava.android_apps.application_management.RosAppActivity;
00050 
00051 import java.io.IOException;
00052 import java.net.HttpURLConnection;
00053 import java.net.MalformedURLException;
00054 import java.net.URISyntaxException;
00055 import java.net.URL;
00056 import java.net.URLEncoder;
00057 import java.util.concurrent.TimeUnit;
00058 import java.util.concurrent.TimeoutException;
00059 
00060 
00069 public class AppLauncher {
00070 
00071     public enum Result {
00072         SUCCESS,
00073         NOT_INSTALLED,
00074         CANNOT_CONNECT,
00075         MALFORMED_URI,
00076         CONNECT_TIMEOUT,
00077         OTHER_ERROR;
00078 
00079         public String message;
00080 
00081         Result withMsg(String message) {
00082             this.message = message;
00083             return this;
00084         }
00085     }
00086 
00090     static public Result launch(final Activity parent, final ConcertDescription concert,
00091                                 final concert_msgs.RemoconApp app) {
00092 
00093         Log.i("AppLaunch", "launching concert app " + app.getDisplayName() + " on service " + app.getServiceName());
00094 
00095         // On android apps, app name will be an intent action, while for web apps it will be its URL
00096         if (Patterns.WEB_URL.matcher(app.getName()).matches() == true) {
00097             return launchWebApp(parent, concert, app);
00098         }
00099         else {
00100             return launchAndroidApp(parent, concert, app);
00101         }
00102     }
00103 
00104 
00108     static private Result launchAndroidApp(final Activity parent, final ConcertDescription concert,
00109                                            final concert_msgs.RemoconApp app) {
00110 
00111         // Create the Intent from rapp's name, pass it parameters and remaps and start it
00112         String appName = app.getName();
00113         Intent intent = new Intent(appName);
00114 
00115         // Copy all app data to "extra" data in the intent.
00116         intent.putExtra(AppManager.PACKAGE + "." + RosAppActivity.AppMode.CONCERT + "_app_name", appName);
00117         intent.putExtra(ConcertDescription.UNIQUE_KEY, concert);
00118         intent.putExtra("RemoconActivity", "com.github.rosjava.android_remocons.concert_remocon.ConcertRemocon"); // TODO must be a RoconConstant!
00119         intent.putExtra("Parameters", app.getParameters());  // YAML-formatted string
00120 
00121         // Remappings come as a messages list that make YAML parser crash, so we must digest if for him
00122         if ((app.getRemappings() != null) && (app.getRemappings().size() > 0)) {
00123             String remaps = "{";
00124             for (rocon_std_msgs.Remapping remap: app.getRemappings())
00125                 remaps += remap.getRemapFrom() + ": " + remap.getRemapTo() + ", ";
00126             remaps = remaps.substring(0, remaps.length() - 2) + "}";
00127             intent.putExtra("Remappings", remaps);
00128         }
00129 
00130 //      intent.putExtra("runningNodes", runningNodes);
00131 //      intent.putExtra("PairedManagerActivity", "com.github.concertics_in_concert.rocon_android.concert_remocon.ConcertRemocon");
00132 
00133         try {
00134             Log.i("AppLaunch", "trying to start activity (action: " + appName + " )");
00135             parent.startActivity(intent);
00136             return Result.SUCCESS;
00137         } catch (ActivityNotFoundException e) {
00138             Log.i("AppLaunch", "activity not found for action: " + appName);
00139         }
00140         return Result.NOT_INSTALLED.withMsg("Android app not installed");
00141     }
00142 
00143 
00147     static private Result launchWebApp(final Activity parent, final ConcertDescription concert,
00148                                        final concert_msgs.RemoconApp app) {
00149         try
00150         {
00151             // Validate the URL before starting anything
00152             URL appURL = new URL(app.getName());
00153 
00154             AsyncTask<URL, Void, String> asyncTask = new AsyncTask<URL, Void, String>() {
00155                 @Override
00156                 protected String doInBackground(URL... urls) {
00157                     try {
00158                         HttpURLConnection urlConnection = (HttpURLConnection)urls[0].openConnection();
00159                         int responseCode = urlConnection.getResponseCode();
00160                         urlConnection.disconnect();
00161                         return urlConnection.getResponseMessage();
00162                     }
00163                     catch (IOException e) {
00164                         return e.getMessage();
00165                     }
00166                 }
00167             }.execute(appURL);
00168             String result = asyncTask.get(5, TimeUnit.SECONDS);
00169             if (result == null || (result.startsWith("OK") == false && result.startsWith("ok") == false)) {
00170                 return Result.CANNOT_CONNECT.withMsg(result);
00171             }
00172 
00173             // We pass concert URL, parameters and remaps as URL parameters
00174             String appUriStr = app.getName();
00175             appUriStr += "?" + "MasterURI=" + concert.getMasterUri();
00176             if ((app.getParameters() != null) && (app.getParameters().length() > 0)) {
00177                 appUriStr += "&" + "params=" + URLEncoder.encode(app.getParameters());
00178             }
00179 
00180             // Remappings come as a messages list that make YAML parser crash, so we must digest if for him
00181             // TODO Single quotes seem to be necessary, but I didn't confirm yet
00182             if ((app.getRemappings() != null) && (app.getRemappings().size() > 0)) {
00183                 String remaps = "{";
00184                 for (rocon_std_msgs.Remapping remap: app.getRemappings())
00185                     remaps += "\'" + remap.getRemapFrom() + "\':\'" + remap.getRemapTo() + "\',";
00186                 remaps = remaps.substring(0, remaps.length() - 1) + "}";
00187                 appUriStr += "&" + "remaps=" + URLEncoder.encode(remaps);
00188             }
00189 
00190             appURL = new URL(appUriStr);
00191             appURL.toURI(); // throws URISyntaxException if fails; probably a redundant check
00192             Uri appURI =  Uri.parse(appUriStr);
00193 
00194             // Create an action view intent and pass rapp's name + extra information as URI
00195             Intent intent = new Intent(Intent.ACTION_VIEW, appURI);
00196 
00197             Log.i("AppLaunch", "trying to start web app (URI: " + appUriStr + ")");
00198             parent.startActivity(intent);
00199             return Result.SUCCESS;
00200         }
00201         catch (URISyntaxException e) {
00202             return Result.MALFORMED_URI.withMsg("Cannot convert URL into URI. " + e.getMessage());
00203         }
00204         catch (MalformedURLException e)
00205         {
00206             return Result.MALFORMED_URI.withMsg("App URL is not valid. " + e.getMessage());
00207         }
00208         catch (ActivityNotFoundException e) {
00209             // This cannot happen for a web site, right? must mean that I have no web browser!
00210             return Result.NOT_INSTALLED.withMsg("Activity not found for view action??? muoia???");
00211         }
00212         catch (TimeoutException e)
00213         {
00214             return Result.CONNECT_TIMEOUT.withMsg("Timeout waiting for app");
00215         }
00216         catch (Exception e)
00217         {
00218             return Result.OTHER_ERROR.withMsg(e.getMessage());
00219         }
00220     }
00221 }


android_remocons
Author(s): Daniel Stonier, Kazuto Murase
autogenerated on Sat Jun 8 2019 19:32:24