Tijil Saka
Tijil Saka

Reputation: 369

How do I detect if a USB is being inserted AND the NAMES of the UBS(S)

I am not sure where to even start I did some googling but I cant find anyhing for java. AI has also been unhelpful

I have treid some code that can dectect a ubs but im not sure about the name

Here is the code I have tried

public class AutoDetect {

static File[] oldListRoot = File.listRoots();
public static void main(String[] args) {
    AutoDetect.waitForNotifying();

}

public static void waitForNotifying() {
    Thread t = new Thread(new Runnable() {
        public void run() {
            while (true) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (File.listRoots().length > oldListRoot.length) {
                    System.out.println("new drive detected");
                    oldListRoot = File.listRoots();
                    System.out.println("drive"+oldListRoot[oldListRoot.length-1]+" detected");

                } else if (File.listRoots().length < oldListRoot.length) {
    System.out.println(oldListRoot[oldListRoot.length-1]+" drive removed");

                    oldListRoot = File.listRoots();

                }

            }
        }
    });
    t.start();
}
}

Detect USB Drive in Java

Upvotes: 0

Views: 81

Answers (2)

VGR
VGR

Reputation: 44338

Some important notes:

  • Avoid the java.io.File class. It is a holdover from Java 1.0 with a lot of flaws. Use Path and Files instead.
  • Never, ever ignore an interrupt. If someone interrupts your thread, they are asking you to stop what you’re doing and exit the thread. A thread which ignores interrupts is a rogue thread that can never be terminated!
  • You are checking for changes ten times per second. In my opinion, that’s a bit much. Listing file roots is not a quick operation to begin with.
  • File.listRoots() will only detect new USB storage devices in Windows. For other operating systems, it is necessary to examine the FileStores.

Unfortunately, there is no reliable way to determine the file path for a FileStore, other than looking at the text returned by its toString method on non-Windows systems. The best we can do is hope that the current format of the toString implementation remains stable. (Java SE tends to be good about keeping toString formats stable, even if it’s detrimental; anyone who has passed an array to System.out.println probably knows this.)

So, with that in mind, here is a program that monitors file systems:

import java.io.IOException;

import java.nio.file.Files;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileStore;
import java.nio.file.Path;

import java.util.Collection;
import java.util.Set;
import java.util.LinkedHashSet;

import java.util.function.Consumer;

public class FileStores {
    public record Root(Path path,
                       String type,
                       String device) {
    }

    public static Collection<Root> listRoots()
    throws IOException {
        Collection<Root> roots = new LinkedHashSet<>();
        FileSystem fs = FileSystems.getDefault();

        if (System.getProperty("os.name").contains("Windows")) {
            for (Path rootDir : fs.getRootDirectories()) {
                String type = Files.getFileStore(rootDir).type();
                roots.add(new Root(rootDir, type, null));
            }
        } else {
            for (FileStore store : fs.getFileStores()) {
                String summary = store.toString();
                String name = store.name();
                String type = store.type();
                String suffix = " (" + name + ")";
                Path mountPath;
                if (summary.endsWith(suffix)) {
                    String mountPoint = summary.substring(0,
                        summary.length() - suffix.length());
                    mountPath = Path.of(mountPoint);
                } else {
                    mountPath = null;
                }

                roots.add(new Root(mountPath, type, name));
            }
        }

        return roots;
    }

    public static void monitorRoots(Consumer<Collection<Root>> listener)
    throws InterruptedException {
        Collection<Root> roots = Set.of();

        while (true) {
            try {
                Collection<Root> newRoots = listRoots();
                if (!newRoots.equals(roots)) {
                    roots = newRoots;
                    listener.accept(new LinkedHashSet<>(roots));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            Thread.sleep(250);
        }
    }

    public static void main(String[] args)
    throws IOException {
        Runnable monitor = () -> {
            try {
                monitorRoots(roots -> roots.forEach(System.out::println));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        Thread monitorThread = new Thread(monitor);
        monitorThread.start();
    }
}

Notice that there is no catching of InterruptedException inside the loop. If an interrupt occurs, the loop will automatically terminate, which is a good thing. Interrupts don’t happen by accident; if a thread is interrupted, it’s because some other code wanted to shut it down.

I changed the frequency of checks to four times per second. Depending on the nature of your application, it can probably be even less frequent than that.

Upvotes: 1

Codo
Codo

Reputation: 78835

Do you want to detect all kind of USB devices, or just USB memory stick and similar (aka as USB mass storage devices)?

With the JavaDoesUSB library, you can detect when a USB device has been connected and you can also filter for specific device classes:

import net.codecrete.usb.Usb;
import net.codecrete.usb.UsbDevice;

import java.io.IOException;

public class MassStorage {

    public static void main(String[] args) throws IOException {
        Usb.setOnDeviceConnected(MassStorage::onConnected);

        System.out.println("Press ENTER to exit");
        System.in.read();
    }

    private static void onConnected(UsbDevice device) {
        if (isMassStorage(device)) {
            System.out.println("Mass storage device connected: " + device);
        }
    }

    private static boolean isMassStorage(UsbDevice device) {
        return device.getInterfaces().stream()
                .anyMatch(intf -> intf.getCurrentAlternate().getClassCode() == 0x08);
    }
}

Upvotes: 0

Related Questions