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();
版权声明:本文为sonichty原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。