GKSession - что делать, если у меня отключены Bluetooth и Wi-Fi? - PullRequest
11 голосов
/ 21 февраля 2010

Я работаю над приложением для iPhone, которое позволит одноранговые соединения. Из того, что я понимаю, у меня есть выбор между использованием GKPeerPicker или GKSession. Мне не нравится идея использования PeerPicker, потому что я хочу показать пользовательский интерфейс, поэтому я решил использовать GKSession, и, кстати, BONUS работает и через Wi-Fi, а Peer Picker - нет.

ОК, проблема в том ... что если у пользователя отключены Bluetooth и Wi-Fi? В Peer Picker есть приглашение включить Bluetooth без выхода из приложения. У GKSession его нет ... но, подождите секунду, кажется, что я даже не могу проверить, включен ли Bluetooth программно или нет!

Carpe Cocoa утверждает, что не проблема , просто используйте метод делегата session:didFailWithError:. Но, как это объясняется в комментариях ... это больше не работает! И по своему опыту я согласен.

Есть ли другой способ программно проверить, включен ли Bluetooth? Это то, что я должен использовать Reachability для? Или это просто ошибка, которую Apple еще не исправила?

Если быть более точным, я создаю свою сессию так:

GKSession *aSession = [[GKSession alloc] initWithSessionID:nil
                                                  displayName:user.displayName 
                                                  sessionMode:GKSessionModePeer];

self.gkSession = aSession;
[aSession release];

self.gkSession.delegate = self;
self.gkSession.available = YES;

[self.gkSession setDataReceiveHandler:self withContext:NULL];

Класс реализует GKSessionDelegate, и я знаю, что он работает, потому что когда у меня включен bluetooth, методы делегата не вызывают проблем. Я реализовал их так:

#pragma mark -
#pragma mark GKSessionDelegate methods

- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state {
     if (GKPeerStateAvailable == state) {
          [session connectToPeer:peerID withTimeout:10];
     } else if (GKPeerStateConnected == state) {
          // gets user

          NSError *error = nil;
          [session sendData:user.connectionData
                      toPeers:[NSArray arrayWithObjects:peerID,nil]
                withDataMode:GKSendDataReliable error:&error];
          if (error)
               NSLog(@"%@",error);
     }
}



- (void)session:(GKSession *)session didReceiveConnectionRequestFromPeer:(NSString *)peerID {
     NSError *error = nil;
     [session acceptConnectionFromPeer:peerID error:&error];
     if (error)
          NSLog(@"%@",error);
}

- (void)session:(GKSession *)session connectionWithPeerFailed:(NSString *)peerID withError:(NSError *)error {
     NSLog(@"%@",error);
}

- (void)session:(GKSession *)session didFailWithError:(NSError *)error {
     NSLog(@"%@",error);
}

Ни одна из инструкций журнала не печатается, и я устанавливаю точки останова в каждом методе, но ни одна из них не срабатывает, когда у пользователя отключены Bluetooth и Wi-Fi. Я надеялся, что что-то произойдет, чтобы вызвать сеанс: didFailWithError: чтобы я мог предложить пользователю включить Bluetooth или подключиться к сети Wi-Fi.

Ответы [ 6 ]

2 голосов
/ 10 августа 2012

Теперь в iOS 5 это можно сделать так:

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
NSMutableArray * discoveredPeripherals = [NSMutableArray new];
CBCentralManager * manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
[manager scanForPeripheralsWithServices:discoveredPeripherals options:options];
[manager stopScan];

Для этого необходимо импортировать инфраструктуру CoreBluetooth в iOS 5. Если Bluetooth выключен, система отобразит окно с предупреждением, в котором будет предложено включить Bluetooth. В противном случае, если он найдет периферийное устройство, он вызовет соответствующий метод делегата, но если в этой реализации ничего нет, вам не нужно об этом беспокоиться.

1 голос
/ 07 октября 2010

Интересный момент, вы пробовали протестировать его с выключенным Bluetooth и включенным WiFi? Недавно я узнал, что, хотя моя программа назвала это сообщение «Bluetooth недоступен», на самом деле он не использовал Bluetooth ВСЕ, а подключался через мою сеть WiFi. Я не знаю способа заставить GKSession подключиться к Bluetooth без использования объекта Apple PeerPicker, но объект PeerPicker позволяет людям создавать свои собственные интерфейсы. Кажется, что это не позволяет использовать типы соединений, отличные от Peer, поэтому, если вы хотите, чтобы клиент-серверное расположение было не слишком полезным,

-Ash

1 голос
/ 02 марта 2010

Я согласен с Мартином Гордоном, но возможен обходной путь: достижимость Apple .

0 голосов
/ 21 сентября 2011

Я придерживаюсь идеи использования доступности Apple. В качестве бонуса он указан в качестве одного из правил подачи заявок в Apple App Store.

Это не так сложно реализовать, так как большая часть необходимого кода уже написана для вас.

Slf предоставил ссылку на некоторый исходный код с использованием класса Reachability, кроме того, вот ссылка на официальный пример достижимости Apple Dev .

Однако убедитесь, что вы проверяете возможность подключения асинхронно.

Я использую его в своем приложении, и хотя это не лучшее решение, по крайней мере, оно уведомляет пользователя о том, что ему / ей нужно настроить параметры соединения или что сети не существуют.

0 голосов
/ 18 августа 2011

Вы должны использовать тот же sessionID.

0 голосов
/ 10 августа 2011

Вы можете включить Blutooth программно, используя частный API Apple (я думаю, BluetoothManger.h), но будьте осторожны, это вызовет отклонение в Apple App Store.

...