mirror of
https://github.com/TeamVanced/VancedMicroG
synced 2024-10-15 01:09:38 +02:00
Support for DNS-SD cast discovery
This commit is contained in:
parent
2368bed54b
commit
477f7b2a15
2
extern/GmsApi
vendored
2
extern/GmsApi
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 5af21c0ff2777e61caba5d111991cbb165167793
|
Subproject commit 540d2922599af4d9c3ef0174b45ebbc875aafd65
|
@ -57,12 +57,12 @@ public class CastMediaRouteController extends MediaRouteProvider.RouteController
|
|||||||
private String routeId;
|
private String routeId;
|
||||||
private ChromeCast chromecast;
|
private ChromeCast chromecast;
|
||||||
|
|
||||||
public CastMediaRouteController(CastMediaRouteProvider provider, String routeId, ChromeCast chromecast) {
|
public CastMediaRouteController(CastMediaRouteProvider provider, String routeId, String address) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.routeId = routeId;
|
this.routeId = routeId;
|
||||||
this.chromecast = chromecast;
|
this.chromecast = new ChromeCast(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onControlRequest(Intent intent, MediaRouter.ControlRequestCallback callback) {
|
public boolean onControlRequest(Intent intent, MediaRouter.ControlRequestCallback callback) {
|
||||||
|
@ -19,6 +19,8 @@ package org.microg.gms.cast;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.net.nsd.NsdManager;
|
||||||
|
import android.net.nsd.NsdServiceInfo;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@ -32,70 +34,27 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.google.android.gms.common.images.WebImage;
|
import com.google.android.gms.common.images.WebImage;
|
||||||
import com.google.android.gms.cast.CastDevice;
|
import com.google.android.gms.cast.CastDevice;
|
||||||
|
import com.google.android.gms.cast.CastMediaControlIntent;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.lang.Thread;
|
import java.lang.Thread;
|
||||||
import java.lang.Runnable;
|
import java.lang.Runnable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import su.litvak.chromecast.api.v2.ChromeCast;
|
|
||||||
import su.litvak.chromecast.api.v2.ChromeCasts;
|
|
||||||
import su.litvak.chromecast.api.v2.Status;
|
|
||||||
import su.litvak.chromecast.api.v2.ChromeCastsListener;
|
|
||||||
|
|
||||||
public class CastMediaRouteProvider extends MediaRouteProvider {
|
public class CastMediaRouteProvider extends MediaRouteProvider {
|
||||||
private static final String TAG = CastMediaRouteProvider.class.getSimpleName();
|
private static final String TAG = CastMediaRouteProvider.class.getSimpleName();
|
||||||
|
|
||||||
private Map<String, ChromeCast> chromecasts = new HashMap<String, ChromeCast>();
|
private Map<String, MediaRouteDescriptor> routes = new HashMap<String, MediaRouteDescriptor>();
|
||||||
|
|
||||||
public CastMediaRouteProvider(Context context) {
|
private NsdManager mNsdManager;
|
||||||
super(context);
|
private NsdManager.DiscoveryListener mDiscoveryListener;
|
||||||
|
|
||||||
// TODO: Uncomment this to manually discover a chromecast on the local
|
|
||||||
// network. Discovery not yet implemented.
|
|
||||||
/*
|
|
||||||
InetAddress addr = null;
|
|
||||||
try {
|
|
||||||
addr = InetAddress.getByName("192.168.1.11");
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
Log.d(TAG, "Chromecast status exception getting host: " + e.getMessage());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
onChromeCastDiscovered(addr);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onChromeCastDiscovered(InetAddress address) {
|
|
||||||
ChromeCast chromecast = new ChromeCast(address.getHostAddress());
|
|
||||||
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
Status status = null;
|
|
||||||
try {
|
|
||||||
status = chromecast.getStatus();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Exception getting chromecast status: " + e.getMessage());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Handler mainHandler = new Handler(CastMediaRouteProvider.this.getContext().getMainLooper());
|
|
||||||
mainHandler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
String routeId = address.getHostAddress();
|
|
||||||
CastMediaRouteProvider.this.chromecasts.put(routeId, chromecast);
|
|
||||||
publishRoutes();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Mock control filters for chromecast; Will likely need to be
|
* TODO: Mock control filters for chromecast; Will likely need to be
|
||||||
@ -105,38 +64,92 @@ public class CastMediaRouteProvider extends MediaRouteProvider {
|
|||||||
static {
|
static {
|
||||||
IntentFilter f2 = new IntentFilter();
|
IntentFilter f2 = new IntentFilter();
|
||||||
f2.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
|
f2.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
|
||||||
|
f2.addCategory(CastMediaControlIntent.CATEGORY_CAST);
|
||||||
f2.addAction(MediaControlIntent.ACTION_PLAY);
|
f2.addAction(MediaControlIntent.ACTION_PLAY);
|
||||||
|
|
||||||
CONTROL_FILTERS = new ArrayList<IntentFilter>();
|
CONTROL_FILTERS = new ArrayList<IntentFilter>();
|
||||||
CONTROL_FILTERS.add(f2);
|
CONTROL_FILTERS.add(f2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public CastMediaRouteProvider(Context context) {
|
||||||
public void onDiscoveryRequestChanged(MediaRouteDiscoveryRequest request) {
|
super(context);
|
||||||
Log.d(TAG, "unimplemented Method: onDiscoveryRequestChanged");
|
|
||||||
|
mNsdManager = (NsdManager)context.getSystemService(Context.NSD_SERVICE);
|
||||||
|
|
||||||
|
mDiscoveryListener = new NsdManager.DiscoveryListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDiscoveryStarted(String regType) {
|
||||||
|
Log.d(TAG, "DiscoveryListener unimplemented Method: onDiscoveryStarted");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceFound(NsdServiceInfo service) {
|
||||||
|
mNsdManager.resolveService(service, new NsdManager.ResolveListener() {
|
||||||
|
@Override
|
||||||
|
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
|
||||||
|
Log.e(TAG, "DiscoveryListener unimplemented Method: Resolve failed" + errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceResolved(NsdServiceInfo serviceInfo) {
|
||||||
|
String name = serviceInfo.getServiceName();
|
||||||
|
InetAddress host = serviceInfo.getHost();
|
||||||
|
int port = serviceInfo.getPort();
|
||||||
|
try {
|
||||||
|
String id = new String(serviceInfo.getAttributes().get("id"), "UTF-8");
|
||||||
|
String deviceVersion = new String(serviceInfo.getAttributes().get("ve"), "UTF-8");
|
||||||
|
String friendlyName = new String(serviceInfo.getAttributes().get("fn"), "UTF-8");
|
||||||
|
String modelName = new String(serviceInfo.getAttributes().get("md"), "UTF-8");
|
||||||
|
String iconPath = new String(serviceInfo.getAttributes().get("ic"), "UTF-8");
|
||||||
|
int status = Integer.parseInt(new String(serviceInfo.getAttributes().get("st"), "UTF-8"));
|
||||||
|
|
||||||
|
onChromeCastDiscovered(id, name, host, port, deviceVersion, friendlyName, modelName, iconPath, status);
|
||||||
|
} catch (UnsupportedEncodingException ex) {
|
||||||
|
Log.e(TAG, "Error getting cast details from DNS-SD response", ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceLost(NsdServiceInfo service) {
|
||||||
|
Log.d(TAG, "DiscoveryListener unimplemented Method: onServiceLost" + service);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDiscoveryStopped(String serviceType) {
|
||||||
|
Log.i(TAG, "DiscoveryListener unimplemented Method: onDiscoveryStopped " + serviceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
|
||||||
|
Log.e(TAG, "DiscoveryListener unimplemented Method: onStartDiscoveryFailed: Error code:" + errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
|
||||||
|
Log.e(TAG, "DiscoveryListener unimplemented Method: onStopDiscoveryFailed: Error code:" + errorCode);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void onChromeCastDiscovered(
|
||||||
public RouteController onCreateRouteController(String routeId) {
|
String id, String name, InetAddress host, int port, String
|
||||||
ChromeCast chromecast = this.chromecasts.get(routeId);
|
deviceVersion, String friendlyName, String modelName, String
|
||||||
return new CastMediaRouteController(this, routeId, chromecast);
|
iconPath, int status) {
|
||||||
}
|
if (!this.routes.containsKey(id)) {
|
||||||
|
// TODO: Capabilities
|
||||||
|
int capabilities = CastDevice.CAPABILITY_VIDEO_OUT | CastDevice.CAPABILITY_AUDIO_OUT;
|
||||||
|
|
||||||
private void publishRoutes() {
|
|
||||||
MediaRouteProviderDescriptor.Builder builder = new MediaRouteProviderDescriptor.Builder();
|
|
||||||
for(Map.Entry<String, ChromeCast> entry : this.chromecasts.entrySet()) {
|
|
||||||
String routeId = entry.getKey();
|
|
||||||
ChromeCast chromecast = entry.getValue();
|
|
||||||
Bundle extras = new Bundle();
|
Bundle extras = new Bundle();
|
||||||
CastDevice castDevice = new CastDevice(
|
CastDevice castDevice = new CastDevice(id, name, host, port, deviceVersion, friendlyName, modelName, iconPath, status, capabilities);
|
||||||
routeId,
|
|
||||||
chromecast.getAddress()
|
|
||||||
);
|
|
||||||
castDevice.putInBundle(extras);
|
castDevice.putInBundle(extras);
|
||||||
builder.addRoute(new MediaRouteDescriptor.Builder(
|
this.routes.put(id, new MediaRouteDescriptor.Builder(
|
||||||
routeId,
|
id,
|
||||||
routeId)
|
friendlyName)
|
||||||
.setDescription("Chromecast")
|
.setDescription(modelName)
|
||||||
.addControlFilters(CONTROL_FILTERS)
|
.addControlFilters(CONTROL_FILTERS)
|
||||||
.setDeviceType(MediaRouter.RouteInfo.DEVICE_TYPE_TV)
|
.setDeviceType(MediaRouter.RouteInfo.DEVICE_TYPE_TV)
|
||||||
.setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
|
.setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
|
||||||
@ -149,6 +162,36 @@ public class CastMediaRouteProvider extends MediaRouteProvider {
|
|||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Handler mainHandler = new Handler(this.getContext().getMainLooper());
|
||||||
|
mainHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
publishRoutes();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDiscoveryRequestChanged(MediaRouteDiscoveryRequest request) {
|
||||||
|
if (request.isValid() && request.isActiveScan()) {
|
||||||
|
mNsdManager.discoverServices("_googlecast._tcp.", NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
|
||||||
|
} else {
|
||||||
|
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RouteController onCreateRouteController(String routeId) {
|
||||||
|
MediaRouteDescriptor descriptor = this.routes.get(routeId);
|
||||||
|
CastDevice castDevice = CastDevice.getFromBundle(descriptor.getExtras());
|
||||||
|
return new CastMediaRouteController(this, routeId, castDevice.getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void publishRoutes() {
|
||||||
|
MediaRouteProviderDescriptor.Builder builder = new MediaRouteProviderDescriptor.Builder();
|
||||||
|
for(MediaRouteDescriptor route : this.routes.values()) {
|
||||||
|
builder.addRoute(route);
|
||||||
|
}
|
||||||
this.setDescriptor(builder.build());
|
this.setDescriptor(builder.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user