Передача файлов с Mac на устройство Bluetooth, простой пример?

Я потратил два дня на поиск в Google и чтение руководства по программированию Bluetooth, пытаясь собрать воедино небольшое приложение для Mac, которое будет извлекать изображения из папки drop и отправлять любые новые файлы на заданное устройство через Bluetooth. Кажется, что существует не так много хороших примеров.

Я нахожусь в точке, где я могу запустить браузер службы Bluetooth и выбрать устройство и его службу 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

person nordhagen    schedule 01.08.2012    source источник
comment
Вы когда-нибудь добивались прогресса в этом?   -  person shein    schedule 25.07.2013
comment
да. В конце концов, у меня все заработало, но это год назад, и у меня нет деталей в голове. Наверное, мне следовало обновить ветку. Я посмотрю, найду ли время в эти выходные.   -  person nordhagen    schedule 26.07.2013
comment
Будет бесконечно признателен!   -  person shein    schedule 28.07.2013


Ответы (1)


В ПОРЯДКЕ; вот что в конечном итоге стало основными частями функциональности. Приложение, которое я сделал, было своего рода сервером печати для принтеров мгновенной печати 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];
}

Я надеюсь, что это помогает кому-то!

person nordhagen    schedule 30.07.2013
comment
Привет, Нордаген, не могли бы вы предоставить остальные классы для этого проекта? Мне нужно то же самое для моего офиса, и я не мог найти учебников о том, как отправлять файлы на Bluetooth-принтер в Mac OS. - person Jukurrpa; 19.03.2014
comment
Извините, я бы сделал, если бы мог, но я не вправе делиться этим. Это была работа для клиента на моей предыдущей работе. Однако представленный здесь код должен предоставить вам основные механизмы, необходимые для передачи файла. - person nordhagen; 21.03.2014
comment
Нет проблем, тем временем я нашел рабочий пример, который можно использовать повторно. - person Jukurrpa; 21.03.2014
comment
Привет, Юкуррпа, не могли бы вы опубликовать ссылку на этот пример? - person Pier; 30.06.2014
comment
@Jukurrpa Есть ли шанс, что вы могли бы опубликовать свой рабочий пример, который вы нашли? Спасибо - person Mattias; 08.12.2014
comment
Прости. См. Ответ тремя строчками вверх. - person nordhagen; 09.12.2014