ios开发进阶Android开发经验谈Android知识

iOS Airplay--Airtunes音乐播放在Androi

2017-07-03  本文已影响324人  RDuwan

在上一篇,我们让iOS设备通过AirTunes发现了Android设备链接
这一篇,我们将完成iOS设备通过AirTunes连接上Android设备。

三、实现iOS设备通过AirTunes连接上Android devices

final ServerBootstrap airTunesBootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(executorService, executorService));
        airTunesBootstrap.setOption("reuseAddress", true); //端口重用
        airTunesBootstrap.setOption("child.tcpNoDelay", true);
        airTunesBootstrap.setOption("child.keepAlive", true); //保持连接

添加到server配置

airTunesBootstrap.setPipelineFactory(new RaopRtsPipelineFactory());

        try {channelGroup.add(airTunesBootstrap.bind(new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), getRtspPort())));
        }
        catch (Exception e) {
            LOG.log(Level.SEVERE, "error",e);
            try {channelGroup.add(airTunesBootstrap.bind(new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), getAnotherRtspPort())));
            }
            catch (Exception e1) {
                LOG.log(Level.SEVERE, "error",e1);
            }
        }

给PiplineFactory添加rtsp decode和encode的handler,并添加Airtunes连接需要的另外三个核心handler。


public class RaopRtsPipelineFactory implements ChannelPipelineFactory {
    @Override
    public ChannelPipeline getPipeline() throws Exception {

        final ChannelPipeline pipeline = Channels.pipeline();
        //因为是管道 注意保持正确的顺序
        pipeline.addLast("decoder", new RtspRequestDecoder());//RtspRequestDecoder
        pipeline.addLast("encoder", new RtspResponseEncoder());//RtspResponseEncoder
        pipeline.addLast("challengeResponse", new RaopRtspChallengeResponseHandler(NetworkUtils.getInstance().getHardwareAddress()));
        pipeline.addLast("header", new RaopRtspHeaderHandler());
        pipeline.addLast("options", new RaopRtspOptionsHandler());

        return pipeline;
    }
}

A. RaopRtspChallengeResponseHandler详解:

@Override
    public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent evt)
        throws Exception
    {
        final HttpRequest req = (HttpRequest)evt.getMessage();

        synchronized(this) {
            if (req.containsHeader(HeaderChallenge)) {
                /* The challenge is sent without padding! */
                final byte[] challenge = Base64.decodeUnpadded(req.getHeader(HeaderChallenge));

                /* Verify that we got 16 bytes */
                if (challenge.length != 16)
                    throw new ProtocolException("Invalid Apple-Challenge header, " + challenge.length + " instead of 16 bytes");

                /* Remember challenge and local address.
                 * Both are required to compute the response
                 */
                m_challenge = challenge;
                m_localAddress = ((InetSocketAddress)ctx.getChannel().getLocalAddress()).getAddress();
            }
            else {
                /* Forget last challenge */
                m_challenge = null;
                m_localAddress = null;
            }
        }

        super.messageReceived(ctx, evt);
    }
@Override
    public void writeRequested(final ChannelHandlerContext ctx, final MessageEvent evt)
        throws Exception
    {
        final HttpResponse resp = (HttpResponse)evt.getMessage();

        synchronized(this) {
            if (m_challenge != null) {
                try {
                    /* Get appropriate response to challenge and
                     * add to the response base-64 encoded. XXX
                     */
                    final String sig = Base64.encodePadded(getSignature());

                    resp.setHeader(HeaderSignature, sig);
                }
                finally {
                    /* Forget last challenge */
                    m_challenge = null;
                    m_localAddress = null;
                }
            }
        }

        super.writeRequested(ctx, evt);
    }

B. RaopRtspHeaderHandler详解:

C. RaopRtspOptionsHandler详解:

public class RaopRtspOptionsHandler extends SimpleChannelUpstreamHandler {
    private static final String Options =
        RaopRtspMethods.ANNOUNCE.getName() + ", " +
        RaopRtspMethods.SETUP.getName() + ", " +
        RaopRtspMethods.RECORD.getName() + ", " +
        RaopRtspMethods.PAUSE.getName() + ", " +
        RaopRtspMethods.FLUSH.getName() + ", " +
        RtspMethods.TEARDOWN.getName() + ", " +
        RaopRtspMethods.OPTIONS.getName() + ", " +
        RaopRtspMethods.GET_PARAMETER.getName() + ", " +
        RaopRtspMethods.SET_PARAMETER.getName();

    @Override
    public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent evt) throws Exception {
        final HttpRequest req = (HttpRequest)evt.getMessage();

        if (RtspMethods.OPTIONS.equals(req.getMethod())) {
            final HttpResponse response = new DefaultHttpResponse(RtspVersions.RTSP_1_0, RtspResponseStatuses.OK);
            response.setHeader(RtspHeaders.Names.PUBLIC, Options);
            ctx.getChannel().write(response);
        }
        else {
            super.messageReceived(ctx, evt);
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读