Chromecast 使用自定义接收器投射 HTML 对象

Chromecast cast HTML object using custom receiver

我正在开发一个 Android 应用程序,我需要将一个 PDF 文件发送到 Chromecast,所以我决定使用一个 PDF 解码库,其中 return 一个 HTML 对象。

//Load Images:
private void pdfLoadImages(final byte[] data)
{
    try
    {
        // run async
        new AsyncTask<Void, Void, String>()
        {
            // create and show a progress dialog
            ProgressDialog progressDialog = ProgressDialog.show(Prueba_PDF.this, "", "Opening...");

            @Override
            protected void onPostExecute(String html)
            {
                //after async close progress dialog
                progressDialog.dismiss();
                //load the html in the webview
                wv.loadDataWithBaseURL("", html, "text/html","UTF-8", "");
            }

            @Override
            protected String doInBackground(Void... params)
            {
                try
                {
                    //create pdf document object from bytes
                    ByteBuffer bb = ByteBuffer.NEW(data);
                    PDFFile pdf = new PDFFile(bb);
                    //Get the first page from the pdf doc
                    PDFPage PDFpage = pdf.getPage(1, true);
                    //create a scaling value according to the WebView Width
                    final float scale = ViewSize / PDFpage.getWidth() * 0.95f;
                    //convert the page into a bitmap with a scaling value
                    Bitmap page = PDFpage.getImage((int)(PDFpage.getWidth() * scale), (int)(PDFpage.getHeight() * scale), null, true, true);
                    //save the bitmap to a byte array
                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    page.compress(Bitmap.CompressFormat.PNG, 100, stream);
                    byte[] byteArray = stream.toByteArray();
                    stream.reset();
                    //convert the byte array to a base64 string
                    String base64 = Base64.encodeToString(byteArray, Base64.NO_WRAP);
                    //create the html + add the first image to the html
                    String html = "<!DOCTYPE html><html><body bgcolor=\"#b4b4b4\"><img src=\"data:image/png;base64,"+base64+"\" hspace=10 vspace=10><br>";
                    //loop though the rest of the pages and repeat the above
                    for(int i = 2; i <= pdf.getNumPages(); i++)
                    {
                        PDFpage = pdf.getPage(i, true);
                        page = PDFpage.getImage((int)(PDFpage.getWidth() * scale), (int)(PDFpage.getHeight() * scale), null, true, true);
                        page.compress(Bitmap.CompressFormat.PNG, 100, stream);
                        byteArray = stream.toByteArray();
                        stream.reset();
                        base64 = Base64.encodeToString(byteArray, Base64.NO_WRAP);
                        html += "<img src=\"data:image/png;base64,"+base64+"\" hspace=10 vspace=10><br>";
                    }
                    stream.close();
                    html += "</body></html>";
                    return html;

                }
                catch (Exception e)
                {
                    Log.d("error", e.toString());
                }
                return null;
            }
        }.execute();
        System.gc();// run GC
    }
    catch (Exception e)
    {
        Log.d("error", e.toString());
    }
}

是否可以使用 sendMessage() 方法将 HTML 对象发送到 Chromecast,以便我可以在电视上显示转换后的 PDF 文件?我应该将 message 参数更改为我的 html 对象吗?

private void sendMessage(String message) {
    if (apiClient != null && mHelloWorldChannel != null) {
        try {
            Cast.CastApi.sendMessage(apiClient, mHelloWorldChannel.getNamespace(), message)
                    .setResultCallback(
                            new ResultCallback<Status>() {
                                @Override
                                public void onResult(Status result) {
                                    if (!result.isSuccess()) {
                                        Log.e(TAG, "Sending message failed");
                                    }
                                }
                            });
        } catch (Exception e) {
            Log.e(TAG, "Exception while sending message", e);
        }
    }
}

我正在为 Android 使用来自 CastHelloText 应用程序的自定义接收器,但恐怕这不符合我的需要。

<!--
Copyright (C) 2014 Google Inc. All Rights Reserved.

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.
-->
<!DOCTYPE html>
<html>
  <head>
<style type="text/css">
  body {
    overflow:hidden;
  }
  div{
    height:720PX;
    width:1280PX;
    text-align:center;
    border:0px solid silver;
    display: table-cell;
    vertical-align:middle;
    color:#FFFFFF;
    background-color:#000000;
    font-weight:bold;
    font-family:Verdana, Geneva, sans-serif;
    font-size:40px;
}
</style>
<title>Cast Hello Text</title>
  </head>
  <body>
<DIV id="message">Talk to me</DIV>
<script type="text/javascript" src="//www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js"></script>
<script type="text/javascript">
  window.onload = function() {
    cast.receiver.logger.setLevelValue(0);
    window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
    console.log('Starting Receiver Manager');

    // handler for the 'ready' event
    castReceiverManager.onReady = function(event) {
      console.log('Received Ready event: ' + JSON.stringify(event.data));
      window.castReceiverManager.setApplicationState("Application status is ready...");
    };

    // handler for 'senderconnected' event
    castReceiverManager.onSenderConnected = function(event) {
      console.log('Received Sender Connected event: ' + event.data);
      console.log(window.castReceiverManager.getSender(event.data).userAgent);
    };

    // handler for 'senderdisconnected' event
    castReceiverManager.onSenderDisconnected = function(event) {
      console.log('Received Sender Disconnected event: ' + event.data);
      if (window.castReceiverManager.getSenders().length == 0) {
        window.close();
      }
    };

    // handler for 'systemvolumechanged' event
    castReceiverManager.onSystemVolumeChanged = function(event) {
      console.log('Received System Volume Changed event: ' + event.data['level'] + ' ' +
          event.data['muted']);
    };

    // create a CastMessageBus to handle messages for a custom namespace
    window.messageBus =
      window.castReceiverManager.getCastMessageBus(
          'urn:x-cast:com.google.cast.sample.helloworld');

    // handler for the CastMessageBus message event
    window.messageBus.onMessage = function(event) {
      console.log('Message [' + event.senderId + ']: ' + event.data);
      // display the message from the sender
      displayText(event.data);
      // inform all senders on the CastMessageBus of the incoming message event
      // sender message listener will be invoked
      window.messageBus.send(event.senderId, event.data);
    }

    // initialize the CastReceiverManager with an application status message
    window.castReceiverManager.start({statusText: "Application is starting"});
    console.log('Receiver Manager started');
  };

  // utility function to display the text message in the input field
  function displayText(text) {
    console.log(text);
    document.getElementById("message").innerHTML=text;
    window.castReceiverManager.setApplicationState(text);
  };
</script>

由于 pdfLoadImages 方法也 return 将 PDF 页面作为图像,这样发送 PDF 文件会更容易吗?

这是Supported Media for Google Cast。此页面没有提及任何有关投射 HTML 内容的内容,但我知道一些支持 PDF 文件的投射应用程序执行以下操作:

  • 将 PDF 文件转换为 JPEG(JPEDAL, PDFOne...)
  • 投射 JPEG 文件(您有大量关于如何操作的教程和示例)

没有明确的方法可以将 HTML 发送到 Cast 设备。有一种方法可以将文本消息发送到 Cast 设备,但该方法专为短消息而设计。您不应使用它向 Cast 设备发送任何其他内容。

接收方可以使用 JavaScript 将 HTML 从 URL 动态加载到 DOM 中。这将像在桌面浏览器上包含一个框架一样工作,但您必须在 Web 服务器上托管 HTML。您可以在移动设备上安装网络服务器,但您应该考虑性能和安全问题。

Chromecast 设备的资源有限,您不应发送任何可能需要大量内存或繁重 CPU 处理的内容。要显示 PDF,您可能需要考虑使用 Remote Display API。您必须在移动设备上呈现 PDF,然后 Cast 协议会在电视上呈现视图。

我认为您应该在自定义接收器 html 代码上使用 PDFJs。然后从您的发件人处向 load/scroll/page change 发送一些指令。我已经为我的一个应用程序要求做了同样的事情。