mirror of
https://github.com/sifacaii/VlcJellyfin
synced 2025-05-26 06:20:20 -04:00
添加投屏
This commit is contained in:
parent
aeac3008b4
commit
ea0af079f2
@ -43,6 +43,7 @@ dependencies {
|
||||
implementation 'com.google.android.material:material:1.6.1'
|
||||
implementation 'com.lzy.net:okgo:3.0.4'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
|
@ -3,23 +3,29 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="org.sifacai.vlcjellyfin">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:name=".application"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:hardwareAccelerated="true"
|
||||
android:icon="@drawable/touchicon144"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@drawable/touchicon144"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/jellyfin"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:hardwareAccelerated="true"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".Dlna.DlnaControllActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".Dlna.DlnaActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".Ui.HomeActivity"
|
||||
android:exported="true">
|
||||
@ -41,7 +47,7 @@
|
||||
<activity
|
||||
android:name=".Player.VlcPlayerActivity"
|
||||
android:exported="false"
|
||||
android:theme="@style/Theme.AppCompat.NoActionBar"/>
|
||||
android:theme="@style/Theme.AppCompat.NoActionBar" />
|
||||
|
||||
<meta-data
|
||||
android:name="design_width_in_dp"
|
||||
|
@ -0,0 +1,47 @@
|
||||
package org.sifacai.vlcjellyfin.Dlna;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class AVTransport implements Parcelable {
|
||||
public String iconurl;
|
||||
public String moduleName;
|
||||
public String UDN;
|
||||
public String controlURL;
|
||||
public String eventSubURL;
|
||||
public String serviceId;
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int i) {
|
||||
parcel.writeString(iconurl);
|
||||
parcel.writeString(moduleName);
|
||||
parcel.writeString(UDN);
|
||||
parcel.writeString(controlURL);
|
||||
parcel.writeString(eventSubURL);
|
||||
parcel.writeString(serviceId);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<AVTransport> CREATOR = new Parcelable.Creator<AVTransport>(){
|
||||
@Override
|
||||
public AVTransport createFromParcel(Parcel parcel) {
|
||||
AVTransport av = new AVTransport();
|
||||
av.moduleName = parcel.readString();
|
||||
av.UDN = parcel.readString();
|
||||
av.serviceId = parcel.readString();
|
||||
av.controlURL = parcel.readString();
|
||||
av.eventSubURL = parcel.readString();
|
||||
av.iconurl = parcel.readString();
|
||||
return av;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AVTransport[] newArray(int i) {
|
||||
return new AVTransport[i];
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package org.sifacai.vlcjellyfin.Dlna;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class AVTransportAdapter extends RecyclerView.Adapter{
|
||||
private Context context;
|
||||
private ArrayList<AVTransport> avTransports;
|
||||
|
||||
public AVTransportAdapter(Context context) {
|
||||
this.context = context;
|
||||
this.avTransports = new ArrayList<>();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View ll = LayoutInflater.from(context).inflate(android.R.layout.simple_spinner_item, parent, false);
|
||||
return new RecyclerView.ViewHolder(ll) {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, @SuppressLint("RecyclerView") int position) {
|
||||
TextView tv = holder.itemView.findViewById(android.R.id.text1);
|
||||
tv.setText(avTransports.get(position).moduleName);
|
||||
tv.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if(listener != null){
|
||||
listener.onClick(avTransports.get(position));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addDevice(AVTransport avTransport) {
|
||||
boolean isexits = false;
|
||||
for(AVTransport av : avTransports){
|
||||
if(av.UDN.equals(avTransport.UDN)) isexits = true;
|
||||
}
|
||||
if(!isexits) {
|
||||
avTransports.add(avTransport);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return avTransports.size();
|
||||
}
|
||||
|
||||
private OnItemClickListener listener;
|
||||
|
||||
public void setOnItemClickListener(OnItemClickListener listener){
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public interface OnItemClickListener{
|
||||
void onClick(AVTransport avTransport);
|
||||
}
|
||||
}
|
303
app/src/main/java/org/sifacai/vlcjellyfin/Dlna/DlnaActivity.java
Normal file
303
app/src/main/java/org/sifacai/vlcjellyfin/Dlna/DlnaActivity.java
Normal file
@ -0,0 +1,303 @@
|
||||
package org.sifacai.vlcjellyfin.Dlna;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
import android.util.Xml;
|
||||
import android.view.View;
|
||||
|
||||
import com.owen.tvrecyclerview.widget.V7LinearLayoutManager;
|
||||
|
||||
import org.sifacai.vlcjellyfin.Component.JRecyclerView;
|
||||
import org.sifacai.vlcjellyfin.R;
|
||||
import org.sifacai.vlcjellyfin.Ui.BaseActivity;
|
||||
import org.sifacai.vlcjellyfin.Utils.JfClient;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class DlnaActivity extends BaseActivity {
|
||||
private String TAG = "Dlna播放器";
|
||||
|
||||
private JRecyclerView rv;
|
||||
private AVTransportAdapter avTransportAdapter;
|
||||
private MulticastSocket mSocket;
|
||||
private Thread listen_thread;
|
||||
|
||||
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 = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
super.handleMessage(msg);
|
||||
switch (msg.what) {
|
||||
case 1:
|
||||
Bundle b = msg.getData();
|
||||
AVTransport avt = new AVTransport();
|
||||
avt.moduleName = b.getString("moduleName");
|
||||
avt.serviceId = b.getString("serviceId");
|
||||
avt.UDN = b.getString("UDN");
|
||||
avt.controlURL = b.getString("controlURL");
|
||||
avt.eventSubURL = b.getString("eventSubURL");
|
||||
avt.iconurl = b.getString("iconurl");
|
||||
avTransportAdapter.addDevice(avt);
|
||||
Log.d(TAG, "handleMessage: " + avt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_dlna);
|
||||
getSupportActionBar().hide();
|
||||
|
||||
try {
|
||||
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() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
refresh();
|
||||
}
|
||||
});
|
||||
|
||||
rv = findViewById(R.id.mDeviceGridView);
|
||||
V7LinearLayoutManager layoutManager = new V7LinearLayoutManager(rv.getContext());
|
||||
layoutManager.setOrientation(V7LinearLayoutManager.VERTICAL);
|
||||
rv.setLayoutManager(layoutManager);
|
||||
avTransportAdapter = new AVTransportAdapter(this);
|
||||
rv.setAdapter(avTransportAdapter);
|
||||
avTransportAdapter.setOnItemClickListener(new AVTransportAdapter.OnItemClickListener() {
|
||||
@Override
|
||||
public void onClick(AVTransport avTransport) {
|
||||
Intent intent = new Intent(DlnaActivity.this, DlnaControllActivity.class);
|
||||
intent.putExtra("AVT",avTransport);
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
listen_thread.start();
|
||||
refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
listen_thread.interrupt();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void 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() {
|
||||
byte[] buff = new byte[1024];
|
||||
DatagramPacket packet = new DatagramPacket(buff, buff.length);
|
||||
while (mSocket != null) {
|
||||
try {
|
||||
mSocket.receive(packet);
|
||||
String clientIP = packet.getAddress().getHostAddress();
|
||||
int clientPort = packet.getPort();
|
||||
String data = new String(packet.getData()).trim();
|
||||
Log.d(TAG, "listen: " + clientIP + ":" + clientPort + ":" + data);
|
||||
ProgressNOTIFY(data);
|
||||
} catch (IOException | XmlPullParserException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
handler.post(listen_thread);
|
||||
}
|
||||
};
|
||||
|
||||
public void ProgressNOTIFY(String data) throws IOException, XmlPullParserException {
|
||||
String[] notify = data.split("\n");
|
||||
boolean isav = false;
|
||||
String location = "";
|
||||
for (String n : notify) {
|
||||
String[] ns = n.split(":", 2);
|
||||
//Log.d(TAG, "ProgressNOTIFY: " + String.join(",",ns));
|
||||
if (ns.length < 2) continue;
|
||||
else if (ns[0].equals("Location")) location = ns[1];
|
||||
else if (ns[0].equals("ST")) {
|
||||
String nsnt = ns[1].trim();
|
||||
if (nsnt.equals("upnp:rootdevice") || nsnt.indexOf("device:MediaRenderer") >= 0) {
|
||||
isav = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isav && !location.equals("")) {
|
||||
Log.d(TAG, "ProgressNOTIFY: " + location);
|
||||
String finalLocation = location;
|
||||
JfClient.SendGet(location,new JfClient.JJCallBack(){
|
||||
@Override
|
||||
public void onSuccess(String str) {
|
||||
Log.d(TAG, "onSuccess: " + 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 = ParseXML(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);
|
||||
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 (XmlPullParserException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public DlnaDevice ParseXML(String xml) throws XmlPullParserException, IOException {
|
||||
Log.d(TAG, "ParseXML: " + xml);
|
||||
XmlPullParser xmlPullParser = Xml.newPullParser();
|
||||
xmlPullParser.setInput(new StringReader(xml));
|
||||
|
||||
DlnaDevice device = new DlnaDevice();
|
||||
|
||||
int eventType = xmlPullParser.getEventType();
|
||||
String tagName = "";
|
||||
DlnaService service = null;
|
||||
String icon = "";
|
||||
while (eventType != XmlPullParser.END_DOCUMENT) {
|
||||
switch (eventType) {
|
||||
case XmlPullParser.START_TAG:
|
||||
tagName = xmlPullParser.getName().toLowerCase();
|
||||
if (tagName.equals("service")) service = new DlnaService();
|
||||
if (tagName.equals("icon")) icon = "";
|
||||
break;
|
||||
case XmlPullParser.TEXT:
|
||||
String value = xmlPullParser.getText();
|
||||
value = value == null ? "" : value.trim();
|
||||
if (tagName.equals("friendlyname")) device.friendlyName = value;
|
||||
if (tagName.equals("devicetype")) device.deviceType = value;
|
||||
if (tagName.equals("modelname")) device.modelName = value;
|
||||
if (tagName.equals("udn")) device.UDN = value;
|
||||
|
||||
if (tagName.equals("url")) icon = value;
|
||||
|
||||
if (tagName.equals("servicetype")) service.serviceType = value;
|
||||
if (tagName.equals("serviceid")) service.serviceId = value;
|
||||
if (tagName.equals("controlurl")) service.controlURL = value;
|
||||
if (tagName.equals("scpdurl")) service.SCPDURL = value;
|
||||
if (tagName.equals("eventsuburl")) service.eventSubURL = value;
|
||||
break;
|
||||
case XmlPullParser.END_TAG:
|
||||
if (xmlPullParser.getName().toLowerCase().equals("service")) device.DlnaServices.add(service);
|
||||
if (xmlPullParser.getName().toLowerCase().equals("icon")) device.icon.add(icon);
|
||||
break;
|
||||
}
|
||||
eventType = xmlPullParser.next();
|
||||
}
|
||||
return device;
|
||||
}
|
||||
|
||||
private String getRspXML(String action, HashMap<String, String> map) {
|
||||
String rsp = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
|
||||
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"" +
|
||||
" s:encodingstyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
|
||||
"<s:Body>" +
|
||||
"<u:" + action + "Response xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">";
|
||||
|
||||
if (map != null) {
|
||||
for (String key : map.keySet()) {
|
||||
rsp += "<" + key + ">" + map.get(key) + "</" + key + ">";
|
||||
}
|
||||
}
|
||||
|
||||
rsp += "</u:" + action + "Response>" +
|
||||
"</s:Body>" +
|
||||
"</s:Envelope>";
|
||||
|
||||
return rsp;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package org.sifacai.vlcjellyfin.Dlna;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import org.sifacai.vlcjellyfin.R;
|
||||
import org.sifacai.vlcjellyfin.Ui.BaseActivity;
|
||||
|
||||
public class DlnaControllActivity extends BaseActivity {
|
||||
String TAG = "DLNA控制器";
|
||||
|
||||
private AVTransport avTransport;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_dlna_controll);
|
||||
|
||||
avTransport = getIntent().getParcelableExtra("AVT");
|
||||
|
||||
Log.d(TAG, "onCreate: " + avTransport.controlURL);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package org.sifacai.vlcjellyfin.Dlna;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class DlnaDevice {
|
||||
public String friendlyName;
|
||||
public String modelName;
|
||||
public String deviceType;
|
||||
public String UDN;
|
||||
public String location;
|
||||
public ArrayList<String> icon = new ArrayList<>();
|
||||
public ArrayList<DlnaService> DlnaServices = new ArrayList<>();
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package org.sifacai.vlcjellyfin.Dlna;
|
||||
|
||||
public class DlnaService {
|
||||
public String serviceType;
|
||||
public String serviceId;
|
||||
public String controlURL;
|
||||
public String eventSubURL;
|
||||
public String SCPDURL;
|
||||
}
|
@ -3,6 +3,7 @@ package org.sifacai.vlcjellyfin.Dlna;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class Utils {
|
||||
|
@ -24,6 +24,7 @@ import org.sifacai.vlcjellyfin.Bean.UserData;
|
||||
import org.sifacai.vlcjellyfin.Component.JAdapter;
|
||||
import org.sifacai.vlcjellyfin.Component.JRecyclerView;
|
||||
import org.sifacai.vlcjellyfin.Component.JTAdapter;
|
||||
import org.sifacai.vlcjellyfin.Dlna.DlnaActivity;
|
||||
import org.sifacai.vlcjellyfin.Utils.JfClient;
|
||||
import org.sifacai.vlcjellyfin.R;
|
||||
import org.sifacai.vlcjellyfin.Utils.Utils;
|
||||
@ -377,8 +378,7 @@ public class DetailActivity extends BaseActivity implements JAdapter.OnItemClick
|
||||
public void toVlcPlayer() {
|
||||
Intent intent;
|
||||
if (JfClient.config.isDlnaPlayer()) {
|
||||
ShowToask("投屏播放");
|
||||
return;
|
||||
intent = new Intent(this, DlnaActivity.class);
|
||||
} else if (JfClient.config.isExtensionPlayer()) {
|
||||
String videourl = JfClient.playList.get(JfClient.playIndex).Url;
|
||||
Uri uri = Uri.parse(videourl);
|
||||
|
@ -666,6 +666,12 @@ public class JfClient {
|
||||
return response;
|
||||
}
|
||||
|
||||
public static String SendPost(String url,String body) throws IOException {
|
||||
String response = "";
|
||||
response = OkGo.<String>post(url).upBytes(body.getBytes()).execute().body().string();
|
||||
return response;
|
||||
}
|
||||
|
||||
public static class JJCallBack implements JCallBack {
|
||||
|
||||
@Override
|
||||
|
5
app/src/main/res/drawable/baseline_sync_white_42dp.xml
Normal file
5
app/src/main/res/drawable/baseline_sync_white_42dp.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="42dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="42dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,4L12,1L8,5l4,4L12,6c3.31,0 6,2.69 6,6 0,1.01 -0.25,1.97 -0.7,2.8l1.46,1.46C19.54,15.03 20,13.57 20,12c0,-4.42 -3.58,-8 -8,-8zM12,18c-3.31,0 -6,-2.69 -6,-6 0,-1.01 0.25,-1.97 0.7,-2.8L5.24,7.74C4.46,8.97 4,10.43 4,12c0,4.42 3.58,8 8,8v3l4,-4 -4,-4v3z"/>
|
||||
</vector>
|
43
app/src/main/res/layout/activity_dlna.xml
Normal file
43
app/src/main/res/layout/activity_dlna.xml
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".Dlna.DlnaActivity">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/dlna_tool_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:text="投屏播放"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="9"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/refresh"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="right"
|
||||
android:focusable="true"
|
||||
android:src="@drawable/baseline_sync_white_42dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<org.sifacai.vlcjellyfin.Component.JRecyclerView
|
||||
android:id="@+id/mDeviceGridView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:padding="@dimen/padding_border"
|
||||
app:tv_horizontalSpacingWithMargins="@dimen/vh_space_width"
|
||||
app:tv_selectedItemIsCentered="true"
|
||||
app:tv_verticalSpacingWithMargins="@dimen/vh_space_width" />
|
||||
|
||||
</LinearLayout>
|
9
app/src/main/res/layout/activity_dlna_controll.xml
Normal file
9
app/src/main/res/layout/activity_dlna_controll.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".Dlna.DlnaControllActivity">
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
Reference in New Issue
Block a user