WifiP2Pサービス検出が期待どおりに動作していません。 DNSSDリスナーが常に呼び出されるとは限らないため、同じアプリを実行している近くのデバイスの手がかりがないという断続的な問題が発生しています。私は次の2つのAPIを使用しています。1つは他のデバイスによって検出されるサービスを登録するためのもので、もう1つは他のデバイスで実行されている近くのサービスを検出するためのものです。ここで何か間違ったことをしているのか、他のAndroid API呼び出しの特定のシーケンスがあり、これらのAPIを呼び出す前に、リスナーが常に呼び出されるようにする必要があるかどうか)登録された新しいサービス、またはAPIを呼び出してローカルサービスを検出する前にサービスが登録されている場合でも。
ローカルサービスを登録するためのAPI:
private void registerService() {
Map<String, String> values = new HashMap<String, String>();
values.put("name", "Steve");
values.put("port", "8080");
WifiP2pServiceInfo srvcInfo = WifiP2pDnsSdServiceInfo.newInstance(mMyDevice.deviceName, "_http._tcp", values);
manager.addLocalService(channel, srvcInfo, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Toast.makeText(WiFiDirectActivity.this, "Local service added successfully",
Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int reasonCode) {
Toast.makeText(WiFiDirectActivity.this, "Local service addition failed : " + reasonCode,
Toast.LENGTH_SHORT).show();
}
});
}
ローカルサービスを検出するためのAPI:
public void discoverService() {
manager.clearServiceRequests(channel, null);
DnsSdTxtRecordListener txtListener = new DnsSdTxtRecordListener() {
@Override
/* Callback includes:
* fullDomain: full domain name: e.g "printer._ipp._tcp.local."
* record: TXT record data as a map of key/value pairs.
* device: The device running the advertised service.
*/
public void onDnsSdTxtRecordAvailable(String fullDomain, Map record, WifiP2pDevice device) {
Log.d(TAG, "DnsSdTxtRecord available -" + record.toString());
}
};
DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {
@Override
public void onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice resourceType) {
Log.d(TAG, "onBonjourServiceAvailable " + instanceName);
}
};
manager.setDnsSdResponseListeners(channel, servListener, txtListener);
WifiP2pDnsSdServiceRequest serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
manager.addServiceRequest(channel, serviceRequest, new ActionListener() {
@Override
public void onSuccess() {
// Success!
Log.d(TAG, "addServiceRequest success");
}
@Override
public void onFailure(int code) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
Log.d(TAG, "addServiceRequest failure with code " + code);
}
});
manager.discoverServices(channel, new ActionListener() {
@Override
public void onSuccess() {
// Success!
Log.d(TAG, "discoverServices success");
}
@Override
public void onFailure(int code) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
if (code == WifiP2pManager.P2P_UNSUPPORTED) {
Log.d(TAG, "P2P isn't supported on this device.");
} else {
Log.d(TAG, "discoverServices failure");
}
}
});
}
注:マネージャーとチャネルは次のように初期化されます
WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
Channel channel = manager.initialize(this, getMainLooper(), null);
WifiP2p
(一般的に):少し前に、私はWifiP2p
とService Broadcasting/Discovery
に基づいた非常に複雑なネットワーク接続システムを備えたアプリケーションを開発していました。そして、その経験に基づいて、私はすでにここにいくつかの投稿を書いていますSOそれがどれほど難しいか、身に着けているか、問題があるかについて。ここに2つあります(それらは私がWifiP2p
について得た内部知識でかなりいっぱいですService Discovery
、およびWifiP2p
自体を使用):
なぜAndroid WifiDirectの信頼性が低い)のピアを検出しているのですか
Wi-fi P2P。利用可能なすべてのピアに何らかのイベントを通知します
私の両方の答えを読むことをお勧めします(それらはWifiP2p
自体にもう少し焦点を合わせていますが)。彼らはあなたがWifiP2p Service Discovery
を扱うときにあなたが探しているべきものについてあなたにいくつかの見通しを与えるはずです。効率的で、比較的信頼性が高く、堅牢なWifiP2p
接続システム(特にService Discovery
を使用)を構築したい場合は、お尻を片付ける必要があると簡単に言えます。
WifiP2p Service Discovery
:あなたの正確な質問にもっとよく答えるために、私のService Discovery
をかなり確実に機能させるために私がしたこと(あなたとは異なります)をお話しします。
1。ブロードキャストService
:
まず第一に:Service
を(addLocalService
メソッドで)登録する前に、WifiP2pManager
のclearLocalServices
メソッドを使用する必要があります。また、リスナーがaddLocalService
コールバックで返されたclearLocalServices
を渡した場合は、onlyでonSuccess
を呼び出す必要があることが重要です。
これによりブロードキャストは非常にうまく設定されますが、他のノードがブロードキャストされたservice
を常に検出できるとは限らないことがわかりました(特に、ローカルService
の登録時にこれらのノードがサービスをアクティブに検出していなかった場合は、後で「参加」しました) )。この問題を100%確実に修正する方法を見つけることができませんでした。そして、私がおそらくWifiP2p
関連のすべてを試していたと信じてください。いいえ、clearLocalServices
-addLocalService
シーケンスは、実際には満足のいく結果をもたらしていませんでした。またはそれ以上に:何か違うことをすることははるかにうまくいった。私がやろうと決めたのは、正常にローカルサービスを追加した後(onSuccess
からのaddLocalService
コールバック)、定期的にWifiP2pManager
のメソッドThread
を呼び出すdiscoverPeers
を開始したことです。それはすべてのservice
情報を再放送することを余儀なくされているようでした。
つまり...基本的に、ブロードキャストコードのベースは、このように見えないはずです(ネットワーク接続システムが適切である場合、ここに投稿するコードのすべての部分からすべての「チェック」が削除されることに注意してください)状態、あなたはあなたのソリューションに最もよく合うようにあなた自身でそれらを設計するべきです):
public void startBroadcastingService(){
mWifiP2pManager.clearLocalServices(mWifiP2pChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
mWifiP2pManager.addLocalService(mWifiP2pChannel, mWifiP2pServiceInfo,
new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
// service broadcasting started
mServiceBroadcastingHandler
.postDelayed(mServiceBroadcastingRunnable,
SERVICE_BROADCASTING_INTERVAL);
}
@Override
public void onFailure(int error) {
// react to failure of adding the local service
}
});
}
@Override
public void onFailure(int error) {
// react to failure of clearing the local services
}
});
}
mServiceBroadcastingRunnable
は次のようになります。
private Runnable mServiceBroadcastingRunnable = new Runnable() {
@Override
public void run() {
mWifiP2pManager.discoverPeers(mWifiP2pChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(int error) {
}
});
mServiceBroadcastingHandler
.postDelayed(mServiceBroadcastingRunnable, SERVICE_BROADCASTING_INTERVAL);
}
};
2。 Service
:の検出
あなたのservice
を発見するために、私は同様のアプローチを使用しました。検出を設定することと、services
の「再検出」を強制しようとすることの両方。
セットアップは、次の3つのWifiP2pManager
のメソッドのシーケンスで実行されました。
removeServiceRequest
、addServiceRequest
、discoverServices
それらはこの正確な順序で呼び出され、特定のメソッド(正確には2番目または3番目のメソッド)は、前のメソッドがonSuccess
コールバックで「戻った」後にのみ呼び出されました。
services
の再検出は、直感的な方法で実行されていました(前述のシーケンスを繰り返すだけです:removeServiceRequest
-> addServiceRequest
-> discoverServices
)。
私のコードのベースはもっと少なく見えました(Service Discovery
を開始するには、最初にprepareServiceDiscovery()
を呼び出し、次にstartServiceDiscovery()
を呼び出します):
public void prepareServiceDiscovery() {
mWifiP2pManager.setDnsSdResponseListeners(mWifiP2pChannel,
new WifiP2pManager.DnsSdServiceResponseListener() {
@Override
public void onDnsSdServiceAvailable(String instanceName,
String registrationType, WifiP2pDevice srcDevice) {
// do all the things you need to do with detected service
}
}, new WifiP2pManager.DnsSdTxtRecordListener() {
@Override
public void onDnsSdTxtRecordAvailable(
String fullDomainName, Map<String, String> record,
WifiP2pDevice device) {
// do all the things you need to do with detailed information about detected service
}
});
mWifiP2pServiceRequest = WifiP2pDnsSdServiceRequest.newInstance();
}
private void startServiceDiscovery() {
mWifiP2pManager.removeServiceRequest(mWifiP2pChannel, mWifiP2pServiceRequest,
new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
mWifiP2pManager.addServiceRequest(mWifiP2pChannel, mWifiP2pServiceRequest,
new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
mWifiP2pManager.discoverServices(mWifiP2pChannel,
new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
//service discovery started
mServiceDiscoveringHandler.postDelayed(
mServiceDiscoveringRunnable,
SERVICE_DISCOVERING_INTERVAL);
}
@Override
public void onFailure(int error) {
// react to failure of starting service discovery
}
});
}
@Override
public void onFailure(int error) {
// react to failure of adding service request
}
});
}
@Override
public void onFailure(int reason) {
// react to failure of removing service request
}
});
}
mServiceDiscoveringRunnable
は次のとおりです。
private Runnable mServiceDiscoveringRunnable = new Runnable() {
@Override
public void run() {
startServiceDiscovery();
}
};
これらすべてが私のシステムを非常にうまく機能させました。まだ完璧ではありませんでしたが、このテーマに関するドキュメントが不足しているため、これ以上改善することはできなかったと思います。
このアプローチをテストする場合は、それがどのように機能するかを必ず教えてください(またはifそれがあなたのために機能する;))。
問題がサービスの検出である場合、デバイスとサービスを検出可能にするための最善の方法はクレアリンググループであると思いますが、すべてのデバイスでグループが作成されている場合は、直接接続できません。しかし、wifiネットワークとして。私は毎日それをします、そしてそれは働きます。