If i use accelerometer in my app should i add Required device capabilitiesi in info.plist and enter accelerometer ?if yes what should i add exactly?
You should write code defensively and always "degrade" the app nicely.
For example, you should think of how you app will run if accelerometer is not present.
Have a look at the CMMotionManager class - in particular at its accelerometerActive property which returns a BOOL. Here is an example:
CMMotionManager *manager = [[CMMotionManager alloc] init];
if(!manager.accelerometerAvailable) {
NSLog(#"Accelerometer not available");
} else {
manager.accelerometerUpdateInterval = 1.0;
NSOperationQueue *motionQueue = [[NSOperationQueue alloc] init];
[manager startAccelerometerUpdatesToQueue: motionQueue withHandler:
^(CMAccelerometerData *data, NSError *error) {
NSLog(#"Accelerometer data: %#", [data description]);
}
];
}
You need to use
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>accelerometer</string>
</array>
Further details in the iOS Application Programming Guide (page 89, table 5-1).
You do not need to include this key if your app detects only device orientation changes.
no you don't need to add anything to your info.plist.
Just make sure that your appDelegate implements protocol UIAccelerometerDelegate and then in your .m file just do:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
....
}
- (void) accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
{
//your accelerometer code
}
Related
I want to open url from the AppleWatch app button tap to the mobile application.
Please any one have any idea regarding to these?
Added this in your AppDelegate.m
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://www.google.com"]];
}
This is what you have to apply on button tap in Watch App
NSURL *url = // your URL
NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:url, #"URLKey", nil];
[WKInterfaceController openParentApplication:dic reply:^(NSDictionary *replyInfo, NSError *error)
{
NSLog(#"%# %#",replyInfo, error);
}];
And you can receive this request in iPhone in AppDelegate.m
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply
{
//receive userinfo dictionary here to perform specific request from watch
NSString *url = [userInfo objectForKey:#"URLKey"];
// perform operation on url
reply(#{#"Notification Alert":[NSString stringWithFormat:#"%f",dist]});
}
I have a cartArray(in AppDelegate.h #interface above) that need to be saved when the app in background mode or the app closed. The app worked fine when the cartArray has nothing but crashed when I added an item (Cart) in it and entered the background or closed the application by pressing the minus sign. My cartArray contains cart class in it.
May I know what is happening? The tutorial online is so complicated and I always find myself lost in the middle of explanation.
[AppDelegate.m]
- (void)applicationDidEnterBackground:(UIApplication *)application {
[AppDelegate saveData];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[AppDelegate getData];
}
+(NSString *) getPathToAchieve{ NSLog(#"+++++getPathToAchieve");
static NSString* docsDir = nil;
if (docsDir == nil) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [paths objectAtIndex:0];
}
NSString *fullFileName = [NSString stringWithFormat:#"%#.plist", docsDir];
return fullFileName;
}
- (void)applicationWillTerminate:(NSNotification *)notification{
[cartArray writeToFile:[AppDelegate getPathToAchieve] atomically:YES];
}
-(id)initWithCoder:(NSCoder *)aDecoder
{ self = [super init];
if (self != nil)
{
cartArray = [aDecoder decodeObjectForKey:#"cartArrayKeys"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)anEncoder
{
[anEncoder encodeObject:cartArray forKey:#"cartArrayKeys"];
}
+(void)saveData{
[NSKeyedArchiver archiveRootObject:cartArray toFile:[self getPathToAchieve] ];
}
+(id)getData{
return [NSKeyedUnarchiver unarchiveObjectWithFile:[self getPathToAchieve]];
}
Your code is pretty messy. First, implement -(id)initWithCoder: and -(void)encodeWithCoder: in your Cart class, not AppDelegate class (and make sure Cart conforms to NSCoding protocol):
- (void) encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.title forKey:#"title"];
[encoder encodeObject:self.description forKey:#"description"];
.....
}
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super init]) {
self.title = [decoder decodeObjectForKey:#"title"] ;
self.description = [decoder decodeObjectForKey:#"description"] ;
....
}
return self;
}
Second, implement -(void)saveData and -(void)getData:
-(void)saveData{
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:cartArray] forKey:#"cartArray"];
}
-(void)getData{
NSData *savedArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"cartArray"];
if (savedArray != nil)
{
NSArray *oldArray = [NSKeyedUnarchiver unarchiveObjectWithData:savedArray];
if (oldArray != nil) {
cartArray = [[NSMutableArray alloc] initWithArray:oldArray];
} else {
cartArray = [[NSMutableArray alloc] init];
}
}
}
Call saveData when application is going to be terminated / entered background.
Call getData when application has loaded.
do all your saving in
- (void)applicationWillResignActive:(UIApplication *)application
from the documentation:
Tells the delegate that the application is about to become inactive.
This method is called to let your application know that it is about to
move from the active to inactive state. This can occur for certain
types of temporary interruptions (such as an incoming phone call or
SMS message) or when the user quits the application and it begins the
transition to the background state. An application in the inactive
state continues to run but does not dispatch incoming events to
responders. You should use this method to pause ongoing tasks, disable
timers, and throttle down OpenGL ES frame rates. Games should use this
method to pause the game. An application in the inactive state should
do minimal work while it waits to transition to either the active or
background state.
Array is a temporary storage if you want to save some data in permanent then try to use NSUSerDefult. After closing app array may vanish. NSUSerDefult data not vanish. NSUserDefault vanish only when app delete or Remove app from simulator.
Help!
I cant find whats wrong. My code is up and mostly running and i needed to incorporate Urban Air push notification and there is something wrong with my code. If there is a better or different way to incorporate this that works without my errors I would appreciate that.
I took this code from a tut of Urban Airmail. I wasnt sure what to inlude and what not to from the sample app.
Now for my code. Ill notate where I get errors They are stray / errors and expected ; b4 :
errors
If you could fix the code that would be awesome!
//
// SuperSlickAppDelegate.m
// SuperSlick
//
// Created by on 8/2/10.
// Copyright __MyCompanyName__ 2010. All rights reserved.
//
#import <SystemConfiguration/SCNetworkReachability.h>
#include <netinet/in.h>
#import "SuperSlickAppDelegate.h"
#import "SuperSlickViewController.h"
#import "Reachability.h"
#implementation SuperSlickAppDelegate
#synthesize window;
#synthesize viewController;
#pragma mark -
#pragma mark Application lifecycle
#define kApplicationKey #"rnftzaemRp2HJMsNjwZvGQ"
#define kApplicationSecret #"X1XdTjdWQIaL72e-gXew5A"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
Reachability *r = [Reachability reachabilityWithHostName:#"google.com"];
NetworkStatus internetStatus = [r currentReachabilityStatus];
if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN))
{
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:#"No Internet Connection" message:#"You require an internet connection via WiFi or cellular network to use this! Try the settings app for WiFi Connectivity." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[myAlert show];
[myAlert release];
}
//Register for notifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert)];
//ERROR HERE in line above Stray 357
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)_deviceToken {
//ERROR HERE Wrong type argument to unary minus + stray
// Get a hex string from the device token with no spaces or < >
self.deviceToken = [[[[_deviceToken description] stringByReplacingOccurrencesOfString:#"<"withString:#""]
stringByReplacingOccurrencesOfString:#">" withString:#""]
stringByReplacingOccurrencesOfString: #" " withString: #""];
NSLog(#"Device Token: %#", self.deviceToken);
if ([application enabledRemoteNotificationTypes] == 0) {
NSLog(#"Notifications are disabled for this application. Not registering with Urban Airship");
return;
}
// this is straight out of the UA sample code
NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
NSString *UAServer = #"https://go.urbanairship.com";
NSString *urlString = [NSString stringWithFormat:#"%#%#%#/", UAServer, #"/api/device_tokens/", self.deviceToken];
NSURL *url = [NSURL URLWithString: urlString];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
request.requestMethod = #"PUT";
// Authenticate to the server
request.username = kApplicationKey;
request.password = kApplicationSecret;
[request setDelegate:self];
[request setDidFinishSelector: #selector(registrationSuccessMethod:)]; // if you want to do something with the token
[request setDidFailSelector: #selector(requestWentWrong:)];
[queue addOperation:request];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *) error {
NSLog(#"Failed to register with error: %#", error);
}
- (void)requestWentWrong: (ASIHTTPRequest *)request {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSError *_error = [request error];
NSLog(#"ERROR: NSError query result: %#", _error);
UIAlertView *someError = [[UIAlertView alloc] initWithTitle:
#"Network error" message: NSLocalizedString( #"Error registering with notifiction server",
#"Error registering with notifiction server")
delegate: self
cancelButtonTitle: #"OK"
otherButtonTitles: nil];
[someError show];
[someError release];
}
// Add the view controller's view to the window and display.
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
}
- (void)applicationWillResignActive:(UIApplication *)application {
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
/*
Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application {
/*
Called when the application is about to terminate.
See also applicationDidEnterBackground:.
*/
}
#pragma mark -
#pragma mark Memory management
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
/*
Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later.
*/
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
New Code that has troubles:
//Register for notifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert)];
;}}
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)_deviceToken {
//ERROR HERE Wrong type argument to unary minus and semi colon b4
Doesn't look like you ever ended your application:didFinishLaunchingWithOptions: method - you should have an end brace after this line:
[[UIApplication sharedApplication] registerForRemoteNotificationTypes...
So it should look like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert)];
//ERROR HERE in line above Stray 357
}
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)_deviceToken {
...
}
That should do it.
For your second code block - without seeing the surrounding code it's difficult to see what you're trying to do...you likely shouldn't have:
;}}
It should probably just be:
}
If you are looking for unbalanced parentheses, then this is probably the part that is giving you troubles:
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
}
I am trying to simply NSLog the output of the new iPhone 4 Gyroscope. But after reading the documentation and following their sample code I am getting this error.
ERROR,Time,300635803.946,Function,"CLLoggingSetFile",could not open locations log /var/mobile/Library/Caches/CoreMotion/CoreMotion.log
Even if I just setup my motionManager object with [[CMMotionManager alloc] init]; on its own and no other code, I still get the error.
Here is my .h file.
#import <UIKit/UIKit.h>
#import <CoreMotion/CoreMotion.h>
#interface GyroTest0ViewController : UIViewController {
CMMotionManager *motionManager;
NSOperationQueue *opQ;
}
#end
And here my .m file.
- (void)viewDidLoad {
[super viewDidLoad];
// the error occurs even just with this line on its own
motionManager = [[CMMotionManager alloc] init];
if (motionManager.gyroAvailable) {
motionManager.gyroUpdateInterval = 1.0/60.0;
[motionManager startGyroUpdates];
opQ = [[NSOperationQueue currentQueue] retain];
CMGyroHandler gyroHandler = ^ (CMGyroData *gyroData, NSError *error) {
CMRotationRate rotate = gyroData.rotationRate;
NSLog(#"rotation rate = [%f, %f, %f]", rotate.x, rotate.y, rotate.z);
};
} else {
NSLog(#"No gyroscope on device.");
[motionManager release];
}
}
Any help and/or source code to simply log the iPhone 4 gyroscope data would be much appreciated. Many thanks!
Try this,
motionManager.gyroUpdateInterval = 1.0/60.0;
[motionManager startGyroUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler: ^(CMGyroData *gyroData, NSError *error)
{
CMRotationRate rotate = gyroData.rotationRate;
NSLog(#"rotation rate = [%f, %f, %f]", rotate.x, rotate.y, rotate.z);
}];
For the WWDC sample code:
Log in to ADC
Click on WWDC 2010 session videos
View in iTunes
There you find the link to sample code (230 MB)
Any results regarding this issue? I get the same error even when I use WWDC teapot demo code.
I filed a bug report (8382659).
By the way I get the same error when I use the push method described by Joshua Weinberg.
Update: Apple confirmed the bug but referred to a duplicate issue 8173937 that I can't find. Well let's hope that it will be fixed in the next release.
How can I play a background audio while my application is running?
Thanks.
Okay. This is a solution for background sound on iOS4 & iOS5 (definitely works up to iOS 5.0.1), and I have tested it only with AVPlayer. It should probably work for MPMusicPlayerController too.
Required frameworks:
AVFoundation.framework
AudioToolbox.framework
In your Info.plist, for the key UIBackgroundModes, add audio.
In MyAppDelegate.h:
reference <AVFoundation/AVFoundation.h> & <AudioToolbox/AudioToolbox.h>
implement the protocol AVAudioSessionDelegate:
#interface MyAppDelegate : NSObject <UIApplicationDelegate, AVAudioSessionDelegate>
define a method ensureAudio:
// Ensures the audio routes are setup correctly
- (BOOL) ensureAudio;
In MyAppDelegate.m:
implement the ensureAudio method:
- (BOOL) ensureAudio
{
// Registers this class as the delegate of the audio session (to get background sound)
[[AVAudioSession sharedInstance] setDelegate: self];
// Set category
NSError *categoryError = nil;
if (![[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&categoryError]) {
NSLog(#"Audio session category could not be set");
return NO;
}
// Activate session
NSError *activationError = nil;
if (![[AVAudioSession sharedInstance] setActive: YES error: &activationError]) {
NSLog(#"Audio session could not be activated");
return NO;
}
// Allow the audio to mix with other apps (necessary for background sound)
UInt32 doChangeDefaultRoute = 1;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(doChangeDefaultRoute), &doChangeDefaultRoute);
return YES;
}
in the application:didFinishLaunchingWithOptions: method, before you assign the root view controller, run [self ensureAudio]:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Configure audio session
[self ensureAudio];
// Add the navigation controller's view to the window and display.
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
implement the AVAudioSessionDelegate methods like this:
#pragma mark - AVAudioSessionDelegate
- (void) beginInterruption
{
}
- (void) endInterruption
{
// Sometimes the audio session will be reset/stopped by an interruption
[self ensureAudio];
}
- (void) inputIsAvailableChanged:(BOOL)isInputAvailable
{
}
ensure that your app continues to run in the background. You can use the ol' [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler] if you want, but I think there are better ways.
play the actual audio (note I'm using ARC, that's why there are no release calls):
NSURL * file = [[NSBundle mainBundle] URLForResource:#"beep" withExtension:#"aif"];
AVURLAsset * asset = [[AVURLAsset alloc] initWithURL:file options:nil];
AVPlayerItem * item = [[AVPlayerItem alloc] initWithAsset:asset];
__block AVPlayer * player = [[AVPlayer alloc]initWithPlayerItem:item];
__block id finishObserver = [[NSNotificationCenter defaultCenter] addObserverForName:AVPlayerItemDidPlayToEndTimeNotification
object:player.currentItem
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
[[NSNotificationCenter defaultCenter] removeObserver:finishObserver];
// Reference the 'player' variable so ARC doesn't release it until it's
// finished playing.
player = nil;
}];
// Trigger asynchronous load
[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:#"tracks"] completionHandler:^{
// Start playing the beep (watch out - we're not on the main thread here)!
[player play];
}];
And it shooooooooooooould work!
If you are using your app also for recording - then don't forget to change setCategory to AVAudioSessionCategoryPlayAndRecord. In other case you won't be able to record
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayAndRecord error:&setCategoryErr];