mirror of
https://github.com/sifacaii/VlcJellyfin
synced 2025-05-26 06:20:20 -04:00
修BUG
This commit is contained in:
parent
356dd2c1b3
commit
88a1917c40
@ -18,9 +18,9 @@ public class AVTransportAdapter extends RecyclerView.Adapter{
|
|||||||
private Context context;
|
private Context context;
|
||||||
private ArrayList<AVTransport> avTransports;
|
private ArrayList<AVTransport> avTransports;
|
||||||
|
|
||||||
public AVTransportAdapter(Context context) {
|
public AVTransportAdapter(Context context,ArrayList<AVTransport> avTransports) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.avTransports = new ArrayList<>();
|
this.avTransports = avTransports;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -0,0 +1,189 @@
|
|||||||
|
package org.sifacai.vlcjellyfin.Dlna;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.lzy.okgo.OkGo;
|
||||||
|
|
||||||
|
import org.sifacai.vlcjellyfin.Utils.JfClient;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.DatagramPacket;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.MulticastSocket;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
|
||||||
|
public class BroadCastThread extends Thread {
|
||||||
|
private String TAG = "广播线程";
|
||||||
|
|
||||||
|
public static final int TYPE_DEVICE = 1; //发现新设备
|
||||||
|
public static final int TYPE_NEW_DEVICE_ADDED = 2; //新加了新设备
|
||||||
|
public static final int TYPE_DEVICE_DEL = 3; //设备离线
|
||||||
|
public static final int TYPE_MSG = 9; //消息
|
||||||
|
|
||||||
|
public static final String GroupAddress = "239.255.255.250";
|
||||||
|
|
||||||
|
private byte[] NOTIFY_rootdevice = ("M-SEARCH * HTTP/1.1\n" +
|
||||||
|
"ST: upnp:rootdevice\n" +
|
||||||
|
"MX: 10\n" +
|
||||||
|
"MAN: \"ssdp:discover\"\n" +
|
||||||
|
"Content-Length: 0\n" +
|
||||||
|
"HOST: 239.255.255.250:1900").getBytes();
|
||||||
|
|
||||||
|
private byte[] NOTIFY_MediaRenderer = ("M-SEARCH * HTTP/1.1\n" +
|
||||||
|
"ST: urn:schemas-upnp-org:device:MediaRenderer:1\n" +
|
||||||
|
"MX: 10\n" +
|
||||||
|
"MAN: \"ssdp:discover\"\n" +
|
||||||
|
"Content-Length: 0\n" +
|
||||||
|
"HOST: 239.255.255.250:1900").getBytes();
|
||||||
|
|
||||||
|
private Handler handler;
|
||||||
|
private MulticastSocket mSocket;
|
||||||
|
private ArrayList<AVTransport> avTransports;
|
||||||
|
private boolean isStop = false;
|
||||||
|
|
||||||
|
public BroadCastThread() {
|
||||||
|
avTransports = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
mSocket = new MulticastSocket(1900);
|
||||||
|
mSocket.joinGroup(InetAddress.getByName(GroupAddress));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (mSocket != null && !isStop) {
|
||||||
|
listenr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetHandler(Handler handler) {
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<AVTransport> GetAVTransportArray() {
|
||||||
|
return avTransports;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送M-SEARCH
|
||||||
|
*/
|
||||||
|
public void refresh() {
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
DatagramPacket packet = new DatagramPacket(NOTIFY_rootdevice, NOTIFY_rootdevice.length);
|
||||||
|
try {
|
||||||
|
packet.setAddress(InetAddress.getByName(GroupAddress));
|
||||||
|
packet.setPort(1900);
|
||||||
|
mSocket.send(packet);
|
||||||
|
packet.setData(NOTIFY_MediaRenderer);
|
||||||
|
mSocket.send(packet);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听广播
|
||||||
|
*/
|
||||||
|
private void listenr() {
|
||||||
|
try {
|
||||||
|
byte[] buff = new byte[1024];
|
||||||
|
DatagramPacket packet = new DatagramPacket(buff, buff.length);
|
||||||
|
mSocket.receive(packet);
|
||||||
|
String clientIP = packet.getAddress().getHostAddress();
|
||||||
|
int clientPort = packet.getPort();
|
||||||
|
String data = new String(packet.getData()).trim();
|
||||||
|
ProgressNOTIFY(data);
|
||||||
|
} catch (IOException | XmlPullParserException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ProgressNOTIFY(String data) throws IOException, XmlPullParserException {
|
||||||
|
Log.d(TAG, "ProgressNOTIFY: " + data);
|
||||||
|
if (data.startsWith("M-SEARCH")) return;
|
||||||
|
HashMap<String, String> dh = DlnaDevice.parseNOTIFY(data);
|
||||||
|
if (isExitsOrByeBye(dh)) return;
|
||||||
|
boolean isav = DlnaDevice.isMediaRenderer(dh.get("nt"));
|
||||||
|
String location = dh.get("location");
|
||||||
|
if (location == null) location = "";
|
||||||
|
if (isav && !location.equals("")) {
|
||||||
|
String xmlstr = JfClient.SendGet(location);
|
||||||
|
if (xmlstr == null || xmlstr.equals("")) return;
|
||||||
|
findDevice(location, xmlstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void findDevice(String location, String xml) {
|
||||||
|
DlnaDevice device;
|
||||||
|
try {
|
||||||
|
device = XmlParser.parseX(xml);
|
||||||
|
for (int i = 0; i < device.DlnaServices.size(); i++) {
|
||||||
|
DlnaService ds = device.DlnaServices.get(i);
|
||||||
|
if (ds.serviceType.indexOf("service:AVTransport") > -1) {
|
||||||
|
int si = location.indexOf("/", 8);
|
||||||
|
String url = si > -1 ? location.substring(0, si) : location;
|
||||||
|
String moduleName = device.friendlyName.equals("") ? device.modelName : device.friendlyName;
|
||||||
|
AVTransport av = new AVTransport();
|
||||||
|
av.moduleName = moduleName;
|
||||||
|
av.serviceId = ds.serviceId;
|
||||||
|
av.UDN = device.UDN;
|
||||||
|
av.controlURL = url + (ds.controlURL.startsWith("/") ? ds.controlURL : "/" + ds.controlURL);
|
||||||
|
av.eventSubURL = url + (ds.eventSubURL.startsWith("/") ? ds.eventSubURL : "/" + ds.eventSubURL);
|
||||||
|
av.iconurl = device.icon.size() > 0 ? url + "/" + device.icon.get(0) : "";
|
||||||
|
avTransports.add(av);
|
||||||
|
if (handler != null) {
|
||||||
|
Message msg = new Message();
|
||||||
|
msg.what = TYPE_NEW_DEVICE_ADDED;
|
||||||
|
handler.sendMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (ParserConfigurationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (SAXException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否已存在或byebye
|
||||||
|
* @param dh
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isExitsOrByeBye(HashMap<String,String> dh) {
|
||||||
|
String USN = dh.get("usn");
|
||||||
|
String[] usns = USN.split("::");
|
||||||
|
if (usns.length < 2) return true;
|
||||||
|
for (AVTransport av : avTransports) {
|
||||||
|
if (usns[0].equals(av.UDN)) {
|
||||||
|
if(dh.get("nts")!=null && dh.get("nts").toLowerCase().indexOf("byebye") >= 0){
|
||||||
|
avTransports.remove(av);
|
||||||
|
Message msg = new Message();
|
||||||
|
msg.what = TYPE_DEVICE_DEL;
|
||||||
|
handler.sendMessage(msg);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop() {
|
||||||
|
isStop = true;
|
||||||
|
}
|
||||||
|
}
|
@ -28,42 +28,25 @@ public class DlnaActivity extends BaseActivity {
|
|||||||
|
|
||||||
private JRecyclerView rv;
|
private JRecyclerView rv;
|
||||||
private AVTransportAdapter avTransportAdapter;
|
private AVTransportAdapter avTransportAdapter;
|
||||||
private MulticastSocket mSocket;
|
|
||||||
private Thread listen_thread;
|
|
||||||
|
|
||||||
private byte[] NOTIFY_rootdevice = ("M-SEARCH * HTTP/1.1\n" +
|
BroadCastThread broadCastTheader = new BroadCastThread();
|
||||||
"ST: upnp:rootdevice\n" +
|
|
||||||
"MX: 10\n" +
|
|
||||||
"MAN: \"ssdp:discover\"\n" +
|
|
||||||
"Content-Length: 0\n" +
|
|
||||||
"HOST: 239.255.255.250:1900").getBytes();
|
|
||||||
|
|
||||||
private byte[] NOTIFY_MediaRenderer = ("M-SEARCH * HTTP/1.1\n" +
|
private Handler handler= new Handler() {
|
||||||
"ST: urn:schemas-upnp-org:device:MediaRenderer:1\n" +
|
|
||||||
"MX: 10\n" +
|
|
||||||
"MAN: \"ssdp:discover\"\n" +
|
|
||||||
"Content-Length: 0\n" +
|
|
||||||
"HOST: 239.255.255.250:1900").getBytes();
|
|
||||||
|
|
||||||
private Handler handler = new Handler() {
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
super.handleMessage(msg);
|
super.handleMessage(msg);
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case 1:
|
case BroadCastThread.TYPE_DEVICE:
|
||||||
Bundle b = msg.getData();
|
break;
|
||||||
AVTransport avt = new AVTransport();
|
case BroadCastThread.TYPE_NEW_DEVICE_ADDED:
|
||||||
avt.moduleName = b.getString("moduleName");
|
avTransportAdapter.notifyDataSetChanged();
|
||||||
avt.serviceId = b.getString("serviceId");
|
break;
|
||||||
avt.UDN = b.getString("UDN");
|
case BroadCastThread.TYPE_DEVICE_DEL:
|
||||||
avt.controlURL = b.getString("controlURL");
|
avTransportAdapter.notifyDataSetChanged();
|
||||||
avt.eventSubURL = b.getString("eventSubURL");
|
|
||||||
avt.iconurl = b.getString("iconurl");
|
|
||||||
avTransportAdapter.addDevice(avt);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@ -71,19 +54,12 @@ public class DlnaActivity extends BaseActivity {
|
|||||||
setContentView(R.layout.activity_dlna);
|
setContentView(R.layout.activity_dlna);
|
||||||
getSupportActionBar().hide();
|
getSupportActionBar().hide();
|
||||||
|
|
||||||
try {
|
broadCastTheader.SetHandler(handler);
|
||||||
mSocket = new MulticastSocket(1900);
|
|
||||||
mSocket.joinGroup(InetAddress.getByName("239.255.255.250"));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
listen_thread = new Thread(listen_Runnable);
|
|
||||||
|
|
||||||
findViewById(R.id.refresh).setOnClickListener(new View.OnClickListener() {
|
findViewById(R.id.refresh).setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
refresh();
|
broadCastTheader.refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -91,7 +67,7 @@ public class DlnaActivity extends BaseActivity {
|
|||||||
V7LinearLayoutManager layoutManager = new V7LinearLayoutManager(rv.getContext());
|
V7LinearLayoutManager layoutManager = new V7LinearLayoutManager(rv.getContext());
|
||||||
layoutManager.setOrientation(V7LinearLayoutManager.VERTICAL);
|
layoutManager.setOrientation(V7LinearLayoutManager.VERTICAL);
|
||||||
rv.setLayoutManager(layoutManager);
|
rv.setLayoutManager(layoutManager);
|
||||||
avTransportAdapter = new AVTransportAdapter(this);
|
avTransportAdapter = new AVTransportAdapter(this, broadCastTheader.GetAVTransportArray());
|
||||||
rv.setAdapter(avTransportAdapter);
|
rv.setAdapter(avTransportAdapter);
|
||||||
avTransportAdapter.setOnItemClickListener(new AVTransportAdapter.OnItemClickListener() {
|
avTransportAdapter.setOnItemClickListener(new AVTransportAdapter.OnItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -103,10 +79,10 @@ public class DlnaActivity extends BaseActivity {
|
|||||||
Controller.SetAVTransportURI(avTransport.controlURL, vurl, new JfClient.JJCallBack() {
|
Controller.SetAVTransportURI(avTransport.controlURL, vurl, new JfClient.JJCallBack() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(String str) {
|
public void onSuccess(String str) {
|
||||||
Controller.GetMediaInfo(avTransport.controlURL,new JfClient.JJCallBack(){
|
Controller.GetMediaInfo(avTransport.controlURL, new JfClient.JJCallBack() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(String str) {
|
public void onSuccess(String str) {
|
||||||
Controller.Play(avTransport.controlURL,new JfClient.JJCallBack(){
|
Controller.Play(avTransport.controlURL, new JfClient.JJCallBack() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(String str) {
|
public void onSuccess(String str) {
|
||||||
ShowToask("已发送!");
|
ShowToask("已发送!");
|
||||||
@ -140,19 +116,18 @@ public class DlnaActivity extends BaseActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
if (!listen_thread.isAlive()) listen_thread.start();
|
broadCastTheader.start();
|
||||||
refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
listen_thread.interrupt();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
|
broadCastTheader.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -160,99 +135,4 @@ public class DlnaActivity extends BaseActivity {
|
|||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 刷新设备
|
|
||||||
*/
|
|
||||||
private void refresh() {
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
DatagramPacket packet = new DatagramPacket(NOTIFY_rootdevice, NOTIFY_rootdevice.length);
|
|
||||||
try {
|
|
||||||
packet.setAddress(InetAddress.getByName("239.255.255.250"));
|
|
||||||
packet.setPort(1900);
|
|
||||||
mSocket.send(packet);
|
|
||||||
packet.setData(NOTIFY_MediaRenderer);
|
|
||||||
mSocket.send(packet);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Runnable listen_Runnable = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
while (mSocket != null) {
|
|
||||||
try {
|
|
||||||
byte[] buff = new byte[1024];
|
|
||||||
DatagramPacket packet = new DatagramPacket(buff, buff.length);
|
|
||||||
mSocket.receive(packet);
|
|
||||||
String clientIP = packet.getAddress().getHostAddress();
|
|
||||||
int clientPort = packet.getPort();
|
|
||||||
String data = new String(packet.getData()).trim();
|
|
||||||
ProgressNOTIFY(data);
|
|
||||||
} catch (IOException | XmlPullParserException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handler.post(listen_thread);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public void ProgressNOTIFY(String data) throws IOException, XmlPullParserException {
|
|
||||||
//Log.d(TAG, "ProgressNOTIFY: " + data);
|
|
||||||
if(data.startsWith("M-SEARCH")) return;
|
|
||||||
HashMap<String,String> dh = DlnaDevice.parseNOTIFY(data);
|
|
||||||
boolean isav = DlnaDevice.isMediaRenderer(dh.get("nt"));
|
|
||||||
String location = dh.get("location");
|
|
||||||
if(location == null) location = "";
|
|
||||||
if (isav && !location.equals("")) {
|
|
||||||
String finalLocation = location;
|
|
||||||
JfClient.SendGet(location, new JfClient.JJCallBack() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(String str) {
|
|
||||||
findDevice(finalLocation, str);
|
|
||||||
}
|
|
||||||
}, new JfClient.JJCallBack() {
|
|
||||||
@Override
|
|
||||||
public void onError(String str) {
|
|
||||||
ShowToask(str);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void findDevice(String location, String xml) {
|
|
||||||
DlnaDevice device;
|
|
||||||
try {
|
|
||||||
device = XmlParser.parseX(xml);
|
|
||||||
for (int i = 0; i < device.DlnaServices.size(); i++) {
|
|
||||||
DlnaService ds = device.DlnaServices.get(i);
|
|
||||||
if (ds.serviceType.indexOf("service:AVTransport") > -1) {
|
|
||||||
int si = location.indexOf("/", 8);
|
|
||||||
String url = si > -1 ? location.substring(0, si) : location;
|
|
||||||
String moduleName = device.friendlyName.equals("") ? device.modelName : device.friendlyName;
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putString("moduleName", moduleName);
|
|
||||||
bundle.putString("UDN", device.UDN);
|
|
||||||
bundle.putString("serviceId", ds.serviceId);
|
|
||||||
bundle.putString("controlURL", url + (ds.controlURL.startsWith("/") ? ds.controlURL : "/" + ds.controlURL));
|
|
||||||
bundle.putString("eventSubURL", url + "/" + ds.eventSubURL);
|
|
||||||
bundle.putString("iconurl", device.icon.size() > 0 ? url + "/" + device.icon.get(0) : "");
|
|
||||||
Message msg = new Message();
|
|
||||||
msg.what = 1;
|
|
||||||
msg.setData(bundle);
|
|
||||||
handler.sendMessage(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} catch (ParserConfigurationException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} catch (SAXException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user