Skip to content

Commit a8c84a8

Browse files
committed
Call libimobiledevice using JNA instead of executable(fixes reading from device on Windows)
1 parent 708d531 commit a8c84a8

File tree

5 files changed

+313
-206
lines changed

5 files changed

+313
-206
lines changed

build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ dependencies {
3838
compile fileTree(dir: 'libs', include: ['*.jar'])
3939
compile group: 'it.sauronsoftware', name: 'junique', version: '1.0.4'
4040
compile "de.codecentric.centerdevice:centerdevice-nsmenufx:2.1.6"
41+
compile 'net.java.dev.jna:jna:5.2.0'
42+
43+
testCompile 'junit:junit:4.12'
4144
}
4245

4346
compileJava {

src/main/java/com/airsquared/blobsaver/Controller.java

Lines changed: 27 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838

3939
import java.awt.Desktop;
4040
import java.io.File;
41-
import java.io.FileNotFoundException;
4241
import java.io.IOException;
4342
import java.io.InputStream;
4443
import java.net.URL;
@@ -200,10 +199,6 @@ public void handle(WindowEvent event) {
200199
}
201200
});
202201
}
203-
204-
if (!PlatformUtil.isMac()) {
205-
readFromConnectedDeviceButton.setText("Read from connected device(beta)");
206-
}
207202
}
208203

209204
private static void addListenerToSetNullEffect(TextField... textFields) {
@@ -1014,183 +1009,49 @@ public void showWiki(ActionEvent event) {
10141009
openURL(url);
10151010
}
10161011

1017-
@SuppressWarnings({"unchecked", "UnnecessaryReturnStatement"})
1012+
@SuppressWarnings("unchecked")
10181013
public void readInfo() {
1019-
if (!PlatformUtil.isMac()) {
1020-
String alertText;
1021-
if (PlatformUtil.isWindows()) {
1022-
alertText = "This feature will most likely not work, but you can give it a try. If this feature doesn't work, please don't report this bug to me, I already know and am trying to fix it.";
1023-
} else {
1024-
alertText = "IMPORTANT: make sure to install libimobiledevice before running it and `ideviceinfo` and `idevicepair` are in your $PATH\n\nThis feature is in beta, and may or may not work. Please report any bugs with this feature to me using the help menu.";
1025-
}
1026-
Alert confirmationAlert = new Alert(Alert.AlertType.CONFIRMATION, alertText);
1027-
confirmationAlert.showAndWait();
1028-
if (confirmationAlert.getResult().equals(ButtonType.CANCEL)) {
1029-
return;
1030-
}
1031-
}
1032-
String idevicepairPath;
1033-
try {
1034-
idevicepairPath = getidevicepair().getPath();
1035-
} catch (FileNotFoundException e) {
1036-
if ("idevicepair is not in $PATH".equals(e.getMessage())) {
1037-
newUnreportableError("Either idevicepair is not in the $PATH, or libimobiledevice is not installed. Please install it before continuing");
1038-
} else {
1039-
e.printStackTrace();
1040-
}
1041-
return;
1042-
} catch (IOException ioe) {
1043-
ioe.printStackTrace();
1044-
return;
1045-
}
1046-
// validate pairing status
1047-
try {
1048-
String idevicepairResult = executeProgram(idevicepairPath, "pair").trim();
1049-
log("idevicepair: " + idevicepairResult);
1050-
//noinspection StatementWithEmptyBody
1051-
if (idevicepairResult.contains("Paired with device")) {
1052-
// continue
1053-
} else if (idevicepairResult.contains("dyld: Library not loaded:")) {
1054-
deleteFolder(new File(System.getProperty("user.home", ".blobsaver_bin")));
1055-
newUnreportableError("This error will happen if you have used version v2.2 before. This error will automatically be fixed after restarting the application.");
1056-
Platform.exit();
1057-
System.exit(-1);
1058-
return;
1059-
} else if (idevicepairResult.contains("Please accept the trust dialog")) {
1060-
newUnreportableError("Please accept the trust dialog on the device");
1061-
return;
1062-
} else if (idevicepairResult.contains("No device found")) {
1063-
newUnreportableError("No device found, is it plugged in?");
1064-
return;
1065-
} else if (idevicepairResult.contains("ERROR") && idevicepairResult.contains("a passcode is set")) {
1066-
newUnreportableError("Please unlock your device.");
1067-
return;
1068-
} else if (idevicepairResult.contains("Device") && idevicepairResult.contains("returned unhandled error code -13")) {
1069-
newUnreportableError("Please disconnect your device, unlock it, plug it back in, and try again. If this doesn't work, please create a new Github issue or PM me on Reddit via the help menu.");
1070-
return;
1071-
} else if (idevicepairResult.contains("ERROR")) {
1072-
newReportableError("idevicepair error.", idevicepairResult);
1073-
return;
1074-
} else {
1075-
newReportableError("Unknown idevicepair result: " + idevicepairResult, idevicepairResult);
1076-
return;
1077-
}
1078-
} catch (IOException e) {
1079-
e.printStackTrace();
1080-
newReportableError("Unable to validate pairing.", e.getMessage());
1081-
}
1082-
String ideviceinfoPath;
1083-
try {
1084-
ideviceinfoPath = getideviceinfo().getPath();
1085-
} catch (FileNotFoundException e) {
1086-
if ("ideviceinfo is not in $PATH".equals(e.getMessage())) {
1087-
newUnreportableError("Either ideviceinfo is not in the $PATH, or libimobiledevice is not installed. Please install it or add it to the path before continuing");
1088-
} else {
1089-
e.printStackTrace();
1090-
}
1091-
return;
1092-
} catch (IOException ioe) {
1093-
ioe.printStackTrace();
1094-
return;
1095-
}
1096-
// read ECID
1097-
try {
1098-
String ideviceinfoResult = executeProgram(ideviceinfoPath, "-k", "UniqueChipID").trim();
1099-
log("ideviceinfo -k UniqueChipID:" + ideviceinfoResult);
1100-
if (ideviceinfoResult.contains("ERROR: Could not connect to lockdownd")) {
1101-
newReportableError("ideviceinfo:" + ideviceinfoResult, ideviceinfoResult);
1102-
return;
1103-
} else if (ideviceinfoResult.contains("dyld: Library not loaded:")) {
1104-
version2dot2libimobiledeviceError();
1105-
return;
1106-
} else if (ideviceinfoResult.contains("No device found")) {
1107-
newUnreportableError("No device found, is it plugged in?");
1108-
return;
1109-
} else if (ideviceinfoResult.contains("ERROR")) {
1110-
newReportableError("ideviceinfo error.", ideviceinfoResult);
1014+
readFromConnectedDeviceButton.setText("Reading...");
1015+
readFromConnectedDeviceButton.setDisable(true);
1016+
if (!PlatformUtil.isMac() && !PlatformUtil.isWindows()) {
1017+
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
1018+
alert.setContentText("IMPORTANT: make sure to install libimobiledevice and have it in your path before running this.");
1019+
alert.showAndWait();
1020+
if (alert.getResult().equals(ButtonType.CANCEL)) {
11111021
return;
1112-
} else {
1113-
try {
1114-
ecidField.setText(Long.toHexString(Long.valueOf(ideviceinfoResult)).toUpperCase());
1115-
} catch (Exception e) {
1116-
e.printStackTrace();
1117-
newReportableError("Unknown ideviceinfo(ecid) result: " + ideviceinfoResult, ideviceinfoResult);
1118-
return;
1119-
}
11201022
}
1121-
} catch (IOException e) {
1122-
e.printStackTrace();
1123-
newReportableError("Unable to get ECID.", e.getMessage());
11241023
}
1125-
// read device model
11261024
try {
1127-
String ideviceinfoResult = executeProgram(ideviceinfoPath, "-k", "ProductType").trim();
1128-
log("ideviceinfo -k ProductType: " + ideviceinfoResult);
1129-
if (ideviceinfoResult.contains("ERROR: Could not connect to lockdownd")) {
1130-
newReportableError("ideviceinfo:" + ideviceinfoResult, ideviceinfoResult);
1131-
return;
1132-
} else if (ideviceinfoResult.contains("dyld: Library not loaded:")) {
1133-
version2dot2libimobiledeviceError();
1134-
return;
1135-
} else if (ideviceinfoResult.contains("No device found")) {
1136-
newUnreportableError("No device found, is it plugged in?");
1137-
return;
1138-
} else if (ideviceinfoResult.contains("ERROR")) {
1139-
newReportableError("ideviceinfo error.", ideviceinfoResult);
1140-
} else if (ideviceinfoResult.startsWith("iPhone")) {
1025+
// read ECID
1026+
ecidField.setText(Long.toHexString(Libimobiledevice.getEcid(true)).toUpperCase());
1027+
// read device model
1028+
String deviceModel = Libimobiledevice.getDeviceModelIdentifier(true);
1029+
if (deviceModel.startsWith("iPhone")) {
11411030
deviceTypeChoiceBox.setValue("iPhone");
1142-
deviceModelChoiceBox.setValue(Devices.getDeviceModelIdentifiersMap().getOrDefault(ideviceinfoResult, null));
1143-
} else if (ideviceinfoResult.startsWith("iPod")) {
1031+
deviceModelChoiceBox.setValue(Devices.getDeviceModelIdentifiersMap().get(deviceModel));
1032+
} else if (deviceModel.startsWith("iPod")) {
11441033
deviceTypeChoiceBox.setValue("iPod");
1145-
deviceModelChoiceBox.setValue(Devices.getDeviceModelIdentifiersMap().get(ideviceinfoResult));
1146-
} else if (ideviceinfoResult.startsWith("iPad")) {
1034+
deviceModelChoiceBox.setValue(Devices.getDeviceModelIdentifiersMap().get(deviceModel));
1035+
} else if (deviceModel.startsWith("iPad")) {
11471036
deviceTypeChoiceBox.setValue("iPad");
1148-
deviceModelChoiceBox.setValue(Devices.getDeviceModelIdentifiersMap().get(ideviceinfoResult));
1149-
} else if (ideviceinfoResult.startsWith("AppleTV")) {
1037+
deviceModelChoiceBox.setValue(Devices.getDeviceModelIdentifiersMap().get(deviceModel));
1038+
} else if (deviceModel.startsWith("AppleTV")) {
11501039
deviceTypeChoiceBox.setValue("Apple TV");
1151-
deviceModelChoiceBox.setValue(Devices.getDeviceModelIdentifiersMap().get(ideviceinfoResult));
1040+
deviceModelChoiceBox.setValue(Devices.getDeviceModelIdentifiersMap().get(deviceModel));
11521041
} else {
1153-
newReportableError("Unknown ideviceinfo(device model) result: " + ideviceinfoResult, ideviceinfoResult);
1042+
newReportableError("Unknown model: " + deviceModel);
11541043
return;
11551044
}
1156-
} catch (IOException e) {
1157-
e.printStackTrace();
1158-
newReportableError("Unable to get device model.", e.getMessage());
1159-
}
1160-
// read board config
1161-
if (!boardConfigField.isDisabled()) {
1162-
try {
1163-
String ideviceinfoResult = executeProgram(ideviceinfoPath, "-k", "HardwareModel").trim();
1164-
log("ideviceinfo -k HardwareModel: " + ideviceinfoResult);
1165-
if (ideviceinfoResult.contains("ERROR: Could not connect to lockdownd")) {
1166-
newReportableError("ideviceinfo:" + ideviceinfoResult, ideviceinfoResult);
1167-
return;
1168-
} else if (ideviceinfoResult.contains("dyld: Library not loaded:")) {
1169-
version2dot2libimobiledeviceError();
1170-
return;
1171-
} else if (ideviceinfoResult.contains("No device found")) {
1172-
newUnreportableError("No device found, is it plugged in?");
1173-
return;
1174-
} else if (ideviceinfoResult.contains("ERROR")) {
1175-
newReportableError("ideviceinfo error.", ideviceinfoResult);
1176-
return;
1177-
} else {
1178-
boardConfigField.setText(ideviceinfoResult);
1179-
}
1180-
} catch (IOException e) {
1181-
e.printStackTrace();
1182-
newReportableError("Unable to get board config.", e.getMessage());
1045+
// read board config
1046+
if (!boardConfigField.isDisabled()) {
1047+
boardConfigField.setText(Libimobiledevice.getBoardConfig(true));
11831048
}
1049+
} finally {
1050+
readFromConnectedDeviceButton.setDisable(false);
1051+
readFromConnectedDeviceButton.setText("Read from connected device");
11841052
}
11851053
}
11861054

1187-
private void version2dot2libimobiledeviceError() {
1188-
deleteFolder(new File(System.getProperty("user.home", ".blobsaver_bin")));
1189-
newUnreportableError("This error will happen if you have used version v2.2 before. This error will automatically be fixed after restarting the application.");
1190-
Platform.exit();
1191-
System.exit(-1);
1192-
}
1193-
11941055
public void donate() { openURL("https://www.paypal.me/airsqrd"); }
11951056

11961057
private static void log(String msg) { System.out.println(msg); }

0 commit comments

Comments
 (0)