
As a developer, you probably know that Apple's iApps are tightly
integrated with the .Mac services. But what about your own application?
If you could integrate your application with .Mac, you could provide your users with innovative new networked features, delivered as seamlessly as they've come to expect from using the iApps.
Apple has been thinking that way, as well; and now you can easily
hook your application up to the features and benefits of the .Mac
“mother ship” just like those iApp applications. The DotMac
Software Development Kit (SDK), whose components include the DotMac Kit, was released
at Apple's Worldwide Developer Conference in June, 2004. The SDK gives you everything you need to build
applications that take advantage of the .Mac services. And if that
weren't enough, by embedding the DotMac Kit into your application you
also stand to collect a significant bounty on each new .Mac member you
bring in.
This article introduces you to the .Mac SDK from a developer's
perspective. We'll cover the components of the .Mac SDK, how it works, why
you want to use it, and how you use it to build applications
integrated with .Mac services. Finally, we'll look at real-world examples of .Mac integrations, to spark your imagination about the possibilities for creating innovative new features for your own application.
Why Integrate with .Mac?
Integrating with .Mac brings your application powerful networked features, easily and with a great user experience. The universal
namespace inherent in .Mac bridges the local world with the online
world, and allows data to flow seamlessly between the two. Here are
just a few things .Mac has to offer to your application at no cost:
-
Services based on stable, secure, and broadly-accepted open
standards. .Mac supports network access via WebDAV, HTTP,
XML-RPC, and other open standards. But integrating with .Mac requires no
network programming on your part, so you can focus on developing product features rather than implementation details.
-
Always-on "store and forward." Integrating .Mac gives your
desktop application the simplest direct-to-Web publishing/storage
available. Every .Mac account includes 250 MB of combined storage
space, of which the user is free to allocate as much as they like to your application. You can
easily publish data, subscribe to data, and share documents in a
distributed workflow.
-
Painless account management. Creating credentials,
resetting passwords, and other account management details are all
handled for you. No assembly required.
-
Access to over one-half million members. Your application
can instantly tap into a growing number of .Mac members. In
addition, customers are more likely to use, and stay with,
your product because of its integration with .Mac.
-
Highly scalable services. Just how scalable? The iDisk service alone
has 7+ TB (yes, that's trillions of bytes) downloaded and 1/2+ TB
uploaded per week. It offers over 1.5Gbps of available bandwidth
that can be increased on demand. That's one less scalability
problem that you have to worry about.
- .Mac Affiliate Program. Simply embed the DotMac
Kit into your application and join the .Mac Affiliate Program, and you've built yourself an additional income stream. For each
new .Mac member that signs up through your application, you'll get paid. Any developer—ISV, shareware, open source—can join the Affiliate Program.
-
Systems support and monitoring 24/7. Simply put, it's a
dedicated group of folks at .Mac whose lives can be interrupted by
a cell phone. Better them than you.
-
The opportunity to stand out in your market. You simply
can't do this on any other platform. No other operating system
gives you access to a universal credentialed namespace and
Internet-based services built on open standards.
In summary, integrating with .Mac can significantly reduce your
development time and cost by providing network services, without your having to worry about
protocols, security, servers, or other backend services and maintenance.
What Is the .Mac SDK?
Taking advantage of .Mac within your application starts with the .Mac SDK. Unveiled at WWDC, the.Mac SDK includes the DotMac Kit—an embeddable framework that
allows you to tightly integrate the Internet-based .Mac services with
your application—all without any network programming. ADC members can download it at no cost, and it's available today. (Membership is free; to learn more, check out the ADC Membership page.)
Because the DotMac Kit is an embeddable framework, not part of the core
operating system, you can use it in applications running on Mac OS X
versions 10.2.6 and higher. And although the
DotMac Kit has only been available since WWDC 2004, it has been
tested the best possible way—through real-world use. The code is already in use by many of the .Mac services
like HomePage, and a wide range of third-party applications, including
Intuit QuickBooks.
How Data Flows
The DotMac Kit fully supports both asynchronous and synchronous data
flow between your application and the .Mac services. All operations
are asynchronous by default, but you can set synchronous behavior at
any time. Asynchronous is preferred because it means that your
application can go about its business while data is moving on the
network.
Figure 1 shows the sequence of events for an asynchronous upload. The
putData:toPath: method returns immediately, but your delegate
object is called asynchronously to signal that the upload has
completed or failed with an error.
Figure 1:
Uploading data asynchronously.
Figure 2 shows the same operation performed synchronously. In this
case, the putData:toPath: method blocks until the upload has
completed or failed with an error.
Figure 2:
Uploading data synchronously.
You can safely flip between asynchronous and synchronous operations
without affecting transactions already in progress. And it's all
thread-safe. You don't have to worry about threading issues, run
loops, or any of that other madness.
The DotMac Kit Framework Classes
The DotMac Kit framework uses a simple "session" style Cocoa API for
moving data between desktop applications and .Mac services. It also
offers a neat wrapper around the .Mac services to shield you from all
the gory protocol, security, and server details. Let's look at the
three classes in the framework that you'll use, shown in Figure 3.
Figure 3:
DotMac Kit Framework Classes.
The DMMemberAccount class encapsulates a .Mac member account.
When you create a DMMemberAccount object, you can instantiate
it with credentials from system preferences—or, optionally, with a
user-specified user name and password. After creating a
DMMemberAccount object, you use it to validate the member's
credentials, check when the account will expire, determine which .Mac
services are available for the account, upgrade an account, or even sign
up a new .Mac member.
Once you have a DMMemberAccount object, you can then use it
to create a .Mac service session object. The first version of the DotMac Kit provides a session for working with the iDisk Service. A DMiDiskSession
object is a remote proxy that initiates transactions to handle all
synchronous and asynchronous I/O with the .Mac iDisk service. With a
DMiDiskSession object in hand, you can perform a rich set of
operations such as uploading and downloading data, moving and
copying resources, locking and unlocking resources, and listing
server-side contents. Each DMiDiskSession object
encapsulates a specific iDisk. Any iDisk or Public Folder may be
accessed provided that the credentials in the DMMemberAccount
object grant the appropriate access.
All of the response details, including tracking transaction states,
monitoring progress, handling errors, and returned results of a
specific operation are encapsulated in a DMTransaction
object. Indeed, a DMTransaction object does all the real
work. DMTransaction
objects are created by both DMMemberAccount
and DMiDiskSession objects, offering an elegant way to handle
both synchronous and asynchronous communication through the same API.
Getting Started
Now it's time to put the DotMac Kit to good use. We'll walk through
how to integrate it into your application step-by-step.
- Become A (Trial) Member. To start using the DotMac Kit, you
need a .Mac account. If you aren't ready to purchase a full membership,
you can get a 60-day free
trial .Mac membership. Doing so now will give you a unique identity
to test your application's integration with .Mac. Go to www.mac.com for more information on a .Mac account and its benefits.
- Get your Creator Code. Apple provides a location online for
submitting your request as part of the ADC Data Type
Registration set of forms—use the Creator Code Registration form.
- Embed DotMac Kit in Your Application. Unlike system frameworks that are shared by other applications, the
DotMac Kit framework is designed to reside in your application
bundle's private
Frameworks directory. Embedding the DotMac
Kit framework in your application guarantees that your application is
always linked to the correct version of the framework. And the whole
kit is just over 500 KB, so it doesn't bloat your application.
After downloading the DotMac Kit, follow these steps to embed the
DotMac Kit into your application:
-
Add the
DotMacKit.framework bundle to your Xcode project.
In Xcode, choose Project > Add to Project and navigate to the
directory where you downloaded the DotMacKit.framework.
Then drag the DotMacKit.framework to the "Frameworks >
Linked Frameworks" folder in Xcode's "Groups & Files" browser.
-
Create a Copy Files build phase to ensure that the DotMac Kit
framework will be copied your application's
private
Frameworks directory. To do that, select your
application target and choose Project > New Build Phase
> New Copy Files Build Phase. Then, in the Inspector
window for the new build phase, choose "Frameworks" in the
Destination pop-up menu.
-
Finally, drag the
DotMacKit.framework listing in the
"Linked Frameworks" folder to the Copy Files build phase you just
created for your application target.
When you've taken care of these steps, you're ready to write some code
and start incorporating the DotMac Kit into your application.
Using the DotMac Kit API
It doesn't take much code to start slushing data around. The
following examples show you the basics:
- Checking a member account
- Signing up a new member
- Uploading data
- Downloading data
Using these examples as a guide, you can quickly enable your
application with push-button collaboration.
Checking a Member Account
The first order of business is to create a DMMemberAccount
object, using the line of code below (note that the four dashes in @"----" should be replaced with your unique Creator Code).
DMMemberAccount *myMemberAccount = [DMMemberAccount accountFromPreferencesWithApplicationID:@"----"];
The accountFromPreferencesWithApplicationID: class method
uses the credentials stored in the .Mac preferences on your system.
This is handy because it means you don't have to prompt the user for
her credentials.
The application ID is your "meal ticket," that is, it's the unique
identifier that lets you get paid for new .Mac customers who sign up
through your application. So don't
forget to obtain a
Creator Code for each application that uses the DotMac Kit.
It's also a good idea to set the application name on
the DMMemberAccount. This will become increasingly useful
over time as the DotMac Kit is revised.
[myMemberAccount setApplicationName:@"My Killer .Mac App"];
Next, validate the credentials.
if ([myMemberAccount validateCredentials] != kDMSuccess) {
// invalid credentials - sign them up?
}
If the credentials validate, then you're set. If not, then you might
want to offer to sign the user up. We'll talk about that shortly.
Once you have validated the credentials, the next step is to verify
that the .Mac service your application will use is available to the
member account. In this example, we'll assume that you want to check
the service availability using a synchronous (blocking) call.
Remember that the DotMac Kit defaults to asynchronous. You must
specify when you want synchronous behavior.
The following code verifies that the iDisk service is available using
a synchronous transaction:
[myMemberAccount setIsSynchronous:YES];
DMTransaction *serviceTransaction = [myMemberAccount servicesAvailableForAccount];
if ([serviceTransaction isSuccessful]) {
NSArray *services = [serviceTransaction result];
if ([services containsObject:kDMiDiskService] == NO) {
// iDisk service is not available
}
} else {
// handle error
}
Finally, check to see if the account will expire soon. This is a
proactive way to nudge your users to upgrade their .Mac account before
it expires and they can't use the .Mac features of your application.
DMTransaction *daysLeftTransaction = [myMemberAccount daysLeftUntilExpiration];
if ([daysLeftTransaction isSuccessful]) {
NSNumber *daysLeft = [daysLeftTransaction result];
if ([daysLeft intValue] < 30) {
// display a reminder message with a prompt, and then...
[myMemberAccount upgradeAccount];
}
} else {
// handle error
}
Signing Up a New Member
If a user of your application is not yet a .Mac member and cannot
fully enjoy your application's features without a .Mac account, sign
them up... and don't forget you qualify for a commission for doing so.
[DMMemberAccount signUpNewMemberWithApplicationID:@"(your creator code here)"];
This method opens the .Mac sign-up page in the user's default browser.
Specifying your unique application ID ensures (assuming you're a
member of the .Mac Affiliate Program) that you'll earn a commission if
the user becomes a paying .Mac member.
You can also obtain the URL for the .Mac sign-up page directly, for
cases where you would like to display the page within your own user
interface.
NSURL *url = [DMMemberAccount signUpURLWithApplicationID:@"(your creator code here)"];
A note of caution: The URL may change in the future, so use the URL
returned by this method rather than hard-coding it into your
application.
Uploading Data
Given a valid DMMemberAccount object, you're ready to start moving
bits. Up to this point, we've been using synchronous operations
because the I/O for checking the member account was relatively
lightweight. However, you want to use asynchronous transactions as
much as possible to offer the best user experience—and it's the
default for the DotMac Kit.
To upload data to an iDisk, create a DMiDiskSession with
the DMMemberAccount object.
DMiDiskSession *mySession = [DMiDiskSession iDiskSessionWithAccount:myMemberAccount];
Then initiate an asynchronous transaction that publishes arbitrary
data to a path on the iDisk. The following example publishes a simple
message to a file in the member's Documents folder:
NSString *message = @"Hello, .Mac!";
NSData *messageData = [message dataUsingEncoding:NSASCIIStringEncoding];
DMTransaction *uploadTransaction = [mySession putData:messageData toPath:@"/Documents/upload.txt"];
if (uploadTransaction != nil) {
// asynchronous transaction is in flight
}
Notice in this example that the message is first wrapped in
an NSData object before being uploaded. We'll look at
convenience methods for placing the contents of local files into
server-side files a bit later.
Since the upload transaction is asynchronous, how do you know whether
it was successful? One way is to use the following methods to check the transaction's state and monitor its progress through polling:
int transactionState = [uploadTransaction transactionState];
SInt64 bytesToMove = [uploadTransaction contentLength];
SInt64 bytesMovedSoFar = [uploadTransaction bytesTransferred];
Displaying the results of these methods gives the user some indication
of the work in progress. For the most responsive user experience,
it's also a good idea to register a callback delegate with the
DMiDiskSession object. We'll do just that in the next
example.
Downloading Data
Next, we want to turn around and get the data that we just uploaded.
The DMiDiskSession object used in the previous example is
still set for asynchronous behavior. However, in this case we set a
delegate on the DMiDiskSession object, and then call
the getDataAtPath: method of the DMiDiskSession
object.
[mySession setDelegate:self];
DMTransaction *downloadTransaction = [mySession getDataAtPath:@"/Documents/upload.txt"];
if (downloadTransaction != nil) {
// asynchronous transaction in flight
}
Using a delegate lets you track coarse-grained transaction state
changes. You can combine this with the asynchronous polling technique
from the last example to create a very responsive user experience. Also, please note that a DMiDiskSession's delegate is only messaged by asynchronous transactions. For example, you could use an NSTimer to poll the transaction
progress and display it in a progress bar. Then when the delegate is
messaged, the flow of the code changes to handle the transaction's
result.
The delegate object must conform to the
informal DMTransactionDelegate protocol which defines three
callback methods for asynchronous transaction operations. Here are
the methods with skeleton implementations:
- (void)transactionSuccessful: (DMTransaction *)theTransaction {
NSData *result = [theTransaction result];
NSString *resultString = [[NSString alloc]initWithData:result encoding:NSASCIIStringEncoding];
}
- (void)transactionHadError: (DMTransaction *)theTransaction {
// asynchronous transaction failed
int errorType = [theTransaction errorType];
}
- (void)transactionAborted: (DMTransaction *)theTransaction {
// asynchronous transaction was cancelled
}
When the transaction has successfully completed, the delegate's
transactionSuccessful: method is called. Use
the result method of the provided DMTransaction
object to obtain the results of those operations that provided a result object. The
NSData object refers to memory-mapped data that, in this
case, is used to create an encoded string.
Note that every transaction can have a different delegate. Simply set
a delegate on the DMiDiskSession object and the next
asynchronous transaction you initiate will message that delegate.
Convenience Methods
To further enable its quick and painless adoption, the DotMac Kit API
also provides NSFileManager-style, synchronous-only methods to move
local files to and from .Mac, and manage resources already on .Mac. The
DMiDiskSession class defines the following methods, for
example:
- createFileAtPath:contents:attributes:
- createDirectoryAtPath:attributes:
- movePath: toPath:handler:
- copyPath: toPath:handler:
- removeFileAtPath:handler:
- contentsAtPath:
- fileExistsAtPath:
These examples have given you a broad view of the DotMac Kit API. For more depth, check out the API documentation and the two sample projects included with the SDK. In our final section below, we look at a few more of the interesting problems you can solve with the DotMac Kit.
What Could You Do?
Armed with this information, you're ready to build applications with
networked features to leverage .Mac's services and member community, and earn revenue while doing it.
What could you do with the DotMac Kit at your fingertips? Here are
just a few examples to help engage your imagination:
- Store and sync software registration information.
Imagine
your machine has a total meltdown and you don't have a current
backup. Usually, you'd have to manually re-enter all the
registration information for your favorite licensed application.
But if that application uses the DotMac Kit and stores all of your
registration details in your .Mac account, then you wouldn't need
to do anything. The next time you launch the application, it
uses your credentials to automatically grant you access to
the application. And because the registration is tied to your
.Mac credentials—rather than to a specific machine—you could use
the application across multiple machines. Further, you could encrypt the information before uploading it to the user's iDisk, and place it in the Documents folder so that it is not web published.
-
Synchronize application preferences across multiple Macs. Many of your favorite
applications have lots of configurable options, such as the
relative size and placement of various windows and palettes. Trouble is, you
use those applications on your iMac at home and your G5 in the office. Wouldn't it
be convenient if the application preferences were stored on your
iDisk so that all the palettes were sized and placed uniformly
across multiple machines?
-
Lightweight collaboration. You don't necessarily have to
read and write to only your iDisk. You can also read from and write
to any .Mac member's Public folder provided you have permissions to
do so. Say, for example, you're on a team developing creative web
content. One of the team members has a document in his Public folder
that's shared by the team. You can generate content in your local
memory, push it up to the server-side document, and then publish the
content. Not everybody has to be online at the same time, and when
they are, using the locking features of the DotMac Kit, the shared
document is protected from concurrent edits. Even better, because
iDisk and HomePage work together, you can publish web reports
on project status or other key metadata at the same time.
Until now, you may have thought of .Mac as just a great big hard drive
in the sky. The DotMac Kit turns it into a digital hub for your
applications. And so the question really is: What couldn't you do
with it?
Conclusion
Using the DotMac Kit, your application can leverage the .Mac services
in the same way that Apple's iApp applications use those services
today. The result is a win-win for everyone. Your application will
stand out from the crowd. Your application's users will enjoy
unparalleled features. And as a .Mac affiliate, you'll earn a
commission every time your application signs up a new .Mac member. So
what are you waiting for?
For More Information
This article has introduced you to the power of the DotMac Kit. The
following references will help you dig in deeper:
Also, the O'Reilly book Inside .Mac by Chuck Toporek is an excellent
introduction and reference guide to the .Mac services
Updated: 2005-09-20
|