Search code examples
javascriptandroidchromecastgoogle-castcustom-receiver

Send Base64 encoded image as string to Chromecast


The problem is to send local image from phone as encoded Base64 string to Chromecast. And decode it using my Custom Receiver. I was following this guide which is based on this project sample.

I suggest the problem might be in:

  1. Custom Receiver is not proper (I'm not strong in JS).
  2. Chromecast didn't load that Receiver (I don't know how to check that).
  3. Image was encoded wrong on device or decoded on Chromecast.

You see, it seems like I coded everithing right since the status of Chromecast when I send photo is:

 statusCode 0 (success), 
 application name: Default Media Receiver, 
 status: Ready To Cast, 
 sessionId: 34D6CE75-4798-4294-BF45-2F4701CE4782, 
 wasLaunched: true.

This is how I send image as String:

mCastManager.castImage(mCastManager.getEncodedImage(currentEntryPictureByPoint.getPath()));

Methods used:

public void castImage(String encodedImage)
{
    Log.d(TAG, "castImage()");
    String image_string = createJsonMessage(MessageType.image, encodedImage);
    sendMessage(image_string);
}

private static String createJsonMessage(MessageType type, String message)
{
    return String.format("{\"type\":\"%s\", \"data\":\"%s\"}", type.toString(), message);
}

/**
 * Convert Image to encoded String
 * */
public String getEncodedImage(String path){
    Bitmap bm = BitmapFactory.decodeFile(path);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); //bm is the bitmap object
    byte[] byteArrayImage = baos.toByteArray();

    String encodedImage = Base64.encodeToString(byteArrayImage, Base64.DEFAULT);

    return encodedImage;
}

/**
 * Send a text message to the receiver
 *
 * @param message
 */
private void sendMessage(String message) {
    if (mApiClient != null && mCustomImageChannel != null) {
        try {
            Cast.CastApi.sendMessage(mApiClient,
                    mCustomImageChannel.getNamespace(), message)
                    .setResultCallback(new ResultCallback<Status>() {
                        @Override
                        public void onResult(Status result) {
                            if (!result.isSuccess()) {
                                //ALWAYS REACHING HERE :(
                                Log.e(TAG, "Sending message failed");
                            }
                        }
                    });
        } catch (Exception e) {
            Log.e(TAG, "Exception while sending message", e);
        }
    } else {
        Toast.makeText(mContext, message, Toast.LENGTH_SHORT)
                .show();
    }
}

If the sending process is correct then the Receiver is wrong and don't know how to decode this message properly. The way I uploaded it (well, at least I think that its uploaded...)

  1. Registered new Custom Receiver on Google Cast Console and received Application ID.
  2. Created cast_receiver.js file. The code inside this file is supposed to decode Base64 string into image.
  3. Copied the code for Receiver from guide to .js file and changed NAMESPACE inside to my one: urn:x-cast:com.it.innovations.smartbus
  4. Uploaded file on Google Drive and modified its access visibility to full public
  5. Copied the link to file to URL field in Cast Console. This link is direct download of file.
  6. Restarted Chromecast. Seems like it tried to download something but not sure if succeed

If anyone faced this problem, please point me out what I am doing wrong. Appreciate any help.

P.S. tell if some more code needed...


Solution

  • I very strongly suggest to avoid using the sendMessage() for sending any large data set; those channels are meant to be used as control channels and not as a way to send a chunk of data. A much much simpler and more robust approach is to embed a tiny dumb web server in your local app (on the sender side) and "serve" your images to your chromecast. There is a number of ready-to-use embedded web servers that you can put in your app and requires almost no configuration; then you can serve all sorts of media, including images, to your chromecast with even the default or styled receiver.