package com.mobilesorcery.sdk.ui.targetphone.internal.bt; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.window.IShellProvider; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IMemento; import org.eclipse.ui.dialogs.ListDialog; import com.mobilesorcery.sdk.core.AbstractTool; import com.mobilesorcery.sdk.core.IBuildVariant; import com.mobilesorcery.sdk.core.MoSyncProject; import com.mobilesorcery.sdk.core.MoSyncTool; import com.mobilesorcery.sdk.core.Util; import com.mobilesorcery.sdk.core.Version; import com.mobilesorcery.sdk.profiles.IDeviceFilter; import com.mobilesorcery.sdk.ui.MosyncUIPlugin; import com.mobilesorcery.sdk.ui.targetphone.ITargetPhone; import com.mobilesorcery.sdk.ui.targetphone.ITargetPhoneTransport; import com.mobilesorcery.sdk.ui.targetphone.TargetPhonePlugin; public class BTTargetPhoneTransport implements ITargetPhoneTransport { private final static Version OSX_108 = new Version("10.8"); private static void assertAvailability() throws CoreException { if (AbstractTool.isMac()) { Version version = new Version(System.getProperty("os.version")); if (version.isValid() && !version.isOlder(OSX_108)) { throw new CoreException(new Status(IStatus.ERROR, TargetPhonePlugin.PLUGIN_ID, "Bluetooth is only supported for Mac OS X before 10.8")); } } } @Override public ITargetPhone load(IMemento memento, String name) { String addr = memento.getString("addr"); Integer portInt = memento.getInteger("port"); int port = portInt == null ? -1 : portInt.intValue(); BTTargetPhone newPhone = new BTTargetPhone(name.toCharArray(), Util .fromBase16(addr), port); return newPhone; } @Override public boolean store(ITargetPhone aPhone, IMemento memento) { if (aPhone instanceof BTTargetPhone) { BTTargetPhone phone = (BTTargetPhone) aPhone; String addr = Util.toBase16(phone.getAddressAsBytes()); int port = phone.getPort(); memento.putString("addr", addr); memento.putInteger("port", phone.getPort()); return true; } else { return false; } } @Override public String getId() { return TargetPhonePlugin.DEFAULT_TARGET_PHONE_TRANSPORT; } public static IStatus assignPort(IShellProvider shellProvider, IProgressMonitor monitor, BTTargetPhone phone) { try { monitor.beginTask("Scanning BT device for OBEX service", 1); monitor.setTaskName("Scanning BT device for OBEX service"); int port = ServiceSearch.search(phone.getAddress()); if (port != -1) { phone.assignPort(port); } else { return new Status(IStatus.ERROR, TargetPhonePlugin.PLUGIN_ID, "The device connected to has no OBEX service"); } return Status.OK_STATUS; } catch (Exception e) { return new Status(IStatus.ERROR, TargetPhonePlugin.PLUGIN_ID, "The device connected to has no OBEX service", e); } finally { monitor.worked(1); } } /** * Pops up a dialog where the user can select a [BT] target phone. * * @return * @throws IOException */ public static BTTargetPhone selectPhone( final Shell shell ) throws IOException { // Use a native dialog on windows /*if( System.getProperty("os.name").toLowerCase().indexOf("win") != -1) { SearchBTDeviceDialog dialog = new SearchBTDeviceDialog( ); BTTargetPhone info = dialog.open(); return info; }*/ final ArrayList<BTTargetPhone> result = new ArrayList<BTTargetPhone>( ); shell.getDisplay().syncExec(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { BluetoothDialog ld = new BluetoothDialog( shell ); ld.open( ); if( ld.getReturnCode( ) == ListDialog.OK ) { BluetoothDevice selectedDevice = ld.getSelectedDevice(); BTTargetPhone targetDevice = selectedDevice.getTargetPhone(); ITargetPhone correspondingDevice = findInHistory(targetDevice); if (correspondingDevice != null) { targetDevice.setPreferredProfile(MoSyncTool.DEFAULT_PROFILE_TYPE, correspondingDevice.getPreferredProfile(MoSyncTool.DEFAULT_PROFILE_TYPE)); targetDevice.setPreferredProfile(MoSyncTool.LEGACY_PROFILE_TYPE, correspondingDevice.getPreferredProfile(MoSyncTool.LEGACY_PROFILE_TYPE)); } result.add(targetDevice); } } catch (Exception e) { e.printStackTrace( ); } } }); if( result.size( ) > 0) { return result.get( 0 ); } else { return null; } } /** * Returns the corresponding target phone from history - can be * used to find out if there is already a preferred profile for a device * @param btTargetPhone * @return */ public static ITargetPhone findInHistory(BTTargetPhone btTargetPhone) { List<ITargetPhone> history = TargetPhonePlugin.getDefault().getSelectedTargetPhoneHistory(); for (ITargetPhone targetPhone : history) { if (targetPhone instanceof BTTargetPhone) { if (btTargetPhone.getAddress().equals(((BTTargetPhone) targetPhone).getAddress())) { return targetPhone; } } } return null; } @Override public void send(IShellProvider shell, MoSyncProject project, IBuildVariant variant, ITargetPhone phone, File packageToSend, IProgressMonitor monitor) throws CoreException { assertAvailability(); BTSendJob job = new BTSendJob(shell, (BTTargetPhone) phone, packageToSend, project, variant); job.runSync(monitor); } @Override public ITargetPhone scan(IShellProvider shell, IProgressMonitor monitor) throws CoreException { assertAvailability(); try { BTTargetPhone phone = selectPhone( shell.getShell( ) ); if (phone != null) { IStatus status = assignPort(shell, monitor, phone); if (status.getSeverity() == IStatus.ERROR) { throw new CoreException(status); } } return phone; } catch (IOException e) { throw new CoreException(new Status(IStatus.ERROR, TargetPhonePlugin.PLUGIN_ID, e.getMessage(), e)); } } @Override public ImageDescriptor getIcon() { return MosyncUIPlugin.getDefault().getImageRegistry().getDescriptor(MosyncUIPlugin.PHONE_IMAGE); } @Override public String getDescription(String context) { return "Bluetooth"; } @Override public boolean isAvailable() { return true; } @Override public IDeviceFilter getAcceptedProfiles() { return null; } }