About facebook checkin in facebook graph api in iphone - iphone

Does anyone know about Facebook checkins with the Facebook iOS SDK?
I have made an application using Facebook Graph API and now I want to add the capability to checkin to it. How would I do this?
I have tried the following code but it returns nil.
FbGraphResponse *fb_graph_response = [fbGraph doGraphGet:#"me/checkins" withGetVars:nil];
//my doTheGraph method
- (FbGraphResponse *)doGraphGet:(NSString *)action withGetVars:(NSDictionary *)get_vars {
NSString *url_string = [NSString stringWithFormat:#"https://graph.facebook.com/%#?", action];
//tack on any get vars we have...
if ( (get_vars != nil) && ([get_vars count] > 0) ) {
NSEnumerator *enumerator = [get_vars keyEnumerator];
NSString *key;
NSString *value;
while ((key = (NSString *)[enumerator nextObject])) {
value = (NSString *)[get_vars objectForKey:key];
url_string = [NSString stringWithFormat:#"%#%#=%#&", url_string, key, value];
}//end while
}//end if
if (accessToken != nil) {
//now that any variables have been appended, let's attach the access token....
url_string = [NSString stringWithFormat:#"%#access_token=%#", url_string, self.accessToken];
}
//encode the string
url_string = [url_string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return [self doGraphGetWithUrlString:url_string];
}

This isn't a great answer, but needs to be noticed. The project linked in your comment to mine under your question is no longer supported or maintained:
NOTE!!: this project is no longer maintained. The official Facebook/iOS SDK can be found here: https://github.com/facebook/facebook-iphone-sdk This project is an open source Objective-C (iPhone/iPad) library for communciating with the Facebook Graph API
That is why I didn't recognize your code, it isn't the Official Facebook iOS SDK.
I strongly encourage you to switch to the up-to-date, and more importantly, maintained project as soon as possible.

Related

How to generate unique identifier which should work in all iOS versions?

I want to get the unique identifier which should support all iOS versions..Can any one help me on this issue. As you know that apple is deprecated the UDID method, So there is possibility to generate Unique id using wifi-mac address.But apple is going to remove the wifi mac address in iOS7 version.So my requirement is to generate a new unique code which should work in all iOS versions.Thanks in advance..
Note: Don't change the UDID once user restart the device or reinstall the application.
I was updating my application that was working based only on Unique Identifier which supported iOS 4.3 and above. So,
1) I was unable to use [UIDevice currentDevice].uniqueIdentifier; as it was no longer available
2) I could not use [UIDevice currentDevice].identifierForVendor.UUIDString because it was Available in iOS 6.0 and later only and was unable to use for lower iOS versions.
3) The mac address was not an option as it wasn't allowed in iOS-7
4) OpenUDID was deprecated some time ago and also had issues with iOS-6.
5) Advertisement identifiers were also not available for iOS-5 and below
Finally this was what i did
a) Added SFHFKeychainUtils to the project
b) Generated CFUUID key String
CFUUIDRef cfuuid = CFUUIDCreate(kCFAllocatorDefault);
udidString = (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfuuid));
c) Saved it to Key Chain Utils or else it will generate a new Unique Each Time
Final Code
+ (NSString *)GetDeviceID {
NSString *udidString;
udidString = [self objectForKey:#"deviceID"];
if(!udidString)
{
CFUUIDRef cfuuid = CFUUIDCreate(kCFAllocatorDefault);
udidString = (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfuuid));
CFRelease(cfuuid);
[self setObject:udidString forKey:#"deviceID"];
}
return udidString;
}
+(void) setObject:(NSString*) object forKey:(NSString*) key
{
NSString *objectString = object;
NSError *error = nil;
[SFHFKeychainUtils storeUsername:key
andPassword:objectString
forServiceName:#"LIB"
updateExisting:YES
error:&error];
if(error)
NSLog(#"%#", [error localizedDescription]);
}
+(NSString*) objectForKey:(NSString*) key
{
NSError *error = nil;
NSString *object = [SFHFKeychainUtils getPasswordForUsername:key
andServiceName:#"LIB"
error:&error];
if(error)
NSLog(#"%#", [error localizedDescription]);
return object;
}
For further Details
Now Device Identifier change to UUID.You can get UUID With the help of following code:
- (NSString *)getUUID
{
NSString *UUID = [[NSUserDefaults standardUserDefaults] objectForKey:#"uniqueID"];
if (!UUID) {
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
UUID = [(__bridge NSString*)string stringByReplacingOccurrencesOfString:#"-"withString:#""];
[[NSUserDefaults standardUserDefaults] setValue:UUID forKey:#"uniqueID"];
}
return UUID;
}
It's Work in all iOS version.
I don't have access to the code right now (can post in a few hours if you still need it) but what I've done is create a static method 'deviceIdentifier' in a helper class.
the method does a basic check for the current iOS version, returns UDID if below 6.0 and uniqueIdentifier otherwise
Let me know if you'd like the code for that and I'll post it when I can..it's only 10-15 lines or so if I remember right but makes a big difference as then you can just call '[myHelper deviceIdentifier]' wherever you need a device ID and not have to worry about which iOS version they are using

Google+ check-in location in ios

I want to implement location check-in feature in ios. My application is using google+ ios sdk. The problem which I am facing is that after I have implemented google+ check-in feature then that post is not being displayed on my google+ account.
The technique which I have tried and implemented is written below.
-(IBAction)checkIn
{
GTMOAuth2Authentication *auth = [GPPSignIn sharedInstance].authentication;
GTLServicePlus* plusService = [[GTLServicePlus alloc] init] ;
plusService.retryEnabled = YES;
[plusService setAuthorizer:auth];
GTLPlusMoment *moment = [[GTLPlusMoment alloc] init];
moment.type = #"http://schemas.google.com/CheckInActivity";
GTLPlusItemScope *target = [[GTLPlusItemScope alloc] init] ;
target.url =#"https://developers.google.com/+/plugins/snippet/examples/place";
moment.target = target;
GTLQueryPlus *query =
[GTLQueryPlus queryForMomentsInsertWithObject:moment
userId:#"me"
collection:kGTLPlusCollectionVault];
[plusService executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
id object,
NSError *error) {
if (error) {
GTMLoggerError(#"Error: %#", error);
NSString *failure =
[NSString stringWithFormat:#"Status: Error: %#", error];
NSLog(#"%#",failure);
} else {
NSString *result = #"CheckedIn Saved in Google+";
NSLog(#"%#",result);
}
}];
}
Can any one please help me out. Is this the right way of implementing location check-in feature of google+ or is there any other method for it?
The method you're using is writing an "app activity" to Google+, which stores a "moment" in the user's app activity vault. As noted on https://developers.google.com/+/mobile/ios/app-activities these moments are not directly visible on the user's stream, although users may choose to share them to the stream if they wish.
To see the moments that have been shared, you will need to use the desktop app. Your profile has a list of apps that are using the Google+ Sign-In and you can view, share, and delete the activities for each of these apps. The mobile Google+ clients don't let you view the activities yet.

Opening iTunes Store to specific song

Ok, I have seen similar questions here but none are actually answering the problem for me.
I have a streaming audio app and the stream source returns to me the song title and artist name. I have an iTunes button in the app, and want to open the iTunes STORE (search) to that exact song, or at least close. I have tried the following:
NSString *baseString = #"itms://phobos.apple.com/WebObjects/MZSearch.woa/wa/advancedSearchResults?songTerm=";
NSString *str1 = [self.songTitle2 stringByReplacingOccurrencesOfString:#" " withString:#"+"];
NSString *str2 = [self.artist2 stringByReplacingOccurrencesOfString:#" " withString:#"+"];
NSString *str = [NSString stringWithFormat:#"%#%#&artistTerm=%#", baseString, str1, str2];
[[UIApplication sharedApplication] openURL: [NSURL URLWithString:str]];
This call does indeed switch me to the iTunes STORE as expected, but then it pops up an error "Cannot connect to iTunes Store". I am obviously on-line as the song is actively streaming, and I am in the store. The search box in iTunes app only shows the song name and nothing else.
Here is an example of a generated string:
itms://phobos.apple.com/WebObjects/MZSearch.woa/wa/advancedSearchResults?artistTerm=Veruca+Salt&artistTerm=Volcano+Girls
I have tired taking the string it generates and pasting it into Safari, and it works OK on my Mac, opening to albums from the artist in the store. Why not on the phone?
Also, it seems to ignore both items, as it does not take me to the song by that artist. Does this require also knowing the album name (which I do not have at this time.)
Help would be appreciated. Thanks.
Yes, I am answering my own question.
After much digging and a talk with one of the best programmers I know, we have a solution, so I thought I would share it here. This solution takes the song name and artist, actually does make a call to the Link Maker API, gets back an XML document, and extracts the necessary info to create a link to the iTunes Store, opening the store to the song in an album by that artist that contains the song.
In the interface of the view controller, add:
#property (strong, readonly, nonatomic) NSOperationQueue* operationQueue;
#property (nonatomic) BOOL searching;
In the implementation:
#synthesize operationQueue = _operationQueue;
#synthesize searching = _searching;
Here are the methods and code that will do this for you:
// start an operation Queue if not started
-(NSOperationQueue*)operationQueue
{
if(_operationQueue == nil) {
_operationQueue = [NSOperationQueue new];
}
return _operationQueue;
}
// change searching state, and modify button and wait indicator (if you wish)
- (void)setSearching:(BOOL)searching
{
// this changes the view of the search button to a wait indicator while the search is perfomed
// In this case
_searching = searching;
dispatch_async(dispatch_get_main_queue(), ^{
if(searching) {
self.searchButton.enabled = NO;
[self.searchButton setTitle:#"" forState:UIControlStateNormal];
[self.activityIndicator startAnimating];
} else {
self.searchButton.enabled = YES;
[self.searchButton setTitle:#"Search" forState:UIControlStateNormal];
[self.activityIndicator stopAnimating];
}
});
}
// based on info from the iTunes affiliates docs
// http://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html
// this assume a search button to start the search.
- (IBAction)searchButtonTapped:(id)sender {
NSString* artistTerm = self.artistField.text; //the artist text.
NSString* songTerm = self.songField.text; //the song text
// they both need to be non-zero for this to work right.
if(artistTerm.length > 0 && songTerm.length > 0) {
// this creates the base of the Link Maker url call.
NSString* baseURLString = #"https://itunes.apple.com/search";
NSString* searchTerm = [NSString stringWithFormat:#"%# %#", artistTerm, songTerm];
NSString* searchUrlString = [NSString stringWithFormat:#"%#?media=music&entity=song&term=%#&artistTerm=%#&songTerm=%#", baseURLString, searchTerm, artistTerm, songTerm];
// must change spaces to +
searchUrlString = [searchUrlString stringByReplacingOccurrencesOfString:#" " withString:#"+"];
//make it a URL
searchUrlString = [searchUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL* searchUrl = [NSURL URLWithString:searchUrlString];
NSLog(#"searchUrl: %#", searchUrl);
// start the Link Maker search
NSURLRequest* request = [NSURLRequest requestWithURL:searchUrl];
self.searching = YES;
[NSURLConnection sendAsynchronousRequest:request queue:self.operationQueue completionHandler:^(NSURLResponse* response, NSData* data, NSError* error) {
// we got an answer, now find the data.
self.searching = NO;
if(error != nil) {
NSLog(#"Error: %#", error);
} else {
NSError* jsonError = nil;
NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if(jsonError != nil) {
// do something with the error here
NSLog(#"JSON Error: %#", jsonError);
} else {
NSArray* resultsArray = dict[#"results"];
// it is possible to get no results. Handle that here
if(resultsArray.count == 0) {
NSLog(#"No results returned.");
} else {
// extract the needed info to pass to the iTunes store search
NSDictionary* trackDict = resultsArray[0];
NSString* trackViewUrlString = trackDict[#"trackViewUrl"];
if(trackViewUrlString.length == 0) {
NSLog(#"No trackViewUrl");
} else {
NSURL* trackViewUrl = [NSURL URLWithString:trackViewUrlString];
NSLog(#"trackViewURL:%#", trackViewUrl);
// dispatch the call to switch to the iTunes store with the proper search url
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] openURL:trackViewUrl];
});
}
}
}
}
}];
}
}
The XML file that comes back has a LOT of other good info you could extract here as well, including three sizes of album art, album name, cost, etc, etc.
I hope this helps someone else out. This stumped me for quite some time, and I thank a good friend of mine for making this work.
You are in fact using a URL for the search. That's why iTunes opens on search. My iTunes in Mac OS X also opens in search.
Use the Search API for iTunes to search for the content you want and get the artist, album or song ids so you can generate a direct URL for that content.
Look in the iTunes Link Maker how to create a URL for an artist or for a specific album and compose that URL on your app.
It appears that now iOS already opens the iTunes app directly when you try to open a itunes html url.
Example, trying to do a openURL on https://itunes.apple.com/br/album/falando-de-amor/id985523754 already opens the iTunes app instead of the website.

Get current iTunesStore country

I need to get currently activated iTunes store country code. I have read about getting current locale, but this is not very smart solution, since user can have one locale but totally different iTunes account. The solution does not need to be legal, apple rejection is not a problem here. Does anybody have found solution for this scenario using private frameworks?
You can do this after you've requested the store's products by checking the NSLocale on one of the product's priceLocale. Try this code:
- (NSString*) storeCountryCode:(NSArray*) products
{
NSString* countryCode = nil;
SKProduct* product = [products objectAtIndex:0];
if(product != nil)
{
NSLocale* storeLocale = product.priceLocale;
countryCode = (__bridge NSString*)CFLocaleGetValue((__bridge CFLocaleRef)storeLocale, kCFLocaleCountryCode);
}
return countryCode;
}
You could call this from your SKProductsRequestDelegate method:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSString* storeCountryCode = [self storeCountryCode:response.products];
//other product handling
}
you can "CFLocaleGetValue" call this use
NSString *aCountry=[getCurrentItunesStoreCountryFromProudct:myProudct];
-(NSString *)getCurrentItunesStoreCountryFromProudct:(SKProduct *)aProudct
{
NSLocale* storeLocale = aProudct.priceLocale;
NSString *storeCountry = (NSString*)CFLocaleGetValue((CFLocaleRef)storeLocale, kCFLocaleCountryCode);
return storeCountry;
}
You can obtain the Storefront ID with this code. As it relies on private APIs, do not use in production code.
NSError *error = nil;
BOOL loaded = [[NSBundle bundleWithPath:#"/System/Library/PrivateFrameworks/iTunesStore.framework"] loadAndReturnError:&error];
if (loaded) {
NSString *localStoreFrontID = nil;
#try {
localStoreFrontID = [NSClassFromString(#"ISClient") valueForKeyPath:#"currentClient.localStoreFrontID"];
}
#catch (NSException *exception) {
NSLog(#"%#", exception);
}
NSLog(#"localStoreFrontID: %#", localStoreFrontID);
}
else {
NSLog(#"Error: %#", error);
}
On iOS 5.1.1, this printed localStoreFrontID: 143459-2,2 for me, i.e. the Swiss store. I’m not sure what the -2,2 suffix mean, maybe it is about the language. I have not tested this on iOS 6.
Note that it even works after you sign out of your account in Settings → Store.

Is it possible to get information about all apps installed on iPhone?

Is it possible to get the information (app icon, app name, app location) about all apps that have been installed on iPhone/iPod?
there is a way to check if an application is installed or not, however, it does violate the Sandbox rules and Apple *may reject your app for using this. But it has been done before by other Apps that are available in the App Store, so feel free to try it
Sometimes you may want to check if a specific app is installed on the device, in case you use custom URL schemes that require some other app to be installed (you could just gray out/disable some buttons then). Unfortunately, Apple apparently does not have any function that checks this for you, so I whipped one up. It does not enumerate every single app, instead it uses the MobileInstallation cache which is always up-to-date with SpringBoard and holds the Info dictionaries of all apps installed. Although you're not "supposed" to access the cache, it's readable by App Store apps. Here is my code which at least works perfectly fine with the Simulator 2.2.1:
Code:
// Declaration
BOOL APCheckIfAppInstalled(NSString *bundleIdentifier); // Bundle identifier (eg. com.apple.mobilesafari) used to track apps
// Implementation
BOOL APCheckIfAppInstalled(NSString *bundleIdentifier)
{
static NSString *const cacheFileName = #"com.apple.mobile.installation.plist";
NSString *relativeCachePath = [[#"Library" stringByAppendingPathComponent: #"Caches"] stringByAppendingPathComponent: cacheFileName];
NSDictionary *cacheDict = nil;
NSString *path = nil;
// Loop through all possible paths the cache could be in
for (short i = 0; 1; i++)
{
switch (i) {
case 0: // Jailbroken apps will find the cache here; their home directory is /var/mobile
path = [NSHomeDirectory() stringByAppendingPathComponent: relativeCachePath];
break;
case 1: // App Store apps and Simulator will find the cache here; home (/var/mobile/) is 2 directories above sandbox folder
path = [[NSHomeDirectory() stringByAppendingPathComponent: #"../.."] stringByAppendingPathComponent: relativeCachePath];
break;
case 2: // If the app is anywhere else, default to hardcoded /var/mobile/
path = [#"/var/mobile" stringByAppendingPathComponent: relativeCachePath];
break;
default: // Cache not found (loop not broken)
return NO;
break; }
BOOL isDir = NO;
if ([[NSFileManager defaultManager] fileExistsAtPath: path isDirectory: &isDir] && !isDir) // Ensure that file exists
cacheDict = [NSDictionary dictionaryWithContentsOfFile: path];
if (cacheDict) // If cache is loaded, then break the loop. If the loop is not "broken," it will return NO later (default: case)
break;
}
NSDictionary *system = [cacheDict objectForKey: #"System"]; // First check all system (jailbroken) apps
if ([system objectForKey: bundleIdentifier]) return YES;
NSDictionary *user = [cacheDict objectForKey: #"User"]; // Then all the user (App Store /var/mobile/Applications) apps
if ([user objectForKey: bundleIdentifier]) return YES;
// If nothing returned YES already, we'll return NO now
return NO;
}
Here is an example of this, assuming that your app is named "yourselfmadeapp" and is an app in the app store.
Code:
NSArray *bundles2Check = [NSArray arrayWithObjects: #"com.apple.mobilesafari", #"com.yourcompany.yourselfmadeapp", #"com.blahblah.nonexistent", nil];
for (NSString *identifier in bundles2Check)
if (APCheckIfAppInstalled(identifier))
NSLog(#"App installed: %#", identifier);
else
NSLog(#"App not installed: %#", identifier);
Log Output:
Code:
2009-01-30 12:19:20.250
SomeApp[266:20b] App installed:
com.apple.mobilesafari 2009-01-30
12:19:20.254 SomeApp[266:20b] App
installed:
com.yourcompany.yourselfmadeapp
2009-01-30 12:19:20.260
SomeApp[266:20b] App not installed:
com.blahblah.nonexistent
Try this out before using it, I think Apple changed where the MobileInstallation.plist is located and if you do change it, try it out on an actual device not the simulator. Good Luck!
http://www.iphonedevsdk.com/forum/iphone-sdk-development/37103-finding-out-what-apps-installed.html
PK
Sure you can do this when the device is Jailbroken, so that you can reach out of the sandBox.
You can get the information you want by analyzing Info.plist in every .app which is located at every path "/var/mobile/Applications/", such as "/var/mobile/Applications//*.app/Info.plist"
Here is my code.
- (void)scan
{
NSString *pathOfApplications = #"/var/mobile/Applications";
NSLog(#"scan begin");
// all applications
NSArray *arrayOfApplications = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:pathOfApplications error:nil];
for (NSString *applicationDir in arrayOfApplications) {
// path of an application
NSString *pathOfApplication = [pathOfApplications stringByAppendingPathComponent:applicationDir];
NSArray *arrayOfSubApplication = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:pathOfApplication error:nil];
// seek for *.app
for (NSString *applicationSubDir in arrayOfSubApplication) {
if ([applicationSubDir hasSuffix:#".app"]) {// *.app
NSString *path = [pathOfApplication stringByAppendingPathComponent:applicationSubDir];
path = [path stringByAppendingPathComponent:#"Info.plist"];
// so you get the Info.plist in the dict
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
// code to analyzing the dict.
}
}
}
NSLog(#"scan end");
}
Here is sample content of an Info.plist. So, get values for any key you care about.
{
BuildMachineOSBuild = 11G63;
CFBundleDevelopmentRegion = "zh_CN";
CFBundleDisplayName = "\U4e50\U89c6\U5f71\U89c6HD";
CFBundleExecutable = LetvIpadClient;
CFBundleIconFile = "icon.png";
CFBundleIconFiles = (
"icon.png",
"icon#2x.png"
);
CFBundleIdentifier = "com.letv.ipad.hdclient";
CFBundleInfoDictionaryVersion = "6.0";
CFBundleName = LetvIpadClient;
CFBundlePackageType = APPL;
CFBundleResourceSpecification = "ResourceRules.plist";
CFBundleShortVersionString = "3.1";
CFBundleSignature = "????";
CFBundleSupportedPlatforms = (
iPhoneOS
);
CFBundleURLTypes = (
{
CFBundleURLName = "m.letv.com";
CFBundleURLSchemes = (
letvIPad
);
}
);
CFBundleVersion = "3.1";
DTCompiler = "com.apple.compilers.llvmgcc42";
DTPlatformBuild = 10A403;
DTPlatformName = iphoneos;
DTPlatformVersion = "6.0";
DTSDKBuild = 10A403;
DTSDKName = "iphoneos6.0";
DTXcode = 0450;
DTXcodeBuild = 4G182;
LSRequiresIPhoneOS = 0;
MinimumOSVersion = "4.3";
UIDeviceFamily = (
2
);
"UILaunchImageFile~ipad" = (
"Default.png",
"Default#2x.png"
);
UIPrerenderedIcon = 1;
UIStatusBarHidden = 1;
UISupportedInterfaceOrientations = (
UIInterfaceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft,
UIInterfaceOrientationLandscapeRight
);
"UISupportedInterfaceOrientations~ipad" = (
UIInterfaceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeLeft
);
}
Another way to get installed applications in iPhone is just call:
NSString *rootAppPath = #"/Applications";
NSArray *listApp = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:rootAppPath error:nil];
You can access then in each application to read their dictionary Info.plist to know more about these applications.
UPDATE: Obviously, this method does not work anymore (for iOS8) cause our application does not have permission to view the content of /Applications
try this, it will work even with non-jailbroken devices
#include <objc/runtime.h>
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
SEL selector=NSSelectorFromString(#"defaultWorkspace");
NSObject* workspace = [LSApplicationWorkspace_class performSelector:selector];
SEL selectorALL = NSSelectorFromString(#"allApplications");
NSLog(#"apps: %#", [workspace performSelector:selectorALL]);