壁に頭をぶつけています。動作しますが、動作しません。
はっきりさせておきますが、テストは LG Optimus G、Galaxy S4、および Lenovo タブレットですべて 4.1+ を実行しています。
私は各デバイスでサーバーを起動しています。各デバイスはポートで自分自身をブロードキャストしています。ユーザーが送信を押すと、サービスが解決され、サービスが失われていないすべてのデバイスで、スレッドが他のスレッドを起動してループします自分自身をブロードキャストしているサーバーに接続し、データを送信します。サーバーは着信接続を受け入れ、それをスレッドに渡し、再び開きます。
要約すると、すべてのデバイスがサーバーをブロードキャストしており、データが送信されると、すべての既知のサーバーがヒットするときに、すべてのデバイスが他のサーバーを認識して追跡する必要があります。
私の問題は、2/3 デバイスでは、デバイス自体との接続を一貫して確立できることです。
どちらの電話も、一度に 1 台だけが、もう一方の電話を認識しているようで、もう一方の電話に接続できます。つまり、Galaxy S4 はオプティマス G に挨拶できますが、オプティマス G はそれ自体にしか挨拶できません。
そのため、発見部分は信頼できないようで、それが私なのか、Android なのか、それともデバイスなのかわかりません。外の目が必要です。私はこれを理解しやすく考え抜かれた方法で展開しようとしました。私はネットワークの世界に謙虚な始まりを迎えたばかりであり、喜んで学びたいので、この問題に関する知識を持っている人からの助けに感謝します.誰か。
私の実装には少なくとも欠陥があるように見えるので、サービスを追跡または発見するためのより信頼できる方法が必要です。
高度な助けに感謝します。(私は、これが他のほとんどの Android エリアほど踏みにじられているエリアではないと思います。)
ここで初期化を行います。
/**initilize everything*/
private void buildNetwork()
{
Log.d(TAG, "buildNetwork");
networkHelper = new NetworkServiceDiscoveryHelper(this);
networkHelper.initializeNsd(this);
networkHelper.discoverServices();
connectionReceiver = new ConnectionReceiver(this, this);
// this next line launches the server thread which will obtain a socket
// to be used in the finishBuildingNetwork()
new Thread(connectionReceiver).start();
}
/** after the serversocket has been given a port we need to broadcast it*/
private void finishBuildingNetwork(int port)
{
Log.d(TAG, "finishBuildingNetwork");
networkHelper.registerService(port);
}
これは、共通NSDManager
ヘルパー クラスの若干変更された実装です。
public class NetworkServiceDiscoveryHelper
{
public static final String TAG = "NetworkServiceDiscoveryHelper";
public static final String KEY_DEVICE = "device";
Context mContext;
NsdManager mNsdManager;
NsdManager.ResolveListener mResolveListener;
NsdManager.DiscoveryListener mDiscoveryListener;
NsdManager.RegistrationListener mRegistrationListener;
public static final String SERVICE_TYPE = "_http._tcp.";
public String mServiceName = "BlurbChat";
NsdServiceInfo mService;
private DiscoveredDevicesManager deviceManager;
private NetworkDiscoveryHelperListener helperListener;
/**
*
* @param context
* - the activity context the service is to be attached to
*/
public NetworkServiceDiscoveryHelper(Context context)
{
mContext = context;
mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
deviceManager = new DiscoveredDevicesManager();
}
/**
* initialize the NetworkServiceDiscovery
*/
public void initializeNsd(NetworkDiscoveryHelperListener helperListener)
{
this.helperListener = helperListener;
initializeResolveListener();
initializeDiscoveryListener();
initializeRegistrationListener();
// mNsdManager.init(mContext.getMainLooper(), this);
}
private void initializeDiscoveryListener()
{
mDiscoveryListener = new NsdManager.DiscoveryListener()
{
@Override
public void onDiscoveryStarted(String regType)
{
Log.d(TAG, "Service discovery started");
helperListener.SERVICE_STARTED(regType);
}
@Override
public void onServiceFound(NsdServiceInfo service)
{
// A service was found! Do something with it.
Log.d(TAG, "Service discovery success" + service);
if (!service.getServiceType().equals(SERVICE_TYPE))
{
// Service type is the string containing the protocol and
// transport layer for this service.
Log.d(TAG, "Unknown Service Type: " + service.getServiceType());
}
else if (service.getServiceName().contains(mServiceName))
{
// we have found our service! we use .contains because if
// there are multiple device with the same service being
// broadcast they will appear with name + (index)
// Resolve a discovered service. An application can resolve
// a service right before establishing a connection to fetch
// the IP and port details on which to setup the connection.
Log.d(TAG, "Found My Service Type: " + service.getServiceType() + service.getServiceName());
helperListener.SERVICE_FOUND(service);
mNsdManager.resolveService(service, mResolveListener);
}
/***************************************************************
* Checking the service name isn't always necessary, and is only relevant if you want to connect to a specific application.
* For instance, the application might only want to connect to instances of itself running on other devices. However, if the
* application wants to connect to a network printer, it's enough to see that the service type is "_ipp._tcp".
******************************************************/
}
/**
* when we lose our service
*/
@Override
public void onServiceLost(NsdServiceInfo service)
{
// When the network service is no longer available.
Log.e(TAG, "service lost" + service);
// remove the service
if (deviceManager.removeDevice(service) != null)
{
helperListener.SERVIVCE_LOST(service);
}
}
/**
* when our service is stopped
*/
@Override
public void onDiscoveryStopped(String serviceType)
{
Log.i(TAG, "Discovery stopped: " + serviceType);
helperListener.DISCOVERY_STOPPED(serviceType);
}
@Override
public void onStartDiscoveryFailed(String serviceType, int errorCode)
{
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
helperListener.DISCOVERY_START_FAILED(serviceType, errorCode);
mNsdManager.stopServiceDiscovery(this);
}
@Override
public void onStopDiscoveryFailed(String serviceType, int errorCode)
{
helperListener.DISCOVERY_STOP_FAILED(serviceType, errorCode);
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
mNsdManager.stopServiceDiscovery(this);
}
};
}
private void initializeResolveListener()
{
mResolveListener = new NsdManager.ResolveListener()
{
@Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode)
{
// Called when the resolve fails. Use the error code to debug.
Log.e(TAG, "Resolve failed" + errorCode);
helperListener.RESOLVE_FAILED(serviceInfo, errorCode);
}
@Override
public void onServiceResolved(NsdServiceInfo serviceInfo)
{
Log.e(TAG, "Resolve Succeeded. " + serviceInfo);
if (serviceInfo.getServiceName().equals(mServiceName))
{
Log.d(TAG, "Same IP.");
return;
}
mService = serviceInfo;
DiscoveredDevice device = new DiscoveredDevice(mService.getPort(), mService.getHost(), mService.getServiceName(), mService.getServiceType());
deviceManager.addDevice(device);
helperListener.RESOLVE_SUCCESS(serviceInfo);
}
};
}
private void initializeRegistrationListener()
{
mRegistrationListener = new NsdManager.RegistrationListener()
{
@Override
public void onServiceRegistered(NsdServiceInfo serviceInfo)
{
mServiceName = serviceInfo.getServiceName();
helperListener.SERVICE_REGISTERED(serviceInfo);
}
@Override
public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode)
{
helperListener.SERVICE_REGISTRATION_FAILED(serviceInfo, errorCode);
}
@Override
public void onServiceUnregistered(NsdServiceInfo serviceInfo)
{
helperListener.SERVICE_UNREGISTERED(serviceInfo);
}
@Override
public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode)
{
helperListener.SERVICE_UNREGISTRATION_FAILED(serviceInfo, errorCode);
}
};
}
/**
* To be called after initialize()
*
* @param port
* - the port you would like to register/broadcast the service through.
*/
public void registerService(int port)
{
NsdServiceInfo serviceInfo = new NsdServiceInfo();
serviceInfo.setPort(port);
serviceInfo.setServiceName(mServiceName);
serviceInfo.setServiceType(SERVICE_TYPE);
mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);
}
/**
* Initiate service discovery to browse for instances of a service type. Service discovery consumes network bandwidth and will continue
* until the application calls stopServiceDiscovery(NsdManager.DiscoveryListener).
*/
public void discoverServices()
{
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
}
/**
* Stop service discovery initiated with discoverServices(String, int, NsdManager.DiscoveryListener). An active service discovery is
* notified to the application with onDiscoveryStarted(String) and it stays active until the application invokes a stop service
* discovery. A successful stop is notified to with a call to onDiscoveryStopped(String).
*/
public void stopDiscovery()
{
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
/**
*
* @return - A class representing service information for network service discovery
*/
public NsdServiceInfo getChosenServiceInfo()
{
return mService;
}
/**
* Unregister a service registered through registerService(NsdServiceInfo, int, NsdManager.RegistrationListener). A successful
* unregister is notified to the application with a call to onServiceUnregistered(NsdServiceInfo).
*/
public void tearDown()
{
if (mNsdManager != null)
{
try
{
mNsdManager.unregisterService(mRegistrationListener);
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
/**
*
* @return - the DiscoveredDevicesManager that contains all valid devices which have the appropriate service susally will call this
* after a msg of RESOLVE_SUCCESS
*/
public DiscoveredDevicesManager getDeviceManager()
{
return deviceManager;
}
}
そして最後に、これがサーバーの基礎です
@Override
public void run()
{
try
{
receiverSocket = new ServerSocket(0);
onPortObtained(receiverSocket.getLocalPort());
Log.d(TAG, "run");
while (broadcastConnection)
{
try
{
Socket newConnectionSocket = receiverSocket.accept();
onNewConnection(newConnectionSocket.getRemoteSocketAddress(), newConnectionSocket.getLocalSocketAddress());
// to clarify this line launches a function that starts threads to handle the socket.
recieveConnection(newConnectionSocket);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
編集:もう1つ、実行中にデバイスがランダムに再起動することがあります。アプリを実行している以外は、一般的な原因はありません。