質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

【ios】bluetoothのアドバタイズ時にサムネイル画像を表示したい

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 1,164

9_zaku

score 10

bluetooth(フレームワーク:multipeer connectivity )を使ってチャットの送受信するアプリを作ろうとしています。
その際にアドバタイズする情報に自分で設定したサムネイル画像を送信し、相手側の端末でデバイス検索時に、相手の端末名と共にそのサムネイル画像も表示したいのですが、うまくいきません。
もちろん、一度端末同時が接続してしまえば、画像を送信することはできます。
しかし、やりたいことは、端末同士が接続する前の端末を検知した時点で、相手の設定した画像情報を取得して表示したいのです。

やり方としては、アドバタイズする際にMCAdvertiserAssistantを作成する際のサービスタイプの詳細情報(info)に画像データ(NSData)をセットする方法かと思うのですが、アプリが引数エラーで異常終了します。

画像データの大きさが問題なのかと思いましたが、どんなに頑張っても700byteくらいにしか小さくできませんでした。
以下にコードのサンプルを掲載します。
コード
         UIImage *imageToSave = [UIImage imageNamed:@"flower.jpg"];
        
        /* 画像をリサイズする*/
        CGSize resize = CGSizeMake(10, 10);
        
        // Create a graphics image context
        UIGraphicsBeginImageContext(resize);
        [imageToSave drawInRect:CGRectMake(0,0,resize.width,resize.height)];
        UIImage* resizedImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        NSData *jpgData = [[NSData alloc] initWithData:UIImageJPEGRepresentation(resizedImage, 0.1)];        
        // infoにメッセージをセットする
        [info setObject:jpgData forKey:@"image"];
        
        _nearbyServiceAdvertiser = [[MCNearbyServiceAdvertiser alloc] initWithPeer:peerID
                                                                     discoveryInfo:info
                                                                       serviceType:serviceType]; 
RFC6763のSection6にアドバタイズ時の詳細情報(info)のkey/valueの
記載がありますが、バイナリデータを送信しても問題ないような記載があります。
リンク内容

また、bluetooth(フレームワーク:multipeer connectivity )を使ってると思われる類似のiosアプリ『偶然の出会い』では、bluetoothのみで相手のサムネイル画像を表示する機能がありました。

どなたかもしご存じの方がいましたら、ご教授をお願いします。



  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

discoveryInfoの型が、
NSDictionary<NSString *, NSString *> 
と、キーも値もNSStringになっていますので、NSDataをBase64でエンコードしてみてはどうでしょうか?
参考URL:iOS 7 では標準で NSData の base64 エンコードが出来るようになりました / Qiita

また、サイズ制限を疑うのであれば、画像以外のデータ(文字列とか)をNSData化して試してみればよいと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/09 14:49

    fuzzball様
    ご回答して頂きありがとうございます。

    discoveryInfoの型が、
    NSDictionary<NSString *, NSString *> とのご指摘まさにその通りでした。
    そこで、ご紹介して頂いきました記事と次の参考URLを元にNSdataをBase64でエンコードしてみました
    参考のURL:http://qiita.com/katsuhisaishii/items/76d5eb76317148662eab

    ------------------------コード開始-------------------------
    NSData *jpgData = [[NSData alloc] initWithData:UIImageJPEGRepresentation(resizedImage, 0.1)];
    NSString *base64str = [jpgData base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    [info setObject:base64str forKey:@"image"];
    ------------------------コード終了-------------------------

    結果、次の様な引数エラーとなりました。
    Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid discoveryInfo passed to MCNearbyServiceAdvertiser'


    また、サイズの方ですが文字列型(NSString)で全角約90文字でエラーとなり、80文字ではエラーとなりませんでした。
    よって160byteくらいが送信の限界なのでしょうか。
    念のためサンプルコードを以下に記載します。
    ------------------------コード開始-------------------------
    NSString *displayMessage="あいうえおかきくけこさしすせそ・・・"
    [info setObject:displayMessage forKey:@"message"];
    ------------------------コード終了-------------------------

    質問ばかりで恐縮ですが、
    画像データを160byte以下のサイズにすることは可能なのでしょうか?

    キャンセル

  • 2015/11/09 17:43

    まともな画像で160バイト以下というのは無理でしょうね。
    Bluetooth関係は実際に使ったことが無いので、これ以上はお役に立てそうにありません。

    キャンセル

  • 2015/11/09 18:22

    fuzzball様
    度々ご回答して頂きありがとうございます。

    試行錯誤した結果、端末を検知した時点で、相手の設定した画像情報を取得して表示することが不完全ながら可能となりました。
    不完全というのは、画像が送信元の画像と完全に同じに復元はできませんが、ある程度の精度で復元できたということです。

    やり方としましては、
    【送信側】
    ①画像データ(NSData)をNSRange(150byte)で分割
    ②①で分割したNSDataをNSString型にbase64エンコード
    ③base64エンコードしたものをそれぞれdiscoveryInfoにセット

    【受信側】
    ①受信したNSStringを順番に結合
    ②結合したNSStringをbase64デコードしてNSDataを復元
    ③NSDataから画像を作成

    ソースは以下の通りです。
    ーーーーー【送信側】ーーーーー
    /* 画像をリサイズする場合*/
    CGSize resize = CGSizeMake(100, 100);
    UIGraphicsBeginImageContext(resize);
    [imageToSave drawInRect:CGRectMake(0,0,resize.width,resize.height)];
    UIImage* resizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    NSData *jpgData = [[NSData alloc] initWithData:UIImageJPEGRepresentation(resizedImage, 0.1)];

    // jpgDataのサイズは1817
    NSRange range1;
    range1.location = 0;
    range1.length = 149;
    NSRange range2;
    range2.location = 150;
    range2.length = 149;
    NSRange range3;
    range3.location = 300;
    range3.length = 149;
    NSRange range4;
    range4.location = 450;
    range4.length = 149;
    NSRange range5;
    range5.location = 600;
    range5.length = 149;
    NSRange range6;
    range6.location = 750;
    range6.length = 149;
    NSRange range7;
    range7.location = 900;
    range7.length = 149;
    NSRange range8;
    range8.location = 1050;
    range8.length = 149;
    NSRange range9;
    range9.location = 1200;
    range9.length = 149;
    NSRange range10;
    range10.location = 1350;
    range10.length = 149;
    NSRange range11;
    range11.location = 1500;
    range11.length = 149;
    NSRange range12;
    range12.location = 1650;
    range12.length = 149;
    NSRange range13;
    range13.location = 1800;
    range13.length = 17;

    NSData *jpgDataPart1 = [jpgData subdataWithRange:range1];
    NSData *jpgDataPart2 = [jpgData subdataWithRange:range2];
    NSData *jpgDataPart3 = [jpgData subdataWithRange:range3];
    NSData *jpgDataPart4 = [jpgData subdataWithRange:range4];
    NSData *jpgDataPart5 = [jpgData subdataWithRange:range5];
    NSData *jpgDataPart6 = [jpgData subdataWithRange:range6];
    NSData *jpgDataPart7 = [jpgData subdataWithRange:range7];
    NSData *jpgDataPart8 = [jpgData subdataWithRange:range8];
    NSData *jpgDataPart9 = [jpgData subdataWithRange:range9];
    NSData *jpgDataPart10 = [jpgData subdataWithRange:range10];
    NSData *jpgDataPart11 = [jpgData subdataWithRange:range11];
    NSData *jpgDataPart12 = [jpgData subdataWithRange:range12];
    NSData *jpgDataPart13 = [jpgData subdataWithRange:range13];

    NSString *base64str1 = [jpgDataPart1 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    NSString *base64str2 = [jpgDataPart2 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    NSString *base64str3 = [jpgDataPart3 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    NSString *base64str4 = [jpgDataPart4 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    NSString *base64str5 = [jpgDataPart5 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    NSString *base64str6 = [jpgDataPart6 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    NSString *base64str7 = [jpgDataPart7 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    NSString *base64str8 = [jpgDataPart8 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    NSString *base64str9 = [jpgDataPart9 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    NSString *base64str10 = [jpgDataPart10 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    NSString *base64str11 = [jpgDataPart11 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    NSString *base64str12 = [jpgDataPart12 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    NSString *base64str13 = [jpgDataPart13 base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];

    [info setObject:base64str1 forKey:@"image1"];
    [info setObject:base64str2 forKey:@"image2"];
    [info setObject:base64str3 forKey:@"image3"];
    [info setObject:base64str4 forKey:@"image4"];
    [info setObject:base64str5 forKey:@"image5"];
    [info setObject:base64str6 forKey:@"image6"];
    [info setObject:base64str7 forKey:@"image7"];
    [info setObject:base64str8 forKey:@"image8"];
    [info setObject:base64str9 forKey:@"image9"];
    [info setObject:base64str10 forKey:@"image10"];
    [info setObject:base64str11 forKey:@"image11"];
    [info setObject:base64str12 forKey:@"image12"];
    [info setObject:base64str13 forKey:@"image13"];

    _nearbyServiceAdvertiser = [[MCNearbyServiceAdvertiser alloc] initWithPeer:peerID discoveryInfo:info serviceType:serviceType];

    ーーーーー【受信側】ーーーーー
    // infoからimageを取得
    NSString *image1 = [info objectForKey:@"image1"];
    NSString *image2 = [info objectForKey:@"image2"];
    NSString *image3 = [info objectForKey:@"image3"];
    NSString *image4 = [info objectForKey:@"image4"];
    NSString *image5 = [info objectForKey:@"image5"];
    NSString *image6 = [info objectForKey:@"image6"];
    NSString *image7 = [info objectForKey:@"image7"];
    NSString *image8 = [info objectForKey:@"image8"];
    NSString *image9 = [info objectForKey:@"image9"];
    NSString *image10 = [info objectForKey:@"image10"];
    NSString *image11 = [info objectForKey:@"image11"];
    NSString *image12 = [info objectForKey:@"image12"];
    NSString *image13 = [info objectForKey:@"image13"];

    // データを結合する
    NSString *base64str = [NSString stringWithFormat:@"%@%@%@%@%@%@%@%@%@%@%@%@%@",
    image1,image2,image3,image4,image5,image6,image7,image8,
    image9,image10,image11,image12,image13];

    // NSDataにBase64エンコードする
    NSData *jpgData = [[NSData alloc] initWithBase64EncodedString:base64str
    options:NSDataBase64DecodingIgnoreUnknownCharacters];

    画像の復元が不完全ではありますが、
    fuzzball様の助言のおかげで目的をほぼ達成することができましたので、
    解決済みとさせて頂きます。
    本当にありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る