Java tutorial
/* * Copyright (C) 2013 ENTERTAILION, LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.entertailion.java.caster; import java.io.Reader; import java.io.StringReader; import java.net.URI; import java.util.UUID; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.ProtocolException; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultRedirectHandler; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; import org.java_websocket.handshake.ServerHandshake; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; /* * Manage RAMP protocol * * @author leon_nicholls */ public class RampClient implements RampWebSocketListener { private static final String LOG_TAG = "RampClient"; private static final String STATE_RUNNING = "running"; private static final String STATE_STOPPED = "stopped"; private static final String PROTOCOL_CM = "cm"; private static final String PROTOCOL_RAMP = "ramp"; private static final String PROTOCOL_CV = "cV"; private static final String TYPE = "type"; private static final String PING = "ping"; private static final String PONG = "pong"; private static final String ACTIVITY = "activity"; private static final String ACTIVITY_MESSAGE = "message"; private static final String ACTIVITY_CURRENT_TIME = "currentTime"; private static final String ACTIVITY_DURATION = "duration"; private static final String ACTIVITY_STATE = "state"; private static final String ACTIVITY_TIME_UPDATE = "timeupdate"; private static final String STATUS = "STATUS"; private static final String RESPONSE = "RESPONSE"; private static final String RESPONSE_STATUS = "status"; private static final String RESPONSE_STATE = "state"; private static final String RESPONSE_CURRENT_TIME = "current_time"; private static final String RESPONSE_DURATION = "duration"; private static final String HEADER_CONNECTION = "Connection"; private static final String HEADER_CONNECTION_VALUE = "keep-alive"; private static final String HEADER_ORIGN = "Origin"; private static final String HEADER_ORIGIN_VALUE = "chrome-extension://boadgeojelhgndaghljhdicfkmllpafd"; private static final String HEADER_USER_AGENT = "User-Agent"; private static final String HEADER_USER_AGENT_VALUE = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36"; private static final String HEADER_DNT = "DNT"; private static final String HEADER_DNT_VALUE = "1"; private static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding"; private static final String HEADER_ACCEPT_ENCODING_VALUE = "gzip,deflate,sdch"; private static final String HEADER_ACCEPT = "Accept"; private static final String HEADER_ACCEPT_VALUE = "*/*"; private static final String HEADER_ACCEPT_LANGUAGE = "Accept-Language"; private static final String HEADER_ACCEPT_LANGUAGE_VALUE = "en-US,en;q=0.8"; private static final String HEADER_CONTENT_TYPE = "Content-Type"; private static final String HEADER_CONTENT_TYPE_JSON_VALUE = "application/json"; private static final String HEADER_CONTENT_TYPE_TEXT_VALUE = "text/plain"; private String connectionServiceUrl; private String state; private String protocol; private String response; private boolean started; private boolean closed; private boolean doPlay; private RampWebSocketClient rampWebSocketClient; private int commandId = 1; private String app; private String activityId; private String senderId; private boolean isChromeCast; private boolean gotStatus; private Thread infoThread; private DialServer dialServer; private Playback playback; private PlaybackListener playbackListener; private DefaultHttpClient defaultHttpClient; private BasicHttpContext localContext; private CustomRedirectHandler handler; public RampClient(Playback playback, PlaybackListener playbackListener) { this.playback = playback; this.playbackListener = playbackListener; this.senderId = UUID.randomUUID().toString(); defaultHttpClient = HttpRequestHelper.createHttpClient(); handler = new CustomRedirectHandler(); defaultHttpClient.setRedirectHandler(handler); localContext = new BasicHttpContext(); } public void launchApp(String app, DialServer dialServer, String body) { this.app = app; // TODO // /this.isChromeCast = app.equals(FlingFrame.CHROMECAST); this.dialServer = dialServer; this.activityId = UUID.randomUUID().toString(); if (dialServer != null) { try { String device = "http://" + dialServer.getIpAddress().getHostAddress() + ":" + dialServer.getPort(); Log.d(LOG_TAG, "device=" + device); Log.d(LOG_TAG, "apps url=" + dialServer.getAppsUrl()); // application instance url String location = null; // check if any app is running HttpGet httpGet = new HttpGet(dialServer.getAppsUrl()); httpGet.setHeader(HEADER_CONNECTION, HEADER_CONNECTION_VALUE); httpGet.setHeader(HEADER_USER_AGENT, HEADER_USER_AGENT_VALUE); httpGet.setHeader(HEADER_ACCEPT, HEADER_ACCEPT_VALUE); httpGet.setHeader(HEADER_DNT, HEADER_DNT_VALUE); httpGet.setHeader(HEADER_ACCEPT_ENCODING, HEADER_ACCEPT_ENCODING_VALUE); httpGet.setHeader(HEADER_ACCEPT_LANGUAGE, HEADER_ACCEPT_LANGUAGE_VALUE); HttpResponse httpResponse = defaultHttpClient.execute(httpGet); if (httpResponse != null) { int responseCode = httpResponse.getStatusLine().getStatusCode(); Log.d(LOG_TAG, "get response code=" + httpResponse.getStatusLine().getStatusCode()); if (responseCode == 204) { // nothing is running } else if (responseCode == 200) { // app is running // Need to get real URL after a redirect // http://stackoverflow.com/a/10286025/594751 String lastUrl = dialServer.getAppsUrl(); if (handler.lastRedirectedUri != null) { lastUrl = handler.lastRedirectedUri.toString(); Log.d(LOG_TAG, "lastUrl=" + lastUrl); } String response = EntityUtils.toString(httpResponse.getEntity()); Log.d(LOG_TAG, "get response=" + response); parseXml(new StringReader(response)); Header[] headers = httpResponse.getAllHeaders(); for (int i = 0; i < headers.length; i++) { Log.d(LOG_TAG, headers[i].getName() + "=" + headers[i].getValue()); } // stop the app instance HttpDelete httpDelete = new HttpDelete(lastUrl); httpResponse = defaultHttpClient.execute(httpDelete); if (httpResponse != null) { Log.d(LOG_TAG, "delete response code=" + httpResponse.getStatusLine().getStatusCode()); response = EntityUtils.toString(httpResponse.getEntity()); Log.d(LOG_TAG, "delete response=" + response); } else { Log.d(LOG_TAG, "no delete response"); } } } else { Log.i(LOG_TAG, "no get response"); return; } // Check if app is installed on device int responseCode = getAppStatus(defaultHttpClient, dialServer.getAppsUrl() + app); if (responseCode != 200) { if (responseCode == 404) { Log.e(LOG_TAG, "APP ID is invalid"); } return; } parseXml(new StringReader(response)); Log.d(LOG_TAG, "state=" + state); // start the app with POST HttpPost httpPost = new HttpPost(dialServer.getAppsUrl() + app); httpPost.setHeader(HEADER_CONNECTION, HEADER_CONNECTION_VALUE); httpPost.setHeader(HEADER_ORIGN, HEADER_ORIGIN_VALUE); httpPost.setHeader(HEADER_USER_AGENT, HEADER_USER_AGENT_VALUE); httpPost.setHeader(HEADER_DNT, HEADER_DNT_VALUE); httpPost.setHeader(HEADER_ACCEPT_ENCODING, HEADER_ACCEPT_ENCODING_VALUE); httpPost.setHeader(HEADER_ACCEPT, HEADER_ACCEPT_VALUE); httpPost.setHeader(HEADER_ACCEPT_LANGUAGE, HEADER_ACCEPT_LANGUAGE_VALUE); httpPost.setHeader(HEADER_CONTENT_TYPE, HEADER_CONTENT_TYPE_TEXT_VALUE); if (isChromeCast) { // httpPost.setEntity(new // StringEntity("v=release-d4fa0a24f89ec5ba83f7bf3324282c8d046bf612&id=local%3A1&idle=windowclose")); httpPost.setEntity( new StringEntity("v=release-d4fa0a24f89ec5ba83f7bf3324282c8d046bf612&id=local%3A1")); } if (body != null) { httpPost.setEntity(new StringEntity(body)); // http://www.youtube.com/watch?v=cKG5HDyTW8o } httpResponse = defaultHttpClient.execute(httpPost, localContext); if (httpResponse != null) { Log.d(LOG_TAG, "post response code=" + httpResponse.getStatusLine().getStatusCode()); response = EntityUtils.toString(httpResponse.getEntity()); Log.d(LOG_TAG, "post response=" + response); Header[] headers = httpResponse.getHeaders("LOCATION"); if (headers.length > 0) { location = headers[0].getValue(); Log.d(LOG_TAG, "post response location=" + location); } headers = httpResponse.getAllHeaders(); for (int i = 0; i < headers.length; i++) { Log.d(LOG_TAG, headers[i].getName() + "=" + headers[i].getValue()); } } else { Log.i(LOG_TAG, "no post response"); return; } getWebSocket(app); } catch (Exception e) { Log.e(LOG_TAG, "launchApp", e); } } else { Log.d(LOG_TAG, "launchApp: dialserver null"); } } private void getWebSocket(String app) { try { int responseCode = 0; // Keep trying to get the app status until the // connection service URL is available state = STATE_STOPPED; do { responseCode = getAppStatus(defaultHttpClient, dialServer.getAppsUrl() + app); if (responseCode != 200) { if (responseCode == 404) { Log.e(LOG_TAG, "APP ID is invalid"); } break; } parseXml(new StringReader(response)); Log.d(LOG_TAG, "state=" + state); Log.d(LOG_TAG, "connectionServiceUrl=" + connectionServiceUrl); Log.d(LOG_TAG, "protocol=" + protocol); try { Thread.sleep(1000); } catch (Exception e) { } } while (state.equals(STATE_RUNNING) && connectionServiceUrl == null); if (connectionServiceUrl == null) { Log.i(LOG_TAG, "connectionServiceUrl is null"); return; // oops, something went wrong } // get the websocket URL String webSocketAddress = null; HttpPost httpPost = new HttpPost(connectionServiceUrl); // "http://192.168.0.17:8008/connection/YouTube" httpPost.setHeader(HEADER_CONNECTION, HEADER_CONNECTION_VALUE); httpPost.setHeader(HEADER_ORIGN, HEADER_ORIGIN_VALUE); httpPost.setHeader(HEADER_USER_AGENT, HEADER_USER_AGENT_VALUE); httpPost.setHeader(HEADER_DNT, HEADER_DNT_VALUE); httpPost.setHeader(HEADER_ACCEPT_ENCODING, HEADER_ACCEPT_ENCODING_VALUE); httpPost.setHeader(HEADER_ACCEPT, HEADER_ACCEPT_VALUE); httpPost.setHeader(HEADER_ACCEPT_LANGUAGE, HEADER_ACCEPT_LANGUAGE_VALUE); httpPost.setHeader(HEADER_CONTENT_TYPE, HEADER_CONTENT_TYPE_JSON_VALUE); httpPost.setEntity(new StringEntity("{\"channel\":0,\"senderId\":{\"appName\":\"" + app + "\", \"senderId\":\"" + senderId + "\"}}")); HttpResponse httpResponse = defaultHttpClient.execute(httpPost, localContext); if (httpResponse != null) { responseCode = httpResponse.getStatusLine().getStatusCode(); Log.d(LOG_TAG, "post response code=" + responseCode); if (responseCode == 200) { // should return JSON payload response = EntityUtils.toString(httpResponse.getEntity()); Log.d(LOG_TAG, "post response=" + response); Header[] headers = httpResponse.getAllHeaders(); for (int i = 0; i < headers.length; i++) { Log.d(LOG_TAG, headers[i].getName() + "=" + headers[i].getValue()); } // http://code.google.com/p/json-simple/ JSONParser parser = new JSONParser(); try { Object obj = parser.parse(new StringReader(response)); // {"URL":"ws://192.168.0.17:8008/session?33","pingInterval":0} JSONObject jsonObject = (JSONObject) obj; webSocketAddress = (String) jsonObject.get("URL"); Log.d(LOG_TAG, "webSocketAddress: " + webSocketAddress); long pingInterval = (Long) jsonObject.get("pingInterval"); // TODO } catch (Exception e) { Log.e(LOG_TAG, "parse JSON", e); } } } else { Log.i(LOG_TAG, "no post response"); return; } // Make a web socket connection for doing RAMP // to control media playback this.started = false; this.closed = false; this.gotStatus = false; if (webSocketAddress != null) { // https://github.com/TooTallNate/Java-WebSocket URI uri = URI.create(webSocketAddress); rampWebSocketClient = new RampWebSocketClient(uri, this); new Thread(new Runnable() { public void run() { Thread t = new Thread(rampWebSocketClient); t.start(); try { t.join(); } catch (InterruptedException e1) { e1.printStackTrace(); } finally { rampWebSocketClient.close(); } } }).start(); } else { Log.i(LOG_TAG, "webSocketAddress is null"); } } catch (Exception e) { Log.e(LOG_TAG, "getWebSocket", e); } } public void closeCurrentApp(DialServer dialServer) { if (dialServer != null) { try { DefaultHttpClient defaultHttpClient = HttpRequestHelper.createHttpClient(); CustomRedirectHandler handler = new CustomRedirectHandler(); defaultHttpClient.setRedirectHandler(handler); BasicHttpContext localContext = new BasicHttpContext(); // check if any app is running HttpGet httpGet = new HttpGet(dialServer.getAppsUrl()); httpGet.setHeader(HEADER_CONNECTION, HEADER_CONNECTION_VALUE); httpGet.setHeader(HEADER_USER_AGENT, HEADER_USER_AGENT_VALUE); httpGet.setHeader(HEADER_ACCEPT, HEADER_ACCEPT_VALUE); httpGet.setHeader(HEADER_DNT, HEADER_DNT_VALUE); httpGet.setHeader(HEADER_ACCEPT_ENCODING, HEADER_ACCEPT_ENCODING_VALUE); httpGet.setHeader(HEADER_ACCEPT_LANGUAGE, HEADER_ACCEPT_LANGUAGE_VALUE); HttpResponse httpResponse = defaultHttpClient.execute(httpGet); if (httpResponse != null) { int responseCode = httpResponse.getStatusLine().getStatusCode(); Log.d(LOG_TAG, "get response code=" + httpResponse.getStatusLine().getStatusCode()); if (responseCode == 204) { // nothing is running } else if (responseCode == 200) { // app is running // Need to get real URL after a redirect // http://stackoverflow.com/a/10286025/594751 String lastUrl = dialServer.getAppsUrl(); if (handler.lastRedirectedUri != null) { lastUrl = handler.lastRedirectedUri.toString(); Log.d(LOG_TAG, "lastUrl=" + lastUrl); } String response = EntityUtils.toString(httpResponse.getEntity()); Log.d(LOG_TAG, "get response=" + response); parseXml(new StringReader(response)); Header[] headers = httpResponse.getAllHeaders(); for (int i = 0; i < headers.length; i++) { Log.d(LOG_TAG, headers[i].getName() + "=" + headers[i].getValue()); } // stop the app instance HttpDelete httpDelete = new HttpDelete(lastUrl); httpResponse = defaultHttpClient.execute(httpDelete); if (httpResponse != null) { Log.d(LOG_TAG, "delete response code=" + httpResponse.getStatusLine().getStatusCode()); response = EntityUtils.toString(httpResponse.getEntity()); Log.d(LOG_TAG, "delete response=" + response); } else { Log.d(LOG_TAG, "no delete response"); } } } else { Log.i(LOG_TAG, "no get response"); return; } } catch (Exception e) { Log.e(LOG_TAG, "closeCurrentApp", e); } } else { Log.d(LOG_TAG, "closeCurrentApp: dialserver null"); } } public String getCurrentApp(DialServer dialServer) { if (dialServer != null) { try { DefaultHttpClient defaultHttpClient = HttpRequestHelper.createHttpClient(); CustomRedirectHandler handler = new CustomRedirectHandler(); defaultHttpClient.setRedirectHandler(handler); BasicHttpContext localContext = new BasicHttpContext(); // check if any app is running HttpGet httpGet = new HttpGet(dialServer.getAppsUrl()); httpGet.setHeader(HEADER_CONNECTION, HEADER_CONNECTION_VALUE); httpGet.setHeader(HEADER_USER_AGENT, HEADER_USER_AGENT_VALUE); httpGet.setHeader(HEADER_ACCEPT, HEADER_ACCEPT_VALUE); httpGet.setHeader(HEADER_DNT, HEADER_DNT_VALUE); httpGet.setHeader(HEADER_ACCEPT_ENCODING, HEADER_ACCEPT_ENCODING_VALUE); httpGet.setHeader(HEADER_ACCEPT_LANGUAGE, HEADER_ACCEPT_LANGUAGE_VALUE); HttpResponse httpResponse = defaultHttpClient.execute(httpGet); if (httpResponse != null) { int responseCode = httpResponse.getStatusLine().getStatusCode(); Log.d(LOG_TAG, "get response code=" + httpResponse.getStatusLine().getStatusCode()); if (responseCode == 204) { // nothing is running } else if (responseCode == 200) { // app is running // Need to get real URL after a redirect // http://stackoverflow.com/a/10286025/594751 String lastUrl = dialServer.getAppsUrl(); if (handler.lastRedirectedUri != null) { lastUrl = handler.lastRedirectedUri.toString(); Log.d(LOG_TAG, "lastUrl=" + lastUrl); String[] parts = lastUrl.split("/"); if (parts.length > 0) { return parts[parts.length - 1]; } } } } else { Log.i(LOG_TAG, "no get response"); } } catch (Exception e) { Log.e(LOG_TAG, "getCurrentApp", e); } } else { Log.d(LOG_TAG, "getCurrentApp: dialserver null"); } return null; } /** * Do HTTP GET for app status to determine response code and response body * * @param defaultHttpClient * @param url * @return */ private int getAppStatus(DefaultHttpClient defaultHttpClient, String url) { int responseCode = 200; try { HttpGet httpGet = new HttpGet(url); HttpResponse httpResponse = defaultHttpClient.execute(httpGet); if (httpResponse != null) { responseCode = httpResponse.getStatusLine().getStatusCode(); Log.d(LOG_TAG, "get response code=" + responseCode); response = EntityUtils.toString(httpResponse.getEntity()); Log.d(LOG_TAG, "get response=" + response); } else { Log.i(LOG_TAG, "no get response"); } } catch (Exception e) { Log.e(LOG_TAG, "getAppStatus", e); } return responseCode; } private void parseXml(Reader reader) { try { InputSource inStream = new org.xml.sax.InputSource(); inStream.setCharacterStream(reader); SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); AppHandler appHandler = new AppHandler(); xr.setContentHandler(appHandler); xr.parse(inStream); connectionServiceUrl = appHandler.getConnectionServiceUrl(); state = appHandler.getState(); protocol = appHandler.getProtocol(); } catch (Exception e) { Log.e(LOG_TAG, "parse device description", e); } } /** * Custom HTTP redirection handler to keep track of the redirected URL * ChromeCast web server will redirect "/apps" to "/apps/YouTube" if that is * the active/last app * */ public class CustomRedirectHandler extends DefaultRedirectHandler { public URI lastRedirectedUri; @Override public boolean isRedirectRequested(HttpResponse response, HttpContext context) { return super.isRedirectRequested(response, context); } @Override public URI getLocationURI(HttpResponse response, HttpContext context) throws ProtocolException { lastRedirectedUri = super.getLocationURI(response, context); return lastRedirectedUri; } } // RampWebSocketListener callbacks public void onMessage(String message) { Log.d(LOG_TAG, "onMessage: message" + message); // http://code.google.com/p/json-simple/ JSONParser parser = new JSONParser(); try { Object obj = parser.parse(new StringReader(message)); JSONArray array = (JSONArray) obj; if (array.get(0).equals(PROTOCOL_CM)) { Log.d(LOG_TAG, PROTOCOL_CM); JSONObject body = (JSONObject) array.get(1); // ["cm",{"type":"ping"}] if (body.get(TYPE).equals(PING)) { rampWebSocketClient.send("[\"cm\",{\"type\":\"pong\"}]"); } } else if (array.get(0).equals(PROTOCOL_RAMP)) { // ["ramp",{"cmd_id":0,"type":"STATUS","status":{"event_sequence":2,"state":0}}] Log.d(LOG_TAG, PROTOCOL_RAMP); JSONObject body = (JSONObject) array.get(1); if (body.get(TYPE).equals(STATUS)) { // Long cmd_id = (Long)body.get("cmd_id"); // commandId = cmd_id.intValue(); if (!gotStatus) { gotStatus = true; // rampWebSocketClient.send("[\"ramp\",{\"type\":\"LOAD\",\"cmd_id\":"+commandId+",\"autoplay\":true}] "); // commandId++; } } else if (body.get(TYPE).equals(RESPONSE)) { // ["ramp",{"cmd_id":7,"type":"RESPONSE","status":{"event_sequence":38,"state":2,"content_id":"http://192.168.0.50:8080/video.mp4","current_time":6.465110778808594, // "duration":27.37066650390625,"volume":1,"muted":false,"time_progress":true,"title":"Video"}}] JSONObject status = (JSONObject) body.get(RESPONSE_STATUS); if (status.get(RESPONSE_CURRENT_TIME) instanceof Double) { Double current_time = (Double) status.get(RESPONSE_CURRENT_TIME); if (current_time != null) { if (playbackListener != null) { playbackListener.updateTime(playback, current_time.intValue()); } } } else { Long current_time = (Long) status.get(RESPONSE_CURRENT_TIME); if (current_time != null) { if (playbackListener != null) { playbackListener.updateTime(playback, current_time.intValue()); } } } if (status.get(RESPONSE_DURATION) instanceof Double) { Double duration = (Double) status.get(RESPONSE_DURATION); if (duration != null) { if (playbackListener != null) { playbackListener.updateDuration(playback, duration.intValue()); } } } else { Long duration = (Long) status.get(RESPONSE_DURATION); if (duration != null) { if (playbackListener != null) { playbackListener.updateDuration(playback, duration.intValue()); } } } Long state = (Long) status.get(RESPONSE_STATE); if (playbackListener != null) { playbackListener.updateState(playback, state.intValue()); } } } else if (array.get(0).equals(PROTOCOL_CV)) { // ChromeCast default // receiver events Log.d(LOG_TAG, PROTOCOL_CV); JSONObject body = (JSONObject) array.get(1); if (body.get(TYPE).equals(ACTIVITY)) { // ["cv",{"type":"activity","message":{"type":"timeupdate","activityId":"d82cede3-ec23-4f73-8abc-343dd9ca6dbb","state":{"mediaUrl":"http://192.168.0.50:8087/cast.webm","videoUrl":"http://192.168.0.50:8087/cast.webm", // "currentTime":20.985000610351562,"duration":null,"pause":false,"muted":false,"volume":1,"paused":false}}}] JSONObject activityMessage = (JSONObject) body.get(ACTIVITY_MESSAGE); if (activityMessage != null) { JSONObject activityMessageType = (JSONObject) activityMessage.get(TYPE); if (activityMessageType.equals(ACTIVITY_TIME_UPDATE)) { JSONObject activityMessageTypeState = (JSONObject) activityMessage.get(ACTIVITY_STATE); if (activityMessageTypeState.get(RESPONSE_CURRENT_TIME) instanceof Double) { Double current_time = (Double) activityMessageTypeState.get(ACTIVITY_CURRENT_TIME); Double duration = (Double) activityMessageTypeState.get(ACTIVITY_DURATION); if (duration != null) { if (playbackListener != null) { playbackListener.updateDuration(playback, duration.intValue()); } } if (current_time != null) { if (playbackListener != null) { playbackListener.updateTime(playback, current_time.intValue()); } } } else { Long current_time = (Long) activityMessageTypeState.get(ACTIVITY_CURRENT_TIME); Double duration = (Double) activityMessageTypeState.get(ACTIVITY_DURATION); if (duration != null) { if (playbackListener != null) { playbackListener.updateDuration(playback, duration.intValue()); } } if (current_time != null) { if (playbackListener != null) { playbackListener.updateTime(playback, current_time.intValue()); } } } } } } } } catch (Exception e) { Log.e(LOG_TAG, "parse JSON", e); } } public void onError(Exception ex) { Log.d(LOG_TAG, "onError: ex" + ex); ex.printStackTrace(); started = false; closed = true; infoThread.interrupt(); } public void onOpen(ServerHandshake handshake) { Log.d(LOG_TAG, "onOpen: handshake" + handshake); started = true; closed = false; if (infoThread != null) { infoThread.interrupt(); } infoThread = new Thread(new Runnable() { public void run() { while (started && !closed) { try { if (gotStatus) { rampWebSocketClient.send("[\"ramp\",{\"type\":\"INFO\",\"cmd_id\":" + commandId + "}]"); commandId++; } try { Thread.sleep(1000); } catch (InterruptedException e) { } } catch (Exception e) { Log.e(LOG_TAG, "infoThread", e); } } } }); infoThread.start(); } public void onClose(int code, String reason, boolean remote) { Log.d(LOG_TAG, "onClose: code" + code + ", reason=" + reason + ", remote=" + remote); closed = true; started = false; infoThread.interrupt(); if (playbackListener != null) { playbackListener.updateTime(playback, 0); } } // Media playback controls public void play() { Log.d(LOG_TAG, "play: " + rampWebSocketClient); if (rampWebSocketClient == null) { String app = getCurrentApp(dialServer); Log.d(LOG_TAG, "play: currentApp=" + app); getWebSocket(app); } if (rampWebSocketClient != null) { rampWebSocketClient.send("[\"ramp\",{\"type\":\"PLAY\", \"cmd_id\":" + commandId + "}]"); commandId++; } } public void play(int position) { Log.d(LOG_TAG, "play: " + rampWebSocketClient); if (rampWebSocketClient == null) { String app = getCurrentApp(dialServer); Log.d(LOG_TAG, "play: currentApp=" + app); getWebSocket(app); } if (rampWebSocketClient != null) { rampWebSocketClient.send( "[\"ramp\",{\"type\":\"PLAY\", \"cmd_id\":" + commandId + ", \"position\":" + position + "}]"); commandId++; } } public void pause() { Log.d(LOG_TAG, "pause: " + rampWebSocketClient); if (rampWebSocketClient == null) { String app = getCurrentApp(dialServer); Log.d(LOG_TAG, "stop: currentApp=" + app); getWebSocket(app); } if (rampWebSocketClient != null) { rampWebSocketClient.send("[\"ramp\",{\"type\":\"STOP\", \"cmd_id\":" + commandId + "}]"); commandId++; } } public void stop() { // ChromeCast app stop behaves like pause /* * if (rampWebSocketClient != null) { * rampWebSocketClient.send("[\"ramp\",{\"type\":\"STOP\", \"cmd_id\":" * + commandId + "}]"); commandId++; } */ // Close the current app closeCurrentApp(dialServer); } public void info() { if (rampWebSocketClient != null) { rampWebSocketClient.send("[\"ramp\",{\"type\":\"INFO\", \"cmd_id\":" + commandId + "}]"); commandId++; } } // Load media public void load(String url) { Log.d(LOG_TAG, "load: " + rampWebSocketClient); if (rampWebSocketClient != null) { if (isChromeCast) { rampWebSocketClient.send( "[\"cv\",{\"type\":\"launch_service\",\"message\":{\"action\":\"launch\",\"activityType\":\"video_playback\",\"activityId\":\"" + activityId + "\",\"senderId\":\"" + senderId + "\",\"receiverId\":\"local:1\",\"disconnectPolicy\":\"stop\",\"initParams\":{\"mediaUrl\":\"" + url + "\",\"currentTime\":0,\"duration\":0,\"pause\":false,\"muted\":false,\"volume\":1}}}]"); } else { rampWebSocketClient.send("[\"ramp\",{\"title\":\"Video\",\"src\":\"" + url + "\",\"type\":\"LOAD\",\"cmd_id\":" + commandId + ",\"autoplay\":true}]"); commandId++; } } } public void volume(float value) { if (rampWebSocketClient != null) { // ["ramp",{"volume":0.5,"type":"VOLUME","cmd_id":6}] rampWebSocketClient.send( "[\"ramp\",{\"type\":\"VOLUME\", \"cmd_id\":" + commandId + ", \"volume\":" + value + "}]"); commandId++; } } // Web socket status public boolean isStarted() { return started; } public boolean isClosed() { return closed; } public void setDialServer(DialServer dialServer) { this.dialServer = dialServer; } }