Pair with a bluetooth peripheral using ios 5 - ios5

I am developing a proximity sensing application using bluetooth technology 4.0. I am able to discover the devices. But I am not able to pair with them. Nor can i call [peripheral readRssi] method. The way I want to achieve this is that if the central scans for say 10 devices and after finding those many, it should stop the scan and then pair the devices and then constantly read the RSSI values.
My piece of code.
- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
BOOL (^test)(id obj, NSUInteger idx, BOOL *stop);
test = ^ (id obj, NSUInteger idx, BOOL *stop) {
if([[[obj peripheral] name] compare:peripheral.name] == NSOrderedSame)
return YES;
return NO;
};
PeripheralCell* cell;
NSUInteger t=[peripherals indexOfObjectPassingTest:test];
if(t!= NSNotFound)
{
cell=[peripherals objectAtIndex:t];
cell.peripheral=peripheral;
cell.rssi=RSSI;
//NSLog(#"%#",RSSI);
[scanResultTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:t inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
}
else{
cell=[[PeripheralCell alloc] init];
[peripherals addObject: cell];
[myPeripheral addObject: peripheral];
cell.peripheral=peripheral;
cell.rssi=RSSI;
NSLog(#"UUID===%#",[peripheral UUID]);
[scanResultTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:[peripherals count]-1 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
if([myPeripheral count]==3)
{
[manager stopScan];
for(CBPeripheral *p in myPeripheral)
{
[manager connectPeripheral:p options:nil]; //this calls didConnectPeripheral but gets disconnected after some time
[p readRssi]; //this does not work even after connecting
}
}
}
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
//self.cBReady = false;
switch (central.state) {
case CBCentralManagerStatePoweredOff:
NSLog(#"CoreBluetooth BLE hardware is powered off");
break;
case CBCentralManagerStatePoweredOn:
NSLog(#"CoreBluetooth BLE hardware is powered on and ready");
//self.cBReady = true;
break;
case CBCentralManagerStateResetting:
NSLog(#"CoreBluetooth BLE hardware is resetting");
break;
case CBCentralManagerStateUnauthorized:
NSLog(#"CoreBluetooth BLE state is unauthorized");
break;
case CBCentralManagerStateUnknown:
NSLog(#"CoreBluetooth BLE state is unknown");
break;
case CBCentralManagerStateUnsupported:
NSLog(#"CoreBluetooth BLE hardware is unsupported on this platform");
break;
default:
break;
}
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(#"connected peripheral");
}
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;
{
NSLog(#"peripheral disconnected");
}
- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error
{
NSLog(#"updated rssi");
}
how can i pair the devices...

After much searching and trail and error I found out that my code is correct. I just had to remove the devices from the ipad's Setting.
Goto Settings > General > Bluetooth > Devices.
Select the device by clicking the accessory indicator. In the next screen just click on "Forget this Device".
Running the application again solved my problem.

Related

reading battery level ble Xcode

I have written an app which I am trying to get and update the battery level on my cB-OLP425 module.
I have used the following code but sometimes it gives me a value of 70 and at other times it gives me a value of -104. I have looked at numerous posts and tried a lot of things but nothing seems to work.
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
if([service.UUID isEqual:[CBUUID UUIDWithString:#"180F"]]) {
for (CBCharacteristic *characteristic in service.characteristics) {
NSLog(#"discovered service %#", service.UUID);
if([characteristic.UUID isEqual:[CBUUID UUIDWithString:#"2A19"]]) {
NSLog(#"Found Notify Characteristic %#", characteristic.UUID);
self.mycharacteristic = characteristic;
[self.testPeripheral readValueForCharacteristic:mycharacteristic];
[self.testPeripheral setNotifyValue:YES forCharacteristic:mycharacteristic];
char batlevel;
[mycharacteristic.value getBytes:& batlevel length:0];
int n = (float)batlevel;
int value = n ;
self.batteryLevel = value;
NSLog(#"batterylevel1;%f",batteryLevel);
/* [[NSUserDefaults standardUserDefaults]setFloat: batteryLevel forKey:#"battery_level"];*/
}
} }
}
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if([characteristic.UUID isEqual:[CBUUID UUIDWithString:#"2A19"]]) {
NSLog(#"Found Battery Characteristic %#", characteristic.UUID);
[mycharacteristic.value getBytes:& batteryLevel length:0];
return;
}
[self.delegate peripheralDidReadChracteristic:mycharacteristic withPeripheral:testPeripheral withError:error];
}
Could someone please help me!!
Your getBytes seems to be the issue. We read the battery level in our app using:
UInt8 batteryLevel = ((UInt8*)value.bytes)[0];
You could also do it with:
UInt8 batteryLevel;
[value getBytes:&battery length:1];
You need to make sure the type is UInt8 otherwise you would read it into the wrong location.
Also, don't read the value right away in the didDiscoverCharacteristicsForService. Wait until you get notified that the value has been updated. The docs state:
When you attempt to read the value of a characteristic, the peripheral calls the peripheral:didUpdateValueForCharacteristic:error: method of its delegate object to retrieve the value. If the value is successfully retrieved, you can access it through the characteristic’s value property, like this:

Issue with transactionreceipt deprecated in iOS 7 warning

I am going to update my application for iOS 7 and I am using IAP , but xcode 5 give me this this error :
transactionreceipt is deprecated : first deprecated in iOS 7
here is my code :
// saves a record of the transaction by storing the receipt to disk
- (void)recordTransaction:(SKPaymentTransaction *)transaction
{
if ([transaction.payment.productIdentifier isEqualToString:kProductIdentifier])
{
// save the transaction receipt to disk
[[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:#"proUpgradeTransactionReceipt"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
how can I fix this issue ?
//EDITED :
I used my AndreyMan's answer but nothing happened and compiler gave me APP:requestProductData END message
- (void)requestProductData
{
[NSThread sleepForTimeInterval:2];
NSLog(#"IN-APP:requestProductData");
SKProductsRequest *request= [[SKProductsRequest alloc]
initWithProductIdentifiers: [NSSet setWithObject: #"com.compony.product"]];
request.delegate = self;
[request start];
NSLog(#"IN-APP:requestProductData END");
}
and then gives me these messages :
2013-10-08 14:26:21.400 Arta[1138:60b] Purchasing... 2013-10-08 14:26:28.380 Arta[1138:60b] Unknown Reason. 2013-10-08 14:26:28.383
Arta[1138:60b] Purchase faild...
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
NSLog(#"Purchase compelete...");
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
NSLog(#"Purchase faild...");
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
NSLog(#"Restore compelete...");
break;
case SKPaymentTransactionStatePurchasing:
NSLog(#"Purchasing...");
break;
default:
break;
}
}
}
- (void)failedTransaction:(SKPaymentTransaction *)transaction
{
if (transaction.error.code != SKErrorPaymentCancelled)
{
// error!
[self finishTransaction:transaction wasSuccessful:NO];
if (transaction.error.code == SKErrorClientInvalid) {
}
else if (transaction.error.code == SKErrorPaymentInvalid) {
}
else if (transaction.error.code == SKErrorPaymentNotAllowed) {
}
else if (transaction.error.code == SKErrorPaymentCancelled) {
// [self showAlert:#"In-App Purchase" withMessage:#"This device is not allowed to make the payment."];
NSLog(#"User Cancellation.");
}
else {
// SKErrorUnknown
NSLog(#"Unknown Reason.");
}
}
else {
// this is fine, the user just cancelled, so don’t notify
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
}
Something like:
NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receipt;
receipt = [NSData dataWithContentsOfURL:receiptUrl];

How to handle internet connection interruption on iOS using CFNetwork?

I have implemented an FTP client on the iPhone, but when the connection is interrupted for a moment while download from the FTP server is in progress, the application informs me there is no connection and stops the client.
Here comes the problem: next time i try to start the download process again, the event stream:handleEvent: is not fired and the streamStatus of the networkStream stays on NSStreamStatusOpening.
If I manually stop the download process (using the same method which I fire when connection is interrupted), I can then re-download again. I have to relaunch the whole application for the downloading to work again.
Here are the key parts of the code:
- (void)downloadFile:(NSDictionary *)file {
NSURL *url;
CFReadStreamRef ftpStream;
url = [NSURL URLWithString:[#"PATH TO FTP FILE" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
[self.fileStream open];
ftpStream = CFReadStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) url);
self.networkStream = (__bridge NSInputStream *) ftpStream;
self.networkStream.delegate = self;
[self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.networkStream open];
CFRelease(ftpStream);
}
and the method that is fired when something happens with the stream
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
switch (eventCode) {
case NSStreamEventOpenCompleted: {
[self updateStatus:#"Opened connection"];
} break;
case NSStreamEventHasBytesAvailable: {
NSInteger bytesRead;
uint8_t buffer[32768];
bytesRead = [self.networkStream read:buffer maxLength:sizeof(buffer)];
if (bytesRead == -1) {
[self stopReceivingWithStatus:#"Network read error"];
} else if (bytesRead == 0) {
[self stopReceivingWithStatus:nil];
} else {
[self processStreamDataWithBuffer:buffer andReadBytes:bytesRead];
}
} break;
case NSStreamEventHasSpaceAvailable: {
assert(NO);
} break;
case NSStreamEventErrorOccurred: {
[self stopReceivingWithStatus:#"Stream open error"];
} break;
case NSStreamEventEndEncountered: {
} break;
default: {
assert(NO);
} break;
}
The problem as I said is that after connection interrupted, the events are not fired anymore.
Note: I am using iOS 5 with ARC.
Perhaps you should set the flag to force the stream to close the underlying native socket which by default is not done;
[self.networkStream setProperty:(id)kCFBooleanTrue forKey:(NSString *)kCFStreamPropertyShouldCloseNativeSocket];

in app purchase non consumable product

I have written the following code.
But when i execute this code, i got log, which shows "no products available".
I am unable to find the reason.
-(void)viewDidLoad {
[super viewDidLoad];
if ([SKPaymentQueue canMakePayments])
{
SKProductsRequest *productsRequest=[[SKProductsRequest alloc]initWithProductIdentifiers:[NSSet setWithObject:#"com.cmp.name.prdt"]];
productsRequest.delegate=self;
[productsRequest start];
}
else {
NSLog(#"Parental Control are enabled");
}
}
-(IBAction)btnpurchase
{
NSString* isPurchased = [[NSUserDefaults standardUserDefaults] stringForKey:#"com.cmp.name.prdt"];
if ([#"purchased" compare:isPurchased]==NSOrderedSame)
{
///do some task
}
else
{
SKPayment * payment=[SKPayment paymentWithProductIdentifier:#"com.cmp.name.prdt"];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
}
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
SKProduct *validProduct=nil;
int count=[response.products count];
if (count>0) {
validProduct=[response.products objectAtIndex:0];
}
else if(!validProduct)
{
NSLog(#"no products available");
}
}
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaaction in transactions)
{
switch (transaaction.transactionState)
{
case SKPaymentTransactionStatePurchasing:
break;
case SKPaymentTransactionStatePurchased:
[[SKPaymentQueue defaultQueue]finishTransaction:transaaction];
[[NSUserDefaults standardUserDefaults] setObject:#"purchased" forKey:#"com.cmp.name.prdt"];
[[NSUserDefaults standardUserDefaults] synchronize];
break;
case SKPaymentTransactionStateRestored:
[[SKPaymentQueue defaultQueue]finishTransaction:transaaction];
break;
case SKPaymentTransactionStateFailed:
if (transaaction.error.code!=SKErrorPaymentCancelled) {
NSLog(#"Error encountered");
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaaction];
break;
default:
break;
}
}
}
Could anyone help me out in this?
You can try out with following piece of code
//PRODUCT REQUEST DELEGATE METHOD
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSLog(#"The product request didReceiveResponse :%#",[response description]);
NSLog(#"The products are :%#",[response.products description]);
NSLog(#"The invalidProductIdentifiers are:%#",[response.invalidProductIdentifiers description]);
NSArray *products=response.products;
for(SKProduct *currentProduct in products){
NSLog(#"THE Product price is :%#",currentProduct.price);
NSLog(#"THE Product description is :%#",currentProduct.localizedDescription);
NSLog(#"THE Product title is :%#",currentProduct.localizedTitle);
NSLog(#"THE Product's product identifier is :%#",currentProduct.productIdentifier);
}
}
THIS WILL LOG THE PRODUCT DETAILS REGISTERED ON iTUNES CONNECT IN CONSOLE WINDOW
Unfortunately, Apple does not respond with any useful information about why your purchases do not show up. I would go through this checklist. In my apps, things didn't work for a few days, then the suddenly started working. Be sure your financial info is correct.

How to get battery status?

How do I get the battery status on an iPhone?
UIDevice *myDevice = [UIDevice currentDevice];
[myDevice setBatteryMonitoringEnabled:YES];
float batLeft = [myDevice batteryLevel];
int i=[myDevice batteryState];
int batinfo=(batLeft*100);
NSLog(#"Battry Level is :%d and Battery Status is :%d",batinfo,i);
switch (i)
{
case UIDeviceBatteryStateUnplugged:
{
[BCStatus setText:NSLocalizedString(#"UnpluggedKey", #"")];
break;
}
case UIDeviceBatteryStateCharging:
{
[BCStatus setText:NSLocalizedString(#"ChargingKey", #"")];
break;
}
case UIDeviceBatteryStateFull:
{
[BCStatus setText:NSLocalizedString(#"FullKey", #"")];
break;
}
default:
{
[BCStatus setText:NSLocalizedString(#"UnknownKey", #"")];
break;
}
}
BCStatus is uilabel.
Iphone SDK 3.0 beta supports this.
The answers above are very good, but they are all in Obj-C, I have used these with other examples to do the same task on MonoTouch, so I am putting my code here in case anybody needs it:
try
{
UIDevice.CurrentDevice.BatteryMonitoringEnabled = true;
_Battery.Level = (int)(UIDevice.CurrentDevice.BatteryLevel * IOSBatteryLevelScalingFactor);
_Battery.State = UIDevice.CurrentDevice.BatteryState;
}
catch (Exception e)
{
ExceptionHandler.HandleException(e, "BatteryState.Update");
throw new BatteryUpdateException();
}
finally
{
UIDevice.CurrentDevice.BatteryMonitoringEnabled = false;
}
I also have a full post on my blog to give all the details in here
Here's what I used for my string as a quick utility method, note that you have to enable battery monitoring to get a value, and then if you don't want to get the notifications (obviously some efficiency to be gained there, since they give you the ability to turn it off) then you should turn it off again after (like I do in this function):
NSString *statusString(void)
{
UIDevice *device = [UIDevice currentDevice];
NSString *batteryStateString = nil;
switch(device.batteryState)
{
case UIDeviceBatteryStateUnplugged: batteryStateString = #"Unplugged"; break;
case UIDeviceBatteryStateCharging: batteryStateString = #"Charging"; break;
case UIDeviceBatteryStateFull: batteryStateString = #"Full"; break;
default: batteryStateString = #"Unknown"; break;
}
[device setBatteryMonitoringEnabled:YES];
NSString *statusString = [NSString stringWithFormat:#"Battery Level - %d%%, Battery State - %#",
(int)round(device.batteryLevel * 100), batteryStateString];
[device setBatteryMonitoringEnabled:NO];
return statusString;
}
Now that the 3.1 SDK is released look for the Getting the Device Battery State section in UIDevice's documentation. It is abunch of battery* properties.