Mac到蓝牙设备文件传输,简单的例子?

时间:2012-08-01 09:34:40

标签: objective-c macos cocoa bluetooth iobluetooth

我花了两天时间用谷歌搜索和阅读蓝牙编程指南,同时尝试拼凑一个小型Mac应用程序,该应用程序将从drop文件夹中检索图像,并通过蓝牙将任何新文件发送到预定设备。似乎没有很多好的例子。

我正处于能够产生蓝牙服务浏览器并选择设备及其OBEX服务,建立服务和创建连接的地步,但之后不再发生任何事情。谁能指点我/向我展示一个可行的简单例子?

附上AppDelegate源代码。谢谢你的阅读!

#import "AppDelegate.h"

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    IOBluetoothServiceBrowserController *browser = [IOBluetoothServiceBrowserController serviceBrowserController:0];
    [browser runModal];

    //IOBluetoothSDPServiceRecord
    IOBluetoothSDPServiceRecord *result = [[browser getResults] objectAtIndex:0];
    [self describe:result];

    if ([[result.device.name substringToIndex:8] isEqualToString:@"Polaroid"]) {
        printer = result.device;
        serviceRecord = result;
        [self testPrint];
    }
    else {
        NSLog(@"%@ is not a valid device", result.device.name);
    }
}

- (void) testPrint {
     currentFilePath = @"/Users/oyvind/Desktop/_DSC8797.jpg";
    [self sendFile:currentFilePath];
}

- (void) sendFile:(NSString *)filePath {
    IOBluetoothOBEXSession *obexSession = [[IOBluetoothOBEXSession alloc] initWithSDPServiceRecord:serviceRecord];

    if( obexSession != nil )
    {
        NSLog(@"OBEX Session Established");

        OBEXFileTransferServices *fst = [OBEXFileTransferServices withOBEXSession:obexSession];
        OBEXDelegate *obxd = [[OBEXDelegate alloc] init];
        [obxd setFile:filePath];
        [fst setDelegate:obxd];

        OBEXError cnctResult = [fst connectToObjectPushService];

        if( cnctResult != kIOReturnSuccess ) {
            NSLog(@"Error creating connection");
            return;
        }
        else {
            NSLog(@"OBEX Session Created. Sending file: %@", filePath);
            [fst sendFile:filePath];
            [printer openConnection];
        }
    }
    else {
        NSLog(@"Error creating OBEX session");
        NSLog(@"Error sending file");
    }
}

@end

1 个答案:

答案 0 :(得分:2)

行;这里最终成为功能的核心部分。我制作的应用程序是Polaroid即时打印机的一种打印服务器,它只能通过Object Push接受图像。

首先,确保监视文件夹存在。

/*

    Looks for a directory named PolaroidWatchFolder in the user's desktop directory
    and creates it if it does not exist.

 */

- (void) ensureWatchedFolderExists {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSURL *url = [NSURL URLWithString:@"PolaroidWatchFolder" relativeToURL:[[fileManager URLsForDirectory:NSDesktopDirectory inDomains:NSUserDomainMask] objectAtIndex:0]];
    BOOL isDir;
    if ([fileManager fileExistsAtPath:[url path] isDirectory:&isDir] && isDir) {
        [self log:[NSString stringWithFormat:@"Watched folder exists at %@", [url absoluteURL]]];
        watchFolderPath = url;
    }
    else {
        NSError *theError = nil;
        if (![fileManager createDirectoryAtURL:url withIntermediateDirectories:NO attributes:nil error:&theError]) {
            [self log:[NSString stringWithFormat:@"Watched folder could not be created at %@", [url absoluteURL]]];
        }
        else {
            watchFolderPath = url;
            [self log:[NSString stringWithFormat:@"Watched folder created at %@", [url absoluteURL]]];
        }
    }
}

然后扫描可用的打印机:

/*

    Loops through all paired Bluetooth devices and retrieves OBEX Object Push service records
    for each device who's name starts with "Polaroid".

 */

- (void) findPairedDevices {
    NSArray *pairedDevices = [IOBluetoothDevice pairedDevices];
    devicesTested = [NSMutableArray arrayWithCapacity:0];
    for (IOBluetoothDevice *device in pairedDevices)
    {
        if ([self deviceQualifiesForAddOrRenew:device.name])
        {
            BluetoothPushDevice *pushDevice = [[BluetoothPushDevice new] initWithDevice:device];
            if (pushDevice != nil)
            {
                [availableDevices addObject:pushDevice];
                [pushDevice testConnection];                
            }
        }
    }
}

最后一次函数调用是用于测试连接的BluetoothPushDevice的内置方法。这是响应的委托处理程序:

- (void) deviceStatusHandler: (NSNotification *)notification {
    BluetoothPushDevice *device = [notification object];
    NSString *status = [[notification userInfo] objectForKey:@"message"];

    if ([devicesTested count] < [availableDevices count] && ![devicesTested containsObject:device.name]) {
        [devicesTested addObject:device.name];
    }
}

在服务器启动时,此方法将响应计时器滴答或手动扫描运行:

- (void) checkWatchedFolder {
    NSError *error = nil;
    NSArray *properties = [NSArray arrayWithObjects: NSURLLocalizedNameKey, NSURLCreationDateKey, NSURLLocalizedTypeDescriptionKey, nil];

    NSArray *files = [[NSFileManager defaultManager]
                      contentsOfDirectoryAtURL:watchFolderPath
                      includingPropertiesForKeys:properties
                      options:(NSDirectoryEnumerationSkipsHiddenFiles)
                      error:&error];

    if (files == nil) {
        [self log:@"Error reading watched folder"];
        return;
    }

    if ([files count] > 0) {
        int newFileCount = 0;

        for (NSURL *url in files) {
            if (![filesInTransit containsObject:[url path]]) {
                NSLog(@"New file: %@", [url lastPathComponent]);
                [self sendFile:[url path]];
                newFileCount++;
            }
        }
    }
}

当找到新文件时,首先需要找到一个不忙于收到打印文件的设备:

/*

 Loops through all discovered device service records and returns the a new OBEX session for
 the first it finds that is not connected (meaning it is not currently in use, connections are
 ad-hoc per print).

 */

- (BluetoothPushDevice*) getIdleDevice {
    for (BluetoothPushDevice *device in availableDevices) {
        if ([device.status isEqualToString:kBluetoothDeviceStatusReady]) {
            return device;
        }
    }
    return nil;
}

然后使用此方法发送文件:

- (void) sendFile:(NSString *)filePath {
    BluetoothPushDevice *device = [self getIdleDevice];
        if( device != nil ) {
        NSLog(@"%@ is available", device.name);
        if ([device sendFile:filePath]) {
            [self log:[NSString stringWithFormat:@"Sending file: %@", filePath]];
            [filesInTransit addObject:filePath];
        }
        else {
            [self log:[NSString stringWithFormat:@"Error sending file: %@", filePath]];
        }
    }
    else {
        NSLog(@"No idle devices");
    }
}

传输完成后,将调用此委托方法:

/*

    Responds to BluetoothPushDevice's TransferComplete notification

 */

- (void) transferStatusHandler: (NSNotification *) notification {
    NSString *status = [[notification userInfo] objectForKey:@"message"];
    NSString *file = ((BluetoothPushDevice*)[notification object]).file;

    if ([status isEqualToString:kBluetoothTransferStatusComplete]) {
        if ([filesInTransit containsObject:file]) {
            NSFileManager *fileManager = [NSFileManager defaultManager];
            NSError *error = nil;
            [fileManager removeItemAtPath:file error:&error];
            if (error != nil) {
                [self log:[NSString stringWithFormat:@"**ERROR** File %@ could not be deleted (%@)", file, error.description]];
            }

            [self log:[NSString stringWithFormat:@"File deleted: %@", file]];
            [filesInTransit removeObject:file];
        }
        else {
            [self log:[NSString stringWithFormat:@"**ERROR** filesInTransit array does not contain file %@", file]];
        }
    }

    [self updateDeviceStatusDisplay];
}

我希望这有助于某人!