微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

WifiP2pManager无法添加LocalService,当应用程序在后台运行时,discoverServices返回WifiP2pManager.Error

如何解决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 举报,一经查实,本站将立刻删除。