5

ドロップ フォルダーから画像を取得し、新しいファイルを Bluetooth 経由で所定のデバイスに送信する小さな Mac アプリをまとめようとしながら、Bluetooth プログラミング ガイドをグーグルで調べて読むのに 2 日間を費やしました。有効な例はあまりないようです。

Bluetooth サービス ブラウザを起動し、デバイスとその OBEX サービスを選択して、サービスを確立し、接続を確立できるところまで来ましたが、それ以上何も起こりません。うまくいく簡単な例を教えてください。

AppDelegate のソース コードが同封されています。読んでくれてありがとう!

#import "AppDelegate.h"

@implementation AppDelegate

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

    IOBluetoothServiceBrowserController *browser = [IOBluetoothServiceBrowserController serviceBrowserController:0];
    [ブラウザ runModal];

    //IOBluetoothSDPServiceRecord
    IOBluetoothSDPServiceRecord *result = [[browser getResults] objectAtIndex:0];
    [自己記述:結果];

    if ([[result.device.name substringToIndex:8] isEqualToString:@"ポラロイド"]) {
        プリンター = 結果.デバイス;
        serviceRecord = 結果;
        [自己テスト印刷];
    }
    そうしないと {
        NSLog(@"%@ は有効なデバイスではありません", result.device.name);
    }
}

- (無効) 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 セッションが確立されました");

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

        OBEXError cnctResult = [fst connectToObjectPushService];

        if( cnctResult != kIOReturnSuccess ) {
            NSLog(@"接続作成エラー");
            戻る;
        }
        そうしないと {
            NSLog(@"OBEX セッションが作成されました。送信ファイル: %@", filePath);
            [fst sendFile:ファイルパス];
            [プリンターopenConnection];
        }
    }
    そうしないと {
        NSLog(@"OBEX セッションの作成エラー");
        NSLog(@"ファイル送信エラー");
    }
}

@終わり
4

1 に答える 1

2

わかった; 最終的に機能のコア部分になったのは次のとおりです。私が作成したアプリケーションは、オブジェクト プッシュ経由でのみ画像を受け入れるポラロイド インスタント プリンター用の一種のプリント サーバーでした。

まず、監視フォルダーが存在することを確認します。

/*

    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++;
            }
        }
    }
}

新しいファイルが見つかったら、ww は最初に、印刷用のファイルを受信して​​いないデバイスを見つける必要があります。

/*

 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];
}

これが誰かに役立つことを願っています!

于 2013-07-30T10:07:15.927 に答える