The printer cannot be searched using WiFi Direct only on tablets

24 views Asked by At

I am creating a program that allows printing from tablets and phones using ipp.
I found a suitable library to use ipp.

Below is my code.

call search code

static List<WifiP2pDevice> devices;
FindP2pPrinters findP2pPrinters = new FindP2pPrinters(builtInPrintService);
devices = findP2pPrinters.search();

FindP2pPrinters.java

package elf.profession.elfscoreprint_mobile;

import android.content.ComponentName;
import android.content.ServiceConnection;
import android.net.Uri;
import android.net.wifi.p2p.WifiP2pDevice;
import android.os.IBinder;
import android.preference.Preference;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

import elf.profession.elfscoreprint_mobile.discovery.DiscoveredPrinter;
import elf.profession.elfscoreprint_mobile.discovery.P2pDiscovery;
import elf.profession.elfscoreprint_mobile.p2p.P2pMonitor;
import elf.profession.elfscoreprint_mobile.p2p.P2pPeerListener;
import elf.profession.elfscoreprint_mobile.ui.PrinterPreference;

public class FindP2pPrinters implements ServiceConnection {
    private static final String TAG = FindP2pPrinters.class.getSimpleName();
    private static final boolean DEBUG = true;

    private BuiltInPrintService mPrintService;
    private P2pListener mPeerDiscoveryListener;

    public static ArrayList<WifiP2pDevice> devices = new ArrayList<>();
    public static ArrayList<DiscoveredPrinter> printers = new ArrayList<>();

    FindP2pPrinters(BuiltInPrintService service) {
        mPrintService = service;
        mPeerDiscoveryListener = null;
        devices.clear();
        printers.clear();
    }

    public ArrayList<WifiP2pDevice> search() {
        if (mPeerDiscoveryListener == null) {
            System.out.println("mPeerDiscoveryListener is null");

            mPeerDiscoveryListener = new P2pListener();
            mPrintService.getP2pMonitor().discover(mPeerDiscoveryListener);
        }else{
            System.out.println("mPeerDiscoveryListener is not null");
        }
        return devices;
    }

    public void stopDiscover(){
        if (mPeerDiscoveryListener != null) {
            mPrintService.getP2pMonitor().stopDiscover(mPeerDiscoveryListener);
            mPeerDiscoveryListener = null;
        }
    }

    public List<WifiP2pDevice> getDevices() {
        if(DEBUG) Log.d(TAG, "devices : " + devices);
        return devices;
    }

    public List<DiscoveredPrinter> getPrinters() {
        if(DEBUG) Log.d(TAG, "printers : " + printers);
        return printers;
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        if (DEBUG) Log.d(TAG, "onServiceConnected");

        if (mPeerDiscoveryListener == null) {
            mPeerDiscoveryListener = new P2pListener();
            mPrintService.getP2pMonitor().discover(mPeerDiscoveryListener);
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        mPrintService = null;
    }

    private class P2pListener implements P2pPeerListener {
        @Override
        public void onPeerFound(WifiP2pDevice peer) {
            if (DEBUG) Log.d(TAG, "onPeerFound: " + P2pMonitor.toString(peer));
            if (mPrintService == null) {
                return;
            }

            if(!devices.contains(peer)){
                devices.add(peer);
            }else{
                int index = devices.indexOf(peer);
                WifiP2pDevice device = devices.get(index);
                if(device.status != peer.status){
                    devices.set(index, peer);
                }
            }

            DiscoveredPrinter printer = P2pDiscovery.toPrinter(peer);
            if (DEBUG) Log.d(TAG, "onPeerFound DiscoveredPrinter: " + "name: " + printer.name + ", uuid: " + printer.uuid + ", path: " + printer.path + ", paths: " + printer.paths + ", location: " + printer.location);
            if(!printers.contains(printer)){
                printers.add(printer);
            }

        }

        @Override
        public void onPeerLost(WifiP2pDevice peer) {
            if (DEBUG) Log.d(TAG, "onPeerLost: " + P2pMonitor.toString(peer));
            if (mPrintService == null) {
                return;
            }

            DiscoveredPrinter printer = P2pDiscovery.toPrinter(peer);
    }
}

P2pMonitor.java

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package elf.profession.elfscoreprint_mobile.p2p;

import android.content.Context;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.util.Log;

import elf.profession.elfscoreprint_mobile.BuiltInPrintService;

/**
 * Globally manage P2P discovery and connectivity
 */
public class P2pMonitor {
    private static final String TAG = P2pMonitor.class.getSimpleName();
    private static final boolean DEBUG = true;

    private final BuiltInPrintService mService;
    private final WifiP2pManager mP2pManager;
    private P2pDiscoveryProcedure mPeerDiscovery;
    private P2pConnectionProcedure mConnection;
    private String mConnectedInterface;

    public P2pMonitor(BuiltInPrintService service) {
        if(DEBUG) Log.d(TAG, "P2pMonitor() call");
        mService = service;
        mP2pManager = (WifiP2pManager) mService.getSystemService(Context.WIFI_P2P_SERVICE);
    }

    /** Return a printable String form of a {@link WifiP2pDevice} */
    public static String toString(WifiP2pDevice device) {
        if (device == null) {
            return "null";
        } else {
            return device.deviceName + " " + device.deviceAddress + ", status="
                    + statusString(device.status);
        }
    }

    private static String statusString(int status) {
        switch (status) {
            case WifiP2pDevice.AVAILABLE:
                return "available";
            case WifiP2pDevice.CONNECTED:
                return "connected";
            case WifiP2pDevice.FAILED:
                return "failed";
            case WifiP2pDevice.INVITED:
                return "invited";
            case WifiP2pDevice.UNAVAILABLE:
                return "unavailable";
            default:
                return "unknown";
        }
    }

    /**
     * Start a discovery of Wi-Fi Direct peers until all requests are closed
     */
    public void discover(P2pPeerListener listener) {
        if (DEBUG) Log.d(TAG, "discover()");

        if (mP2pManager == null) {
            if (DEBUG) Log.d(TAG, "mP2pManager is null");
            return;
        }
        if (mPeerDiscovery == null) {
            if (DEBUG) Log.d(TAG, "mPeerDiscovery is null");
            mPeerDiscovery = new P2pDiscoveryProcedure(mService, mP2pManager, listener);
        } else {
            if (DEBUG) Log.d(TAG, "mPeerDiscovery is not null");
            mPeerDiscovery.addListener(listener);
        }
    }

    /**
     * Remove the request to discover having the same listener. When all outstanding requests are
     * removed, discovery itself is stopped.
     */
    public void stopDiscover(P2pPeerListener listener) {
        if (DEBUG) Log.d(TAG, "stopDiscover");
        if (mPeerDiscovery != null) {
            mPeerDiscovery.removeListener(listener);
            if (mPeerDiscovery.getListeners().isEmpty()) {
                mPeerDiscovery.cancel();
                mPeerDiscovery = null;
            }
        }
    }

    /**
     * Request connection to a peer (which may already be connected) at least until stopped. Keeps
     * the current connection open as long as it might be useful.
     */
    public void connect(WifiP2pDevice peer, P2pConnectionListener listener) {
        if (DEBUG) Log.d(TAG, "connect(" + toString(peer) + ")");

        if (mP2pManager == null) {
            // Device has no P2P support so indicate failure
            mService.getMainHandler().post(listener::onConnectionClosed);
            return;
        }

        // Check for competing connection
        if (mConnection != null && !peer.deviceAddress.equals(mConnection.getPeer()
                .deviceAddress)) {
            Log.d(TAG, "connection 1 : " + mConnection.getListenerCount());
            if (mConnection.getListenerCount() == 1) {
                Log.d(TAG, "connection 2");
                // The only listener is our internal one, so close this connection to make room
                mConnection.close();
                mConnection = null;
            } else {
                Log.d(TAG, "connection 3");
                // Cannot open connection
                mService.getMainHandler().post(listener::onConnectionClosed);
                return;
            }
        }

        // Check for existing connection to the same device
        if (mConnection == null) {
            Log.d(TAG, "connection 4");
            // Create a new connection request with our internal listener
            mConnection = new P2pConnectionProcedure(mService, mP2pManager, peer,
                    new P2pConnectionListener() {
                        @Override
                        public void onConnectionOpen(String networkInterface, WifiP2pInfo info) {
                            Log.d(TAG, "networkInterface : " + networkInterface);
                            mConnectedInterface = networkInterface;
                        }

                        @Override
                        public void onConnectionClosed() {
                            mConnectedInterface = null;
                            Log.d(TAG, "onConnectionClosed()");
                        }

                        @Override
                        public void onConnectionDelayed(boolean delayed) {
                        }
                    });
        }
        mConnection.addListener(listener);
        Log.d(TAG, "mConnection count2 : " + mConnection.getListenerCount());
    }


    /**
     * Give up on the connection request associated with a listener. The connection will stay
     * open as long as other requests exist.
     */
    void stopConnect(P2pConnectionListener listener) {
        if (mConnection == null || !mConnection.hasListener(listener)) {
            return;
        }

        if (DEBUG) Log.d(TAG, "stopConnect " + toString(mConnection.getPeer()));
        mConnection.removeListener(listener);

        // If current connection attempt is incomplete and no longer required, close it.
        if (mConnection.getListenerCount() == 1 && mConnectedInterface == null) {
            if (DEBUG) Log.d(TAG, "Abandoning connection request");
            mConnection.close();
            mConnection = null;
        }
    }

    /** Return the current connection procedure, if any */
    P2pConnectionProcedure getConnection() {
        return mConnection;
    }

    /** Return the current connected interface, if any */
    public String getConnectedInterface() {
        return mConnectedInterface;
    }

    /** Forcibly stops all connections/discoveries in progress, if any */
    public void stopAll() {
        if (mConnection != null) {
            mConnection.close();
            mConnection = null;
            mConnectedInterface = null;
        }
        if (mPeerDiscovery != null) {
            mPeerDiscovery.cancel();
            mPeerDiscovery = null;
        }
    }
}

P2pDiscoveryProcedure.java

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package elf.profession.elfscoreprint_mobile.p2p;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Looper;
import android.util.Log;

import elf.profession.elfscoreprint_mobile.BuiltInPrintService;
import elf.profession.elfscoreprint_mobile.util.BroadcastMonitor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;

/**
 * Manage the process of discovering P2P printer devices
 */
class P2pDiscoveryProcedure {
    private static final String TAG = P2pDiscoveryProcedure.class.getSimpleName();
    private static final boolean DEBUG = true;

    private static final Pattern PRINTER_PATTERN =
            Pattern.compile("^(^3-.+-[145])|(0003.+000[145])$");

    private final WifiP2pManager mP2pManager;
    private final List<P2pPeerListener> mListeners = new CopyOnWriteArrayList<>();
    private final List<WifiP2pDevice> mPeers = new ArrayList<>();
    private BroadcastMonitor mBroadcastMonitor;
    private WifiP2pManager.Channel mChannel;

    P2pDiscoveryProcedure(BuiltInPrintService service, WifiP2pManager p2pManager,
            P2pPeerListener listener) {
        mP2pManager = p2pManager;
        if (DEBUG) Log.d(TAG, "P2pDiscoveryProcedure()");
        mChannel = mP2pManager.initialize(service, Looper.getMainLooper(), null);
        mListeners.add(listener);

        BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
                    if (DEBUG) Log.d(TAG, "WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)");
                    int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
                    boolean isP2pEnabled = state == WifiP2pManager.WIFI_P2P_STATE_ENABLED;
                    if (DEBUG) Log.d(TAG, "WIFI_P2P_STATE_CHANGED_ACTION: enabled=" + isP2pEnabled);
                    if (isP2pEnabled) {
                        mP2pManager.stopPeerDiscovery(mChannel, null);
                        mP2pManager.discoverPeers(mChannel, null);
                    }
                } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
                    if (DEBUG) Log.d(TAG, "WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)");
                    WifiP2pDeviceList list = intent.getParcelableExtra(
                            WifiP2pManager.EXTRA_P2P_DEVICE_LIST);
                    Collection<WifiP2pDevice> newPeers = list.getDeviceList();
                    updatePeers(newPeers);

                    if (newPeers.isEmpty()) {
                        // Remind system we are still interested
                        mP2pManager.stopPeerDiscovery(mChannel, null);
                        mP2pManager.discoverPeers(mChannel, null);
                    }
                }
            }
        };

        mBroadcastMonitor = service.receiveBroadcasts(receiver,
                WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION,
                WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
        mP2pManager.discoverPeers(mChannel, null);
    }

    void addListener(P2pPeerListener listener) {
        mListeners.add(listener);
        if (!mPeers.isEmpty()) {
            for (WifiP2pDevice peer : mPeers) {
                listener.onPeerFound(peer);
            }
        }
    }

    void removeListener(P2pPeerListener listener) {
        mListeners.remove(listener);
    }

    List<P2pPeerListener> getListeners() {
        return mListeners;
    }

    /**
     * Signal find/loss of each device to listeners as it occurs
     */
    private void updatePeers(Collection<WifiP2pDevice> newPeers) {
        List<WifiP2pDevice> oldPeers = new ArrayList<>(mPeers);

        // Reset peer list and populate with new printer-type devices
        mPeers.clear();
        for (WifiP2pDevice peer : newPeers) {
            if (PRINTER_PATTERN.matcher(peer.primaryDeviceType).find()) {
                mPeers.add(peer);
            }
        }

        // Notify newly found devices
        Set<String> foundAddresses = new HashSet<>();
        for (WifiP2pDevice peer : mPeers) {
            foundAddresses.add(peer.deviceAddress);
            WifiP2pDevice old = getDevice(oldPeers, peer.deviceAddress);
            if (old == null || !old.equals(peer)) {
                for (P2pPeerListener listener : mListeners) {
                    listener.onPeerFound(peer);
                }
            }
        }

        // Notify lost devices
        for (WifiP2pDevice oldPeer : oldPeers) {
            if (!foundAddresses.contains(oldPeer.deviceAddress)) {
                for (P2pPeerListener listener : mListeners) {
                    listener.onPeerLost(oldPeer);
                }
            }
        }
    }

    private WifiP2pDevice getDevice(Collection<WifiP2pDevice> peers, String address) {
        for (WifiP2pDevice found : peers) {
            if (found.deviceAddress.equals(address)) {
                return found;
            }
        }
        return null;
    }

    /** Stop the discovery procedure */
    public void cancel() {
        if (DEBUG) Log.d(TAG, "stop()");
        mBroadcastMonitor.close();
        if (mChannel != null) {
            mP2pManager.stopPeerDiscovery(mChannel, null);
            mChannel.close();
            mChannel = null;
        }
    }
}

The phone normally searches for the printer device through P2P. However, the device is not detected on the tablet. Do I need to take different steps depending on my phone and tablet? If so, I would appreciate it if you could tell me how.

0

There are 0 answers