How-to Fix: The application-identifier entitlement is not formatted correctly

A new error has started showing up when submitting iPhone Apps through iTunes Connect:

“The application-identifier entitlement is not formatted correctly; it should contain your 10-character App ID Seed, followed by a dot, followed by your bundle identifier.”

From what I can tell, the way to fix this to create a NEW entitlements file (see my previous post on creating adhoc builds for instructions on how to do this).  Previously we’d only had to create an entitlements file and uncheck “get-task-allow”.

However now it appears you also need to add a new “keychain-access-group” and add an item which includes your App Identifier (get this from the iTunes Provisioning Portal) and your bundle identifier (com.mycompany.bundle_name).

See an example below:

How To: iPhone SDK – Play and Record Audio concurrently

Unfortunately, it’s quite a fiddly process to record audio and play it back at the same time on the iPhone.  By default, the sound output is very quiet from the iPhone’s speaker when you are recording sound.  So how do we fix this?

First, setup your audio session to record audio:

NSURL *url = [NSURL fileURLWithPath:@"/dev/null"];
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
   [NSNumber numberWithFloat: 44100.0],                 AVSampleRateKey,
   [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
   [NSNumber numberWithInt: 1],                         AVNumberOfChannelsKey,
   [NSNumber numberWithInt: AVAudioQualityMax],         AVEncoderAudioQualityKey, nil];

recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
if (recorder) {
   [recorder prepareToRecord]; 
   recorder.meteringEnabled = YES;
   [recorder record]; 
} else {
   NSLog(@"Error: %@", error);
}

Then tell the device you want to record and play audio at the same time:

AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *err = nil;
[audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err];

Then, and this is the key, allow the volume from the speakers to also be loud when recording:

UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
sizeof(audioRouteOverride),&audioRouteOverride);

The end result? You can happily play audio at full volume while recording from the device’s microphone. Happy days.

New iPhone: Torch, Flash and Front/Rear cameras?


After the recent release to developers of iPhone SDK 4.0, the inevitable scramble to review the new APIs has been on in earnest.  One of the first things noticed were the following new AVCaptureDevice class properties:

  • AVCaptureDevice – isFlashMode Supported
  • AVCaptureDevice – isTorchMode Supported
  • AVCaptureDevice – position (Front or Rear)

These new properties relating to the iPhone SDK class AVCaptureDevice, a class used for audio and video capture and management, suggest that the new iPhone (to be announced at WWDC 2010??) may well include a “Flash”, a “Torch” and a front camera.

If this was to turn out to be true, then a front camera for the phone would make video calls possible, the ability to take photos while viewing the camera feed, and the flash would allow you to take photos in the dark!

All very cool new potential features.  Let’s keep our fingers crossed that this turns out to be the case!

How-To: Convert UIImage to Greyscale Equivalent

Here’s a simple code snippet for converting a UIImage to a greyscale equivalent:

-(UIImage *) convertToGreyscale:(UIImage *)i {
	
    int kRed = 1;
    int kGreen = 2;
    int kBlue = 4;
	
    int colors = kGreen;
    int m_width = i.size.width;
    int m_height = i.size.height;
	
    uint32_t *rgbImage = (uint32_t *) malloc(m_width * m_height * sizeof(uint32_t));
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(rgbImage, m_width, m_height, 8, m_width * 4, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGContextSetShouldAntialias(context, NO);
    CGContextDrawImage(context, CGRectMake(0, 0, m_width, m_height), [i CGImage]);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
	
    // now convert to grayscale
    uint8_t *m_imageData = (uint8_t *) malloc(m_width * m_height);
    for(int y = 0; y < m_height; y++) {
        for(int x = 0; x < m_width; x++) {
			uint32_t rgbPixel=rgbImage[y*m_width+x];
			uint32_t sum=0,count=0;
			if (colors & kRed) {sum += (rgbPixel>>24)&255; count++;}
			if (colors & kGreen) {sum += (rgbPixel>>16)&255; count++;}
			if (colors & kBlue) {sum += (rgbPixel>>8)&255; count++;}
			m_imageData[y*m_width+x]=sum/count;
        }
    }
    free(rgbImage);
	
    // convert from a gray scale image back into a UIImage
    uint8_t *result = (uint8_t *) calloc(m_width * m_height *sizeof(uint32_t), 1);
	
    // process the image back to rgb
    for(int i = 0; i < m_height * m_width; i++) {
        result[i*4]=0;
        int val=m_imageData[i];
        result[i*4+1]=val;
        result[i*4+2]=val;
        result[i*4+3]=val;
    }
	
    // create a UIImage
    colorSpace = CGColorSpaceCreateDeviceRGB();
    context = CGBitmapContextCreate(result, m_width, m_height, 8, m_width * sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
    CGImageRef image = CGBitmapContextCreateImage(context);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    UIImage *resultUIImage = [UIImage imageWithCGImage:image];
    CGImageRelease(image);
	
    // make sure the data will be released by giving it to an autoreleased NSData
    [NSData dataWithBytesNoCopy:result length:m_width * m_height];
	
    return resultUIImage;
}

Thanks to the friendly people at StackOverflow.com for this snipet.

How-To: Convert NSData to NSString

How do you convert an NSData object into it’s string representation?  Should be easy, right?  It is, when you know how…

NSString* theString = [[NSString alloc] initWithData:theData encoding:NSASCIIStringEncoding];

iPhone UIScrollView with UIImageView have issues Interface Builder

Ever wanted to have an image view in a scrollview? Sure, you could directly add it using code, but wouldn’t it be nice to do it in Interface Builder?

If you’re like me, you like to leave on the defaults unless absolutely necessary. I had an issue where I added an image view to the scroll view in Interface Builder.
The image view then had an image added to in code. I resized the content view of the scroll view in code to be the same size as the image view (which you have to do
in order to get it to scroll).

Unfortunately, when an image larger than the scrollview was used, it went off the top of the scroll view by about 30px. I thought its origin was using the main view,
instead of the scroll view’s frame, but after modifying various properties I had no luck – and strange results, with the image always returning to about 30px higher than
the scroll view content area.

After trying to resolve things programattically, I resorted to Interface Builder again. I tried any number of properties on the scroll view to get its content
placed at its origin. It turns out that, by default, a UIImageView has a default “Mode” of center. That affects its alignment in its parent view. This ain’t
HTML kids, it is the elements themselves who decide how they are aligned in their parent elements. So, I just change the “Mode” to “Top Left”, and Robert’s your mother’s
brother.

Top Left Screenshot

The code for getting the scroll view to scroll (just FYI) is included below. If thisImage is bigger than the scroll view in any dimension, it will let you scroll
in the corresponding direction – but if it’s the same size or smaller, no scrolling is possible in that direction. Pretty nice. self.scrollView, by the way, has
only the default Interface Builder properties.

CGImageRef imageRef = thisImage.CGImage;
CGFloat width = CGImageGetWidth(imageRef);
CGFloat height = CGImageGetHeight(imageRef);

[self.scrollView setContentSize:CGSizeMake(width, height)];

iPhone: Bugged UINavigationController? View doesn’t Scroll.

Developing a networked iPhone application, I had two views that were very similar – so similar in fact that they were copies of one-another with “Sending” renamed to “Receiving”. The idea was to get them both working with different XIB files, and then modify them.

The code to load the sending view (from the main app delegate) was:

- (IBAction)sendContact:(id)sender
{
	DataController* dc = [DataController sharedInstance];
	dc.contactRecord = (NSMutableDictionary*) [self.userDefaults dictionaryForKey:@"currentUser"];

	SendingViewController *sendingViewController = [[SendingViewController alloc] initWithNibName:@"ReceiverView" bundle:nil];
	[self setBackButtonText:@"Back"];
	[self.navigationController pushViewController:sendingViewController animated:YES];
	[sendingViewController release];
}

The code for the receiving view was:

- (IBAction)receiveContact:(id)sender
{
	ReceivingViewController *receiverViewController = [[ReceivingViewController alloc] initWithNibName:@"ReceivingView" bundle:nil];
	[self setBackButtonText:@"Back"];
	[self.navigationController pushViewController:receiverViewController animated:YES];
	[receiverViewController release];
}

On load, I could _swear_ that nothing happend with the DataController’s contact record. But something screwy was going on. When I hit “send” first (on app launch), hitting “receive” worked fine (you could navigate back with no worries at all). However, when you hit “receive” first, going back only got the navigation bar to change, while the receive view was still visible.

It took ages, but setting contactRecord in the DataController shared instance fixed the problem.

The thing is, the view loaded just fine, no worries at all. No errors or warnings occured… and I wasn’t using contactRecord for anything on the view. So why did it behave like it encountered an error? I searched the code, and I was setting a label (which didn’t even exist on-screen anymore, it was an unused IBOutlet UILabel) to something contained in the DataController. Why it didn’t error properly, and why that stopped the view from unloading properly is completely beyond me… The NavigationBar operates (somewhat) in isolation from the views inside it, so if a view gets stuck (but not the Nav control) you can find yourself in a very weird situation.

So, my advice to you is:

  • It ain’t the same until it’s _exactly_ the same.
  • Just because it doesn’t error, doesn’t mean it hasn’t produced an error.
  • If you can at all avoid it, don’t copy paste entire files. Best to start empty and include the stuff you need instead.

BudTrap: An easy way to solve iPhone/iPod headphone tangles

The guys at BudTrap have a great idea.  Create a device, which clips into your iPhone/iPod, stops your headphone getting tangled, and costs just $5 – with $1 being donated to charity.  On top of which, you get 5 additional “buddy” devices which you can share with your friends.

BudTrap In Use

They are also into working out how much time you save by using their device – which they use as a global tally to show how much time the world is saving by removing the need to untangle headphones.

This is a really novel idea and a cool device.  Head over to BudTrap.com now to start saving your tangle time.