This time I will show you how to discover Printers over a wifi network, to do this we need to use the jmDNS Java Library which is an implementation of Multi-Cats DNS, a network service discovery service.
First of all we need to create a Printer Object which is here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
import java.net.InetAddress; public class Printer { private String name; private InetAddress address; public Printer(String name, InetAddress address) { this.name = name; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public InetAddress getAddress() { return address; } public void setAddress(InetAddress address) { this.address = address; } @Override public boolean equals(Object o) { if (o instanceof Printer) { Printer printer = (Printer) o; if (printer.name.equals(this.name)) return true; } return false; } } |
This class represents an instance of a Printer in the Local Network.
Then we need to implement the ServiceListener, here it is for you:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
package com.example.testandroid; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import javax.jmdns.JmDNS; import javax.jmdns.ServiceEvent; import javax.jmdns.ServiceListener; import android.content.Context; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.MulticastLock; import android.util.Log; /** * This class implements a network service listener to discover Printers over a * local wifi network, to aid this functionality this class implements the jmdns * Service listener which is an implementation of Multi-Cast DNS * * @author JPopoka */ public class PrinterDiscovery implements ServiceListener { private final String TAG = this.getClass().getName(); private Context context; /* Service type for printers */ private static final String SERVICE_TYPE = "_ipp._tcp.local."; /* List to store discovered printers */ private List printers; private Printer currentPrinter; /* Helper used for printer discovery */ private JmDNS jmdns; /* Wifi Lock to keep radio ON as needed */ private MulticastLock lock; /* Singleton Pattern shared instance methods ---------------------------- */ private static PrinterDiscovery printerDiscovery; private PrinterDiscovery(Context context) { this.context = context; printers = new ArrayList(); } /** * Singleton accessor to the instance * * @param context * @return instance - And instance of PrinterDiscovery */ public static PrinterDiscovery getInstance(Context context) { if (printerDiscovery == null) printerDiscovery = new PrinterDiscovery(context); return printerDiscovery; } /** * Starts the service to discover printers in the local network */ public void start() { new Thread(new Runnable() { @Override public void run() { startDiscovery(); } }).start(); } private void startDiscovery() { WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); int localIP = wifiInfo.getIpAddress(); if (localIP != 0) { byte[] byteaddr = new byte[] { (byte) (localIP & 0xff), (byte) (localIP >> 8 & 0xff), (byte) (localIP >> 16 & 0xff), (byte) (localIP >> 24 & 0xff) }; try { InetAddress addr = InetAddress.getByAddress(byteaddr); InetSocketAddress myServer = new InetSocketAddress(InetAddress.getByAddress(byteaddr), 9100); /* Adquire a wifi lock to keep radio ON */ lock = wifiManager.createMulticastLock("PRT LCK"); lock.setReferenceCounted(true); lock.acquire(); /* Create an instance of JmDNS and bind it to network */ jmdns = JmDNS.create(addr, "myJMDNS"); /* Bind this listener to the service */ jmdns.addServiceListener(SERVICE_TYPE, this); Log.d(TAG, "Listening to Printers"); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } /* Stops the discovery service */ public synchronized void stop() { if (jmdns != null) { jmdns.unregisterAllServices(); try { jmdns.close(); } catch (IOException e) { e.printStackTrace(); } finally { jmdns = null; } } if (lock != null) { lock.release(); lock = null; } printerDiscovery = null; } public synchronized List getPrinters() { return printers; } public synchronized void selectPrinter(Printer printer) { this.currentPrinter = printer; } public synchronized Printer getCurrentPrinter() { return currentPrinter; } public synchronized Printer getPrinterByName(String name) { for (Printer printer : printers) { if (printer.getName().equals(name)) return printer; } return null; } /* Service Listener methods --------------------------------------------- */ // @SuppressWarnings("deprecation") @Override public void serviceResolved(ServiceEvent ev) { Log.d(TAG, "service resolved: " + ev.getInfo().getName() + ", port: " + ev.getInfo().getPort() + " address: " + ev.getInfo().getInetAddress()); Printer printer = new Printer(ev.getInfo().getName(), ev.getInfo().getInetAddress()); printers.add(printer); } @SuppressWarnings("deprecation") @Override public void serviceRemoved(ServiceEvent ev) { Log.d(TAG, "service removed: " + ev.getName()); Printer printer = new Printer(ev.getInfo().getName(), ev.getInfo().getInetAddress()); printers.remove(printer); } @Override public void serviceAdded(ServiceEvent ev) { Log.d(TAG, "service added, name: " + ev.getName() + ", type: " + ev.getType()); jmdns.requestServiceInfo(ev.getType(), ev.getName(), 1); } } |
We instantiate it on our main activity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
. . . public class MainActivity extends Activity { final String TAG = ""; PrinterDiscovery pd; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pd = PrinterDiscovery.getInstance(getApplicationContext()); } . . . |
And finally we start it and stop it onResume and onPause respectively:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
. . . @Override protected void onResume() { super.onResume(); Log.d(TAG, "Resume"); pd.start(); } @Override protected void onPause() { super.onPause(); pd.stop(); Log.d(TAG, "Paused"); } . . . |
We should see on the Log something like this:
1 2 3 |
Listening to Printers service added, name: HP LaserJet 100, type: _ipp._tcp.local service resolved, name: HP LaserJet 100, port: 631 address: /192.168.1.57 |
Remember to add this permissions in your manifest:
<uses-permission android:name=”android.permission.INTERNET”/>
<uses-permission android:name=”android.permission.ACCESS_WIFI_STATE” />
<uses-permission android:name=”android.permission.CHANGE_WIFI_MULTICAST_STATE” />