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.