¿Cómo obtener el enlace directo de video remoto de url incrustado dentro de una url en Android usando JSoup?
Había hecho la pregunta anteriormente sobre cómo recuperar la url incrustada para un archivo de vídeo y lo han hecho con éxito. Ahora tengo un problema diferente. La respuesta de json para una respuesta de webcam WUnderground API da la siguiente URL:
https://www.wunderground.com/webcams/cadot1/902/show.html
- Android java.lang.NoClassDefFoundError: org.jsoup.Jsoup
- Analizar una miniatura de YouTube en un iframe con Jsoup
- RoboSpice y Jsoup
- ¿Cuál es la mejor manera de raspar este código HTML para una aplicación para Android?
- JSoup no analiza la página de problemas conocidos de Android
Utilizando JSoup y por la respuesta a mi problema inicial pude conseguir este enlace incrustado:
https://www.wunderground.com/webcams/cadot1/902/video.html?month=11&year=2016&filename=current.mp4
Mientras intentaba "transmitir" el video de esa url a un VideoView, seguí recibiendo el error "no se puede reproducir video". Al mirar la fuente de ese enlace me di cuenta de que el archivo de vídeo que necesita ser jugado no se hace referencia en html, sino más bien javascript. ¿Cómo puedo obtener el enlace directo para el archivo de vídeo que se debe reproducir? ¿Usando JSoup u otro proceso?
La fuente de la URL https://www.wunderground.com/webcams/cadot1/902/video.html?month=11&year=2016&filename=current.mp4
muestra lo siguiente para el archivo de vídeo necesario dentro de un soporte <script>
:
Url: "//icons.wunderground.com/webcamcurrent/c/a/cadot1/902/current.mp4?e=1480377508"
Estoy usando JSoup para obtener la url incrustada para el video de la URL de respuesta como así:
private class VideoLink extends AsyncTask<Void, Void, Void> { String title; @Override protected void onPreExecute() { super.onPreExecute(); mProgressDialog.setTitle("JSOUP Test"); mProgressDialog.setMessage("Loading..."); mProgressDialog.setIndeterminate(false); mProgressDialog.show(); } @Override protected Void doInBackground(Void... params) { try { // for avoiding javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name System.setProperty("jsse.enableSNIExtension", "false"); // WARNING: do it only if security isn't important, otherwise you have // to follow this advices: http://stackoverflow.com/a/7745706/1363265 // Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager(){ public X509Certificate[] getAcceptedIssuers(){return null;} public void checkClientTrusted(X509Certificate[] certs, String authType){} public void checkServerTrusted(X509Certificate[] certs, String authType){} }}; // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { ; } // Connect to the web site Document doc = Jsoup.connect(TEST_URL).get(); Elements elements = doc.getElementsByClass("videoText"); // Get the html document title for (Element link : elements) { String linkHref = link.attr("href"); // linkHref contains something like video.html?month=11&year=2016&filename=current.mp4 // TODO check if linkHref ends with current.mp4 title = linkHref; } } catch (IOException e) { e.printStackTrace(); mProgressDialog.dismiss(); } return null; } @Override protected void onPostExecute(Void result) { // Set title into TextView resultTxt.setText(title); String resVid = TEST_URL; Log.d(TAG, "URL: " + resVid); Uri resUri = Uri.parse(resVid); try { // Start the MediaController MediaController mediacontroller = new MediaController( MainActivity.this); mediacontroller.setAnchorView(resultVidVw); // Get the URL from String VideoURL Uri video = Uri.parse(resVid); resultVidVw.setMediaController(mediacontroller); resultVidVw.setVideoURI(video); } catch (Exception e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } resultVidVw.requestFocus(); resultVidVw.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { // Close the progress bar and play the video public void onPrepared(MediaPlayer mp) { mProgressDialog.dismiss(); resultVidVw.start(); } }); } }
Tenga en cuenta que necesito hacer esto en cada JSONObject en la matriz de respuesta.
- Cómo llamar a Javascript __doPostBack de JSOUP
- Error al liberar APK con AsyncTask y Jsoup
- Utilice jsoup para extraer texto de la clase 'form' con datos de página variable
- Analizando HTML con Jsoup y eliminando spans con cierto estilo
- ¿Cómo conectarse vía HTTPS usando Jsoup?
- Jsoup.connect () que trabaja con Java, no con Android
- Cierre de la conexión Jsoup
- ¿Hay una manera de acelerar Jsoup.parse ()?
Así es como puede obtener el archivo:
( Aviso : la parte de extracción sólo funciona con el html actual del sitio y si eso cambia, puede que no funcione correctamente!)
String url = "https://www.wunderground.com/webcams/cadot1/902/video.html"; int timeout = 100 * 1000; // Extract video URL Document doc = Jsoup.connect(url).timeout(timeout).get(); Element script = doc.getElementById("inner-content") .getElementsByTag("script").last(); String content = script.data(); int indexOfUrl = content.indexOf("url"); int indexOfComma = content.indexOf(',', indexOfUrl); String videoUrl = "https:" + content.substring(indexOfUrl + 6, indexOfComma - 1); System.out.println(videoUrl);
[Salida: https://icons.wunderground.com/webcamcurrent/c/a/cadot1/902/current.mp4?e=1481246112
]
Ahora puede obtener el archivo especificando .ignoreContentType(true)
para evitar que org.jsoup.UnsupportedMimeTypeException
y .maxBodySize(0)
eliminen el límite en el tamaño del archivo.
// Get video file byte[] video = Jsoup.connect(videoUrl) .ignoreContentType(true).timeout(timeout).maxBodySize(0) .execute().bodyAsBytes();
No sé si puedes jugarlo en Android o no, pero creo que puedes guardarlo usando org.apache.commons.io.FileUtils
(lo probé en Java SE, pero no en el entorno de desarrollo de Android).
// Save video file org.apache.commons.io.FileUtils.writeByteArrayToFile(new File("test.mp4"), video);
- La aplicación ActiveAndroid se autoclama cuando se ejecuta en Gingerbread
- Prueba en vivo de Android LVL