Search code examples
androidtelevisionapple-tv

Connect SDK: Share Video file to Apple TV from Android


I use Connect SDK v v1.4.3 to connect android device to Apple tv I can share Audio and Photo file from my device by own WebServer (extend NanoHttpd) but when I try share Vidio file into TV I see Alert "downloading content fails" but in log all OK

05-15 22:49:54.764   31061-2326/com.example.sharemedia D/AirPlay﹕ [ 05-15 22:49:54.767 31061:31061 D/MediaHelper ]
    onSuccess:::line:520:::VIDEO PLAY

My Method

public void playVideo(String path) {
        String videoPath = path;
//        String videoPath = "http://10.0.1.66:8091/Download/Eminem%20-%20Guts%20Over%20Fear%20ft.%20Sia.mp4";
        String mimeType = "video/" + FilenameUtils.getExtension(path);
        Log.d("MediaHelper", "playVideo:::line:509:::" + mimeType);
        String title = "title";
        String description = "description";
        String icon = "";

        Log.d("MediaHelper", "playVideo:::line:515:::" + path);

        mediaPlayer.playMedia(videoPath, mimeType, title, description, icon, true, new MediaPlayer.LaunchListener() {

            public void onSuccess(MediaPlayer.MediaLaunchObject object) {
                Log.d("MediaHelper", "onSuccess:::line:520:::" + "VIDEO PLAY");

                launchSession = object.launchSession;
//                testResponse = new TestResponseObject(true, TestResponseObject.SuccessCode, TestResponseObject.Play_Video);
                mMediaControl = object.mediaControl;
                mPlaylistControl = object.playlistControl;

                stopUpdating();
                enableMedia();
                isPlaying = true;
            }

            @Override
            public void onError(ServiceCommandError error) {
                Log.d("MediaHelper", "onError:::line:534:::" + "Error playing Video");
                if (launchSession != null) {
                    launchSession.close(null);
                    launchSession = null;
//                    testResponse = new TestResponseObject(false, error.getCode(), error.getMessage());
                    stopUpdating();
                    disableMedia();
                    isPlaying = isPlayingImage = false;
                }
            }
        });
    }

also I try put my URL to the Connect-SDK-Android-API-Sampler but the problem did not solve

If I open my URL in browser (Chrome) Video is playing.

WebServer Method

@Override
    public Response serve(IHTTPSession session) {
        Method method = session.getMethod();
        switch (method) {
            case GET:

                String path = session.getUri().replace(Utils.getIPAddress(true) + ":" + port, "");
                //TODO refactoring

                String type = FilenameUtils.getExtension(path);
                String contentType = "";
                if (type.equals("jpg") || type.equals("jpeg") || type.equals("png") || type.equals("gif") || type.equals("tiff"))
                    contentType = "image/";
                else if (type.equals("mpeg") || type.equals("mp4") || type.equals("avi") || type.equals("quicktime"))
                    contentType = "video/";
                else if (type.equals("mp3") || type.equals("wav") || type.equals("acc") || type.equals("aiff"))
                    contentType = "audio/";

                else return new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "HTTPError: HTTP 8: BAD REQUEST 1");
                contentType += type;

                FileInputStream fis = null;
                try {
                    fis = new FileInputStream(Environment.getExternalStorageDirectory() + path);
                } catch (FileNotFoundException e) {

                    new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "HTTPError: HTTP 8: BAD REQUEST 2");
                }

                return new Response(Response.Status.OK, contentType, fis);

            default:
                return new Response(Response.Status.METHOD_NOT_ALLOWED, NanoHTTPD.MIME_PLAINTEXT, "HTTPError: HTTP 405: Method Not Allowed");
        }
    }

P.S. Sorry for my English.


Solution

  • The problem was in a response.

    I added "Content-Range" and "Content-Length" to Headers, and Video stream worked.

    private FileInputStream fileInputStream;
    
    @Override
    public Response serve(IHTTPSession session) {
    
    ....
    
    String range = session.getHeaders().get("range");
    if (range != null)
        return getVideoResponse(filePath, contentType, range);
    else
        .....
    
    ....
    
    }
    
    private Response getVideoResponse(String filePath, String mimeType, String rangeHdr) {
        File file = new File(filePath);
        String rangeValue = rangeHdr.trim().substring("bytes=".length());
        long fileLength = file.length();
        long start, end;
        if (rangeValue.startsWith("-")) {
            end = fileLength - 1;
            start = fileLength - 1 - Long.parseLong(rangeValue.substring("-".length()));
        } else {
            String[] range = rangeValue.split("-");
            start = Long.parseLong(range[0]);
            end = range.length > 1 ? Long.parseLong(range[1])
                    : fileLength - 1;
        }
        if (end > fileLength - 1) {
            end = fileLength - 1;
        }
        if (start <= end) {
            long contentLength = end - start + 1;
            try {
                cleanupStream();
                fileInputStream = new FileInputStream(file);
                fileInputStream.skip(start);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            Response response = new Response(Response.Status.PARTIAL_CONTENT, mimeType, fileInputStream);
            response.addHeader("Content-Length", contentLength + "");
            response.addHeader("Content-Range", "bytes " + start + "-" + end + "/" + fileLength);
            return response;
        } else {
            return new Response(Response.Status.RANGE_NOT_SATISFIABLE, NanoHTTPD.MIME_PLAINTEXT, rangeHdr);
        }
    }
    
    private voud cleanupStream() throws IOException {
        if (fileInputStream != null) 
            fileInputStream.close();
    }