calling an application from other application - objective-c

I am writing an application in Objective-C whose functionality is to call and execute another application.Pls can i know the procedure???Let me also know where i need to keep the calling application which has to load and execute???

The only way to "launch" another application is if the other application "cooperates" with yours, if you will.
The cooperation comes in the form of a URL protocol scheme that an application exposes. Examples are mailto: (exposed by the system mail application) and sms: (exposed by the Messages app).
http://wiki.akosma.com/IPhone_URL_Schemes seems to have a comprehensive list of third party apps exposing a custom protocol scheme that you can make use of.
Launching another app is a matter of calling [[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"twitterrific://..."]; (for example).
As of OS 3.0 you can also check if a given URL protocol scheme is available via UIApplication's -canOpenURL: — checking if some app has registered the protocol scheme, or in other words checking if an application is installed.
If you are writing both apps yourself then launching a custom protocol scheme is pretty simple, however you can't launch an arbitrary iPhone app, and you wouldn't be able to enumerate available apps anyway because of the sandbox.

I'm not sure I fully understand your question, but if all you're trying to do is launch another app, there are a number of ways to do this. The most straightforward is probably by using the NSTask class. Here is a simple example of launching iCal from within an Objective-C application using an NSTask.
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:#"/Applications/iCal.app/Contents/MacOS/iCal"];
[task launch];
[task release];

See the -launchApplication: method of the NSWorkspace class.

1 Register a custom URL Scheme - In your applications Info.plist specify the subproperties of the CFBundleURLTypes
CFBundleURLName
A string that is the abstract name for the URL type. To ensure
uniqueness, it is recommended that
you specify a reverse-DNS style of
identifier, for example,
com.acme.myscheme. The URL-type name
provided here is used as a key to a
localized string in the
InfoPlist.strings file in a
language-localized bundle
subdirectory. The localized string is
the human-readable name of the URL
type in a given language.
CFBundleURLSchemes
An array of URL schemes for URLs belonging to this URL type. Each
scheme is a string. URLs belonging to
a given URL type are characterized by
their scheme components.
2 implement the handleOpenURL method to receive the notifications
(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[url scheme] isEqualToString:#"myscheme"]) {
...
3 in the calling application construct a URL to the custom scheme you have defined and open it. The iPhone OS uses this for http, mailto, tel, and sms URL schemes
NSURL *myURL = [NSURL URLWithString:#"myscheme://?params..."];
[[UIApplication sharedApplication] openURL:myURL];

Related

Objective-C - Loop through all installed applications

I've been trying to use NSWorkspace and fullPathForApplication but this isn't meeting my needs as it doesn't return the correct application.
I could do:
[NSBundle bundleWithPath: [[NSWorkspace sharedWorkspace] fullPathForApplication: #"My Application"]];
And this will return whichever (I believe) was installed most recently out of:
/Applications/My Application
/Applications/My Application 2
I want "My Application" to be returned, but the second is being returnd. I don't want to assume all applications are installed in /Applications/ so I'm not just going to loop through a folder.
Does anyone know how I can manually just loop through all applications and verify which is correct? Or a similar method to fullPathForApplication that would return all results, vs. just choosing one at random?
I believe the NSWorkspace method you're using is a facade for LSFindApplicationForInfo(), which is documented to return just a single application:
If more than one application is found matching the specified characteristics, Launch Services chooses one in the same manner as when locating the preferred application for opening an item.
If your app opens a specific file type or URL, use LSCopyApplicationURLsForURL(), which returns an array of matching apps.

Tracking individual requests to Open Graph through iOS SDK

I'm building an app, essentially a very basic Facebook client using the Facebook SDK for iOS. I have implemented the FBRequestDelegate protocol, and am sending my requests to the Open Graph API in the following way
[facebook requestWithGraphPath:#"me/friends" andDelegate:self]
This works fine, and once the requested content arrives, the SDK calls the delegate method, passing in the data
- (void)request:(FBRequest *)request didLoad:(id)result
My question is, does anyone know the best practice way to use the FBRequest passed into the delegate method to explicitly identify it as coming from my original request?
If I make several requests, how can I differentiate which request the delegate call is related to? I'm using BOOL flags, and only doing one request at a time at the moment, but it's not a good way of doing it.
Any help much appreciated :)
The method requestWithGraphPath returns a FBRequest object which will be also passed to request:didLoad later. So you can simply compare the two objects and determine if they're the same.

iOS 5 Maintain variables and state in an application?

I am new to iOS 5 programming so I'm sure that these are basic questions for the experienced folks.
I have a log in form that creates a unique session string. How can I maintain string in a way that it will be usable on all view controllers throughout the application just for that session?
How can I store a series of strings (maybe 1 or 2 of them) so that they will be available to the application on subsequent application loads? In other words, how can I maintain a default string that can be used throughout the lifetime of the application on any given device?
First, this can be stored on the Application Delegate (which is accessible like below from anywhere within your application:
YourAppDelegate.h
- (NSString *)uniqueSessionString;
View Controller:
NSString *uniqueString = [(YourAppDelegate *)[[UIApplication sharedApplication] delegate] uniqueSessionString];
Second, to save this information look at NSUserDefaults. This information will persist even after the application closes. Here is a tutorial on using it here:
http://mobile.tutsplus.com/tutorials/iphone/nsuserdefaults_iphone-sdk/
If you need to maintain this string for all of a user's devices, then you need to look at the NSUbiquitousKeyValueStore (part of iCloud). You also can use both of these methods together. See this SO question:
How to use NSUbiquitousKeyValueStore and NSUserDefaults together

iOS: Asynchronously Download Images from Web *unless* they already exists in filesystem?

In my iOS app I'm using Core Data to model a number of entities that exist in a remote Ruby on Rails application. A number of these entities reference the URLs of images stored in S3 which I need to download and store locally on the user's iDevice as needed.
My specific requirements are:
Display the image (in a UITableView usually or on its own) from the local filesystem.
IF the image doesn't exist locally I need to be able to download it in the background (usually there will be two images that need to be downloaded ... a thumbnail and an original). A default image should be displayed until the downloaded image is persisted.
Once the image is downloaded I need to have it saved in the filesystem and displayed on the screen.
I know there are a number of related posts but I'm interested to hear of what you all would consider a recommended approach based on my specific needs. Also, are there any gotchas I need to be wary of?
Thanks -wg
Use ASIHTTPRequest. Read the section on using a download cache here - http://allseeing-i.com/ASIHTTPRequest/How-to-use
Basically you'll want to turn on the cache which you can do for all requests or just your image requests:
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]]; // all requests
// specific requests
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
Then you probably want to use the cache policy:
ASIOnlyLoadIfNotCachedCachePolicy
and the storage policy:
ASICachePermanentlyCacheStoragePolicy
However multiple cache policies would meet your needs.
I'm recommending to use ASI because it solves lots of problems in an app. I recently developed my own network library, partially as an exercise and partially because I did not know about ASI and didn't like the other options I found at the time. I recently started moving everything to use ASI and I'm very happy with my choice
I have a similar requirement for a project I worked on. In my cases I wanted local files when running in test mode but remote files otherwise.
To implement this, I defined a "ResourceURLProvider" protocol within the header file for the class that would be loading the files:
#protocol ResourceURLProvider
-(NSURL *)getURLForFile:(NSString *fileName);
#end
#interface MyFileLoader {
id<ResourceURLProvider> provider;
}
#property (nonatomic, assign) id<ResourceURLProvider> provider;
In my implementation class I did something like this:
NSURL *url = [provider getURLForFile:#"myfile.xml"];
if (!url) {
url = // Some code to create the URL for the remote myfile.xml
}
If you set something up like this then you can implement your version of the provider (whatever you name it) and have it returned a URL to the cached file if it exists. If not, you return nil and the code above will use the URL to the remote location.
Unlike my case, you want to cache the file after you've downloaded it. To do that I might add another method to the protocol I defined:
#protocol ResourceURLProvider
-(NSURL *)getURLForFile:(NSString *fileName);
-(void)cacheFileData:(NSData *)data filename:(NSString *)fileName;
#end
Your implementation would look at the file name and check to see if the file was already cached. If not, the NSData (the contents of the file) would be written to your cache.
Hope that helps.

How to hardcode CFBundleIdentifier?

what else can I say, how do I hardcode the CFBundleIdentifier in the app ?
Thanks
If you want to change CFBundleIdentifier during runtime, you can’t unless you write to the application bundle Info.plist. That’s bad practice because the application bundle might have been moved to a read-only volume, or had its write permissions limited by the system administrator, or digitally signed to avoid tampering. I guess Launch Services wouldn’t recognise this change instantly and the application would have to be restarted. Furthermore, it is also a reason for rejection by the Mac Apple Store.
On the other hand, if you want to detect tampering of CFBundleIdentifier, you can always read its value upon application startup, e.g. in applicationDidFinishLaunching:
- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleIdentifier"];
if (! [bundleId isEqualToString:#"com.yourcompany.yourapp"])
{
// Ooops, CFBundleIdentifier doesn’t match
}
}
Depending on your requirements, you might want to obfuscate the code above, including the literal strings. However, in general, you won’t be able to stop a determined adversary.