在 Android 應用中實現「一鍵 USB 傳輸」功能,將手機儲存檔案同步至電腦。主要有兩種實現路徑:ADB 指令與 Socket 通訊。
// 在應用中執行 ADB 指令 (需 USB 偵錯模式、電腦授權)
String command = "adb pull /sdcard/DCIM/photo.jpg D:/Backup/";
try {
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
Log.d("ADB", line);
}
process.waitFor();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
限制:需電腦安裝 ADB、手機開啟 USB 偵錯、用戶授權,不適合一般消費者應用。
public class FileTransferServer extends Thread {
private ServerSocket serverSocket;
private boolean running = true;
@Override public void run() {
try {
serverSocket = new ServerSocket(8888);
while (running) {
Socket client = serverSocket.accept();
new Thread(() -> handleClient(client)).start();
}
} catch (IOException e) { e.printStackTrace(); }
}
private void handleClient(Socket socket) {
try (DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream())) {
String cmd = in.readUTF(); // 如 "LIST" 或 "GET filename"
if ("LIST".equals(cmd)) {
sendFileList(out);
} else if (cmd.startsWith("GET ")) {
String filename = cmd.substring(4);
sendFile(out, new File(Environment.getExternalStorageDirectory(), filename));
}
} catch (IOException e) { e.printStackTrace(); }
}
private void sendFileList(DataOutputStream out) throws IOException {
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
File[] files = dir.listFiles();
out.writeInt(files.length);
for (File f : files) {
out.writeUTF(f.getName());
out.writeLong(f.length());
out.writeLong(f.lastModified());
}
}
private void sendFile(DataOutputStream out, File file) throws IOException {
out.writeUTF("FILE_START");
out.writeLong(file.length());
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[8192];
int len;
while ((len = fis.read(buffer)) > 0) out.write(buffer, 0, len);
}
out.writeUTF("FILE_END");
}
}
public class FileTransferClient {
public static void main(String[] args) {
try (Socket socket = new Socket("192.168.1.100", 8888);
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream())) {
out.writeUTF("LIST");
out.flush();
int count = in.readInt();
for (int i = 0; i < count; i++) {
String name = in.readUTF();
long size = in.readLong();
long modified = in.readLong();
System.out.printf("%s (%d bytes)%n", name, size);
}
// 下載特定檔案
out.writeUTF("GET photo.jpg");
out.flush();
String status = in.readUTF();
if ("FILE_START".equals(status)) {
long size = in.readLong();
try (FileOutputStream fos = new FileOutputStream("download/photo.jpg")) {
byte[] buffer = new byte[8192];
long received = 0;
while (received < size) {
int len = in.read(buffer, 0, (int) Math.min(buffer.length, size - received));
fos.write(buffer, 0, len);
received += len;
}
}
}
} catch (IOException e) { e.printStackTrace(); }
}
}
adb forward tcp:8888 tcp:8888 映射端口INTERNET、READ_EXTERNAL_STORAGE 權限Range 請求,傳輸大檔案更可靠