I have been trying to create some simple WiFi Direct prototype apps and have been unable to get WiFi Direct (P2P) for Service Discovery working. (Android docs here: https://developer.android.com/training/connect-devices-wirelessly/nsd-wifi-direct)
I started with a barebones Android Studio project based on the empty activity template. My target version of Android is 10 (level 29). I have tried several different arrangements of code similar to what is found on the above Android web page, which basically consist of the following basic parts:
<?xmlversion="1.0"encoding="utf-8"?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permissionandroid:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permissionandroid:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permissionandroid:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permissionandroid:name="android.permission.INTERNET"/>
<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permissionandroid:name="android.permission.NEARBY_WIFI_DEVICES"/>
<uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"tools:ignore="CoarseFineLocation"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.app_name"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
private static final String SERVICE_NAME="WiFiD_DemoService";
private static final String SERVICE_TYPE="_presence._tcp";
private WifiP2pManager manager;
private WifiP2pManager.Channel channel;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(!initP2p()){
finish();
}
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M
&&checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
!=PackageManager.PERMISSION_GRANTED){
requestPermissions(newString[]{Manifest.permission.ACCESS_FINE_LOCATION},
MainActivity.PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION);
}
}
privatebooleaninitP2p(){
//Devicecapabilitydefinitioncheck
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)){
Log.e(TAG,"Wi-FiDirectisnotsupportedbythisdevice.");
returnfalse;
}
//Hardwarecapabilitycheck
WifiManagerwifiManager=(WifiManager)getApplicationContext().getSystemService(WIFI_SERVICE);
if(wifiManager==null){
Log.e(TAG,"CannotgetWi-Fisystemservice.");
returnfalse;
}
if(!wifiManager.isP2pSupported()){
Log.e(TAG,"Wi-FiDirectisnotsupportedbythehardwareorWi-Fiisoff.");
returnfalse;
}
manager=(WifiP2pManager)getApplicationContext().getSystemService(WIFI_P2P_SERVICE);
if(manager==null){
Log.e(TAG,"CannotgetWi-FiDirectsystemservice.");
returnfalse;
}
channel=manager.initialize(this,getMainLooper(),null);
if(channel==null){
Log.e(TAG,"CannotinitializeWi-FiDirect.");
returnfalse;
}
returntrue;
}
privatevoidstartRegistration(){
//Createastringmapcontaininginformationaboutyourservice.
Map<String,String>record=newHashMap<String,String>();
record.put("listenport",String.valueOf(SERVER_PORT));
record.put("buddyname","ExperienceHost"+(int)(Math.random()*1000));
record.put("available","visible");
//Serviceinformation.Passitaninstancename,servicetype
//_protocol._transportlayer,andthemapcontaining
//informationotherdeviceswillwantoncetheyconnecttothisone.
WifiP2pDnsSdServiceInfoserviceInfo=WifiP2pDnsSdServiceInfo.newInstance(SERVICE_NAME,SERVICE_TYPE,record);
//Addthelocalservice,sendingtheserviceinfo,networkchannel,
//andlistenerthatwillbeusedtoindicatesuccessorfailureof
//therequest.
manager.addLocalService(channel,serviceInfo,newWifiP2pManager.ActionListener(){
@Override
publicvoidonSuccess(){
//Commandsuccessful! Codeisn'tnecessarilyneededhere,
//UnlessyouwanttoupdatetheUIoraddloggingstatements.
outputLog("Service:"+SERVICE_NAME+"Started.");
}
@Override
publicvoidonFailure(intarg0){
//Commandfailed.CheckforP2P_UNSUPPORTED,ERROR,orBUSY
outputLog("Warning,Service:"+SERVICE_NAME+"FailedtoStart.");
}
});
}
privatevoiddiscoverService(){
manager.setDnsSdResponseListeners(channel,
newWifiP2pManager.DnsSdServiceResponseListener(){
@Override
publicvoidonDnsSdServiceAvailable(StringinstanceName,StringregistrationType,WifiP2pDeviceresourceType){
outputLog("Servicediscovered:"+instanceName);
if(instanceName==SERVICE_NAME){
//shouldconnecttoservice
outputLog("JoiningService:"+instanceName);
}
Log.d(TAG,"onBonjourServiceAvailable"+instanceName);
}
},newWifiP2pManager.DnsSdTxtRecordListener(){
/*Callbackincludes:
*fullDomain:fulldomainname:e.g"printer._ipp._tcp.local."
*record:TXTrecorddtaasamapofkey/valuepairs.
*device:Thedevicerunningtheadvertisedservice.
*/
@Override
publicvoidonDnsSdTxtRecordAvailable(StringfullDomain,Map<String,String>record,WifiP2pDevicedevice){
Log.d(TAG,"DnsSdTxtRecordavailable-"+record.toString());
outputLog("Found service on device: " + device.deviceAddress + " with idenity of: "+ (String)record.get("buddyname"));
}
});
serviceRequest=WifiP2pDnsSdServiceRequest.newInstance();
manager.addServiceRequest(channel,serviceRequest,
newWifiP2pManager.ActionListener(){
@Override
publicvoidonSuccess(){
//Success!
outputLog("ServiceRequestadded");
}
@Override
publicvoidonFailure(intcode){
//Commandfailed.CheckforP2P_UNSUPPORTED,ERROR,orBUSY
outputLog("ServiceRequestaddfailed");
}
});
manager.discoverServices(channel,
newWifiP2pManager.ActionListener(){
@Override
publicvoidonSuccess(){
//Success!
outputLog("DiscoverServicesinitsucceeded");
}
@Override
publicvoidonFailure(intcode){
//Commandfailed.CheckforP2P_UNSUPPORTED,ERROR,orBUSY
if(code==WifiP2pManager.P2P_UNSUPPORTED){
Log.d(TAG,"Wi-FiDirectisn'tsupportedonthisdevice.");
}
outputLog("DiscoverServicesinitfailed"+code);
}
});
}
publicvoidonClickButHostService(Viewview){
startRegistration();
}
publicvoidonClickButDiscoverService(Viewview){
discoverService();
}
publicvoidoutputLog(Stringmsg){
Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();
}
If I run the app on one device, and click the Host Service button, then deploy the app in debug mode on another device, and click the DiscoverService button, testing with break points shows the discovery service initializing successfully, but neither the onDnsSdServiceAvailable nor the onDnsSdTxtRecordAvailable listeners ever seem to fire. I have also used break points to confirm when clicking on the HostService that the addLocalService launches successfully.
I have not been able to find a current, and buildable sample project of a WiFi Direct P2P Service Discovery app anywhere, and therefore unable to walk through, and test a working sample.
Is there anyone that has been able to recently get this API to work who can shed some light or offer some pointers on why this code is not discovering and firing with the detection of WiFi Direct P2P Services registered on either the same app running on another device, or even 3rd party services from some of the many devices in the local area?
Is there something else, or more required to discover this type of service?
I don't see any glaring issues with your code as it is roughly what lies in the docs, but here is a sample from the Android repo that I have cloned into a Github repo here and verified is working as expected.