Android 投屏: 发现和发送

  • Post author:
  • Post category:其他


Qt:

投屏的发现和发送_海天鹰-CSDN博客

做好一部分,就忍不住做安卓版,入门难,找对资料才是王道。


SSDP协议的Android实现以及使用 – yxwkaifa – 博客园

SSDP他用了4个类,看得我头晕眼花,改一改,一个都不要!

一.MulticastSocket 的设置和发收

package com.hty.dlna;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.method.ScrollingMovementMethod;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class MainActivity extends Activity {

    TextView textView;
    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView);
        textView.setMovementMethod(ScrollingMovementMethod.getInstance());
        button = findViewById(R.id.button);
        button.setOnClickListener(new MyOnClickListener());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(0, 0, 0, "投屏");
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int item_id = item.getItemId();
        switch (item_id) {
            case 0:
                textView.setText("");
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        discover();
                    }
                }).start();
                break;
        }
        return true;
    }

    class MyOnClickListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.button:
                    textView.setText("");
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            discover();
                        }
                    }).start();
                    break;
            }
        }
    }

    void discover() {
        String s = "M-SEARCH * HTTP/1.1\r\n"
                + "HOST: 239.255.255.250:1900\r\n"
                + "MAN: \"ssdp:discover\"\r\n"
                + "ST: urn:schemas-upnp-org:service:AVTransport:1\r\n" //投屏
                + "MX: 3\r\n"
                + "\r\n";

        try  {
            MulticastSocket socket = new MulticastSocket(5800);
            InetAddress address = InetAddress.getByName("239.255.255.250");
            socket.joinGroup(address);
            DatagramPacket DP = new DatagramPacket(s.getBytes(), s.length(), address, 1900);
            socket.send(DP);
            Message message = new Message();
            message.what = 0;
            message.obj = "发送:\n" + s;
            handler.sendMessage(message);

            while (true) {
                byte[] buf = new byte[1024];
                DP = new DatagramPacket(buf, buf.length);
                socket.receive(DP);
                String IP = DP.getAddress().toString();
                int port = DP.getPort();
                s = new String(DP.getData());
                message = new Message();
                message.what = 0;
                message.obj = "接收:" + IP + ":" + port + "\n" + s;
                handler.sendMessage(message);
            }
        } catch (Exception e) {
            Message message = new Message();
            message.what = 0;
            message.obj = e.toString();
            handler.sendMessage(message);
        }
    }

    @SuppressLint("HandlerLeak")
    Handler handler = new Handler(Looper.getMainLooper()) {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0:
                    String s = (String) msg.obj;
                    textView.append(s);
                    break;
            }
        }
    };

}

二、解析XML,获取服务,推送网址

package com.hty.dlna;

import android.util.Log;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class DLNAClient {

    String url="", scheme="", IP="", port="", description="", friendlyName="", responseData="";
    List<Map> list_service = new ArrayList<>();

    public DLNAClient(String s) {
        for (String l: s.split("\r\n")) {
            if (l.toUpperCase().startsWith("LOCATION:")) {
                url = l.substring(9).trim();
                Log.e(Thread.currentThread().getStackTrace()[2] + "", url);
                scheme = url.substring(0, url.indexOf("://") + 3);
                l = url.substring(url.indexOf("://") + 3);
                Log.e(Thread.currentThread().getStackTrace()[2] + "", l);
                IP = l.substring(0, l.indexOf(":"));
                port = l.substring(l.indexOf(":") + 1, l.indexOf("/"));
                description = l.substring(l.indexOf("/") + 1);
                Log.e(Thread.currentThread().getStackTrace()[2] + "", scheme + " , " + IP + " , " + port + " , " + description);
                getDescription(url);
            }
        }

    }

    void getDescription(String surl) {
        try {
            URL url = new URL(surl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            InputStream IS = conn.getInputStream();
            InputStreamReader ISR = new InputStreamReader(IS);
            BufferedReader BR = new BufferedReader(ISR);
            String inputLine;
            while ((inputLine = BR.readLine()) != null) {
                responseData += inputLine + "\n";
            }
            //Log.e(Thread.currentThread().getStackTrace()[2] + "", "responseText:\n" + responseData);
            DocumentBuilderFactory DBF = DocumentBuilderFactory.newInstance();
            DocumentBuilder DB = DBF.newDocumentBuilder();
            Document doc = DB.parse(new ByteArrayInputStream(responseData.getBytes()));
            friendlyName = doc.getElementsByTagName("friendlyName").item(0).getFirstChild().getNodeValue();
            Log.e(Thread.currentThread().getStackTrace()[2] + "", friendlyName);
            NodeList NL = doc.getElementsByTagName("service");
            for (int i=0; i<NL.getLength(); i++) {
                NodeList NL1 = NL.item(i).getChildNodes();
                Map map = new HashMap();
                for (int j=0; j<NL1.getLength(); j++) {
                    Node node = NL1.item(j);
                    if (node.getFirstChild() != null) {
                        map.put(node.getNodeName(), node.getFirstChild().getNodeValue());
                        //Log.e(Thread.currentThread().getStackTrace()[2] + "", map.toString());
                    }
                }
                list_service.add(map);
            }
            //Log.e(Thread.currentThread().getStackTrace()[2] + "", list_service.toString());
        } catch (Exception e){
            Log.e(Thread.currentThread().getStackTrace()[2] + "", e.toString());
        }
    }

    String uploadFileToPlay(String controlURL, String UrlToPlay) {
        String XML = "<?xml version=\"1.0\"?>\n"
                +"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
                +"<SOAP-ENV:Body>\n"
                +"<u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">\n"
                +"<InstanceID>0</InstanceID>\n";
        XML += "<CurrentURI>" + UrlToPlay + "</CurrentURI>\n";
        XML += "<CurrentURIMetaData></CurrentURIMetaData>\n";
        XML += "</u:SetAVTransportURI>\n";
        XML += "</SOAP-ENV:Body>\n"
                +"</SOAP-ENV:Envelope>\n";
        String surl = scheme + IP + ":" + port;
        if (!controlURL.startsWith("/"))
            surl += "/";
        surl += controlURL;
        Log.e(Thread.currentThread().getStackTrace()[2] + "", surl);
        return post(surl, XML);
    }

    String post(String surl, String s) {
        String result = "";
        PrintWriter out = null;
        BufferedReader in = null;
        try {
            URL url = new URL(surl);
            URLConnection conn = url.openConnection();
            conn.setRequestProperty("Content-Type", "text/xml; charset=\"utf-8\"");
            conn.setRequestProperty("SOAPAction", "urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(s);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line + "\n";
            }
        } catch (Exception e) {
            return e.toString();
        } finally {
            try {
                if (out != null){
                    out.close();
                }
                if(in != null){
                    in.close();
                }
            } catch (Exception e) {
                return e.toString();
            }
        }
        return result;
    }

}

MainActivity.java 的接口

String items[] = new String[list_client.size()];
for (int i=0; i<list_client.size(); i++) {
    items[i] = list_client.get(i).friendlyName;
}
AlertDialog.Builder ADB = new AlertDialog.Builder(MainActivity.this);
ADB.setTitle("选择投屏设备");
ADB.setItems(items, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        DLNAClient client = list_client.get(which);
        for (int i=0; i<client.list_service.size(); i++) {
            Map map = client.list_service.get(i);
            //Log.e(Thread.currentThread().getStackTrace()[2] + "", map.toString());
            final String controlURL;
            //Log.e(Thread.currentThread().getStackTrace()[2] + "", map.get("serviceType") + " , " + map.get("controlURL"));
            if (map.get("serviceType").toString().equals("urn:schemas-upnp-org:service:AVTransport:1")) {
                controlURL = map.get("controlURL").toString();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        String s = client.uploadFileToPlay(controlURL, editText.getText().toString());
                        Message message = new Message();
                        message.what = 0;
                        message.obj = "投屏响应:\n" + s;
                        handler.sendMessage(message);
                    }
                }).start();
                break;
            }
        }
    }
});
ADB.show();

源码:

sonichy/HTYDLNA_Android



版权声明:本文为sonichty原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。