如何解决WifiP2pManager无法添加LocalService,当应用程序在后台运行时,discoverServices返回WifiP2pManager.Error
我是新来的。无论如何,我一直在努力解决这个问题。我创建了一个运行wifip2pHelper的服务,以发现附近的设备并检索wifip2pDnsSdServiceInfo。我在多部电话上进行了测试,它们似乎工作正常。如果工作正常,则应返回以下日志:
2020-08-12 13:32:23.449 24345-24345/com.example.acts D/WiFi P2P Helper: Service Request Added
2020-08-12 13:32:23.449 24345-24345/com.example.acts D/WiFi P2P Helper: discover Services Successful
2020-08-12 13:32:23.473 24345-24345/com.example.acts D/WiFi P2P Helper: Local Service Added
现在,我使服务在后台运行(即使应用程序被杀死)。除了在Android 10上运行的任何设备外,它在我测试过的设备上似乎都可以正常运行。我怀疑是Android 10导致wifip2pManager或WiFi P2P本身不在后台运行。但我不确定是由Android 10引起的(我只有2台经过测试的Android 10设备)。它返回以下日志:
2020-08-12 13:33:23.517 24345-24345/com.example.acts D/WiFi P2P Helper: Service Request Added
2020-08-12 13:33:23.517 24345-24345/com.example.acts D/WiFi P2P Helper: Error with P2P 0
2020-08-12 13:33:23.518 24345-24345/com.example.acts D/WiFi P2P Helper: Failed to Add Local Service
2020-08-12 13:33:23.518 24345-24345/com.example.acts E/WiFi P2P Helper: 0
如您所见,“ P2P 0错误”和“添加本地服务失败”指向discoverServices和addLocalService。下面是代码。对不起,把它们都丢在这里。任何帮助将不胜感激!谢谢!
public class wifip2pHelper extends Service {
wifip2pManager manager;
wifip2pManager.Channel channel;
wifip2pDnsSdServiceRequest serviceRequest;
IntentFilter intentFilter;
String iid;
private String baseServiceName = "ACTS";
private String serviceName = "";
final HashMap<String,String> buddies = new HashMap<String,String>();
final String TAG = "WiFi P2P Helper";
Handler handler = new Handler();
Runnable runnable;
int delay = 15000;
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onCreate() {
super.onCreate();
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public int onStartCommand(Intent intent,int flags,int startId) {
manager = (wifip2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this,getMainLooper(),null);
intentFilter = new IntentFilter();
intentFilter.addAction(wifip2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(wifip2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter.addAction(wifip2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter.addAction(wifip2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
getUser();
startRegistration();
discoverService();
startMyOwnForeground();
return START_STICKY;
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void startMyOwnForeground() {
String NOTIFICATION_CHANNEL_ID = "com.example.acts";
String channelName = "My Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID,channelName,notificationmanager.IMPORTANCE_NONE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
notificationmanager manager = (notificationmanager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this,NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setongoing(true)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle("Hello World")
.setPriority(notificationmanager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(1333,notification);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void getUser() {
List<User> users = User.getUser();
int count = users.size();
if (count > 0) {
User loggedInUser = users.get(0);
iid = loggedInUser.Id;
serviceName = baseServiceName + "_" + loggedInUser.Id;
Log.e("User",iid);
} else {
//uId = "User_Unregistered";
serviceName = baseServiceName + "_User_Unregistered";
Log.e("User in else",serviceName);
}
}
public String getWFDMacAddress() {
try {
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface ntwInterface : interfaces) {
if (ntwInterface.getName().equalsIgnoreCase("p2p0")) {
byte[] byteMac = ntwInterface.getHardwareAddress();
if (byteMac == null) {
return null;
}
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < byteMac.length; i++) {
strBuilder.append(String.format("%02X:",byteMac[i]));
}
if (strBuilder.length() > 0) {
strBuilder.deleteCharat(strBuilder.length() - 1);
}
return strBuilder.toString().toLowerCase();
}
}
} catch (Exception e) {
Log.d(TAG,e.getMessage());
}
return null;
}
public int findOpenSocket() throws IOException {
// Initialize a server socket on the next available port.
ServerSocket serverSocket = new ServerSocket(0);
// Store the chosen port.
int port = serverSocket.getLocalPort();
serverSocket.close();
return port;
}
private void startRegistration() {
manager.clearLocalServices(channel,new wifip2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.e(TAG,"onSuccess: Sucessss");
int port = 3030;
try {
port = findOpenSocket();
} catch (IOException e) {
e.printstacktrace();
}
Map record = new HashMap();
record.put("listenport",String.valueOf(port));
record.put("buddyname",iid);
record.put("available","visible");
wifip2pDnsSdServiceInfo serviceInfo =
wifip2pDnsSdServiceInfo.newInstance(serviceName,"_presence._tcp",record);
manager.addLocalService(channel,serviceInfo,new wifip2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.d(TAG,"Local Service Added");
}
@Override
public void onFailure(int arg0) {
Log.d(TAG,"Failed to Add Local Service");
Log.e(TAG,String.valueOf(arg0));
}
});
}
@Override
public void onFailure(int arg0) {
Log.d(TAG,"P2P Unsupported");
}
});
}
private void discoverService() {
wifip2pManager.DnsSdTxtRecordListener txtListener = new wifip2pManager.DnsSdTxtRecordListener() {
@Override
public void onDnsSdTxtRecordAvailable(
String fullDomain,Map record,wifip2pDevice device) {
Log.d(TAG,"DnsSdTxtRecord available - " + record.toString());
buddies.put(device.deviceAddress,(String) record.get("buddyname"));
}
};
wifip2pManager.DnsSdServiceResponseListener servListener = new wifip2pManager.DnsSdServiceResponseListener() {
@Override
public void onDnsSdServiceAvailable(String instanceName,String registrationType,wifip2pDevice resourceType) {
resourceType.deviceName = buddies
.containsKey(resourceType.deviceAddress) ? buddies
.get(resourceType.deviceAddress) : resourceType.deviceName;
String uId = instanceName.replace(baseServiceName + "_","");
Log.d(TAG,"Received " + uId);
/*discovered device1 = new discovered();
device1.discoveredthreeID = uId;
discovered.insertTransactionTosqlite(device1);*/
}
};
serviceRequest = wifip2pDnsSdServiceRequest.newInstance();
manager.addServiceRequest(channel,serviceRequest,"Service Request Added");
}
@Override
public void onFailure(int code) {
Log.d(TAG,"Failed to Add Service Request");
}
});
manager.setDnsSdResponseListeners(channel,servListener,txtListener);
manager.discoverServices(channel,new wifip2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.d(TAG,"discover Services Successful");
}
@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 if (code == wifip2pManager.ERROR) {
Log.d(TAG,"Error with P2P " + code);
} else if (code == wifip2pManager.BUSY) {
Log.d(TAG,"P2P is Busy " + code);
}
}
});
}
}
解决方法
大家好,与我有相同问题的所有人。我找到了解决方案。基本上,Android 10(API 29)将位置权限分为普通位置权限和后台位置权限。您需要让您的应用程序提示后台权限(因为默认情况下不允许)。
将它们添加到您的AndroidManifest.xml文件中
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
,并且在我的MainActivity onCreate方法中,添加了检查以查看设备是否在Android 10(API 29)上以及是否已授予权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if ((ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) ||
(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_BACKGROUND_LOCATION},1);
}
} else {
if ((ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
}
}
如果还有其他人可以更好地实施权限检查,请在此处共享。我也想学习。谢谢!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。