ref:

http://chrisalvares.com/blog/7/creating-an-iphone-daemon-part-1/

http://chrisalvares.com/blog/30/creating-an-iphone-daemon-part-2/

http://chrisalvares.com/blog/35/creating-an-iphone-daemon-part-3/

http://chrisalvares.com/blog/38/creating-an-iphone-daemon-part-4/

http://chrisalvares.com/blog/72/creating-an-iphone-daemon-part-5/

So I thought I would start this blog of with a BANG!, and show people how to create an iPhone Daemon.

daemon is a program or application that runs in the background on the device. This differs from a regular program as it is started on boot of the device, and can run at certain intervals without the users permission. I am going to show you how to create a very simple one that polls the GPS on the iPhone, and stores the information on a database.

You will need to do the following things before we can get started.

1) Make sure your iPhone is jail broken
2) Install openSSH on your iPhone via Cyndia
3) xcode has the tool chain installed, if it does not there are very easy instructions over at the hackint0sh forums
4) Install Cyberduck/or another SFTP program on your mac

So now that we have done this, lets get coding!

Open up xcode and start a new xcode project with the open tool chain template.

The first thing to note is that it is not good to use the UIApplication class to start your daemon (it takes more memory than we need), so we are going to write our own main method.

#import
#import "CALocationDelegate.h"
 
int main(int argc, char *argv[]) {
//start a pool
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
 
//initialize our LocationManager delegate so we can pick up GPS information
DLocationDelegate *obj = [[DLocationDelegate alloc] init];
 
//start a timer so that the process does not exit, this will GPS time to fetch and come back.
NSDate *now = [[NSDate alloc] init];
NSTimer *timer = [[NSTimer alloc] initWithFireDate:now
interval:.01
target:obj
selector:@selector(startIt:)
userInfo:nil
repeats:YES];
 
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
[runLoop run];
 
[pool release];
NSLog(@"Finished Everything, now closing");
return 0;
}

You might notice that we started a timer and used the NSRunloop-run method. The run method blocks the thread, but still lets delegates (like the CoreLocationDelegate) receive delegate methods.

On the next segment, we will create the DLocationDelegate class to receive GPS coordinates, and send them to a server.

Here is part two of the blog series “Creating an iPhone Daemon”, for part one please click this link

As I said in part 1, we will be creating the DLocationDelegate class.
With most daemons, you do a task like read a file, do something with that file, sleep for a certain amount of time, then check for file changes, and repeat the steps over again. Unfortunately, with GPS coordinates, we have to wait for the CoreLocation delegate to give us the coordinates. The thing about Objective-C and Apple’s Cocoa framework is that most of the classes depend heavily on delegates. This is also true when dealing with the CoreLocation APIs. So lets get coding.

So lets write the DLocationDelegate header file first, this will give us a good look at what is ahead

#import <CoreLocation/CoreLocation.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
 
@interface DLocationDelegate : NSObject <CLLocationManagerDelegate>
{
BOOL trackingGPS;
CLLocationManager *locationManager;
}
 
@property (nonatomic, retain) CLLocationManager *locationManager;
 
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation;
 
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error;
 
-(void) startIt:(NSTimer *) timer;
-(void) startItAgain:(NSTimer *)timer;
 
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
 
@end

So lets go through this line by line starting with our imports

#import <CoreLocation/CoreLocation.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

The most important import we have here is the CoreLocation framework, this will let us use the CLLocationManager class.

@interface DLocationDelegate : NSObject <CLLocationManagerDelegate>

When you have a class name in <> symbols, Objective-C now knows that you are implementing methods from this class. In this case to receive the GPS coordinates we use the CLLocationManagerDelegate protocol

	BOOL trackingGPS;
CLLocationManager *locationManager;

The Boolean trackingGPS will tell us if we are currently tracking the GPS, this will be used to tell if the CLLocationManager is currently looking for coordinates. The locationManager is the actual class that will get the GPS coordinates from either the GPS (iPhone 3G) or the cell towers (iPhone 2G).

- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation;
 
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error;

These are the delegate methods for the CLLocationManagerDelegate. The first one “didUpdateToLocation” will give us the coordinates using a CLLocation class which contains a longitude, latitude, and sometimes even a altitude. The second function will notify our DLocationDelegate of any errors with the GPS, maybe if your iPhone is inside a lead case  .

-(void) startIt:(NSTimer *) timer;
-(void) startItAgain:(NSTimer *)timer;

We will use these functions to start the GPS after a certain amount of time.

- (void)connectionDidFinishLoading:(NSURLConnection *)connection;

This is for the NSURLConnection object that will send the GPS coordinates to our server.

In part three of this tutorial we will create the DLocationDelegate.m file (the implementation file)

This is part three of the blog series “Creating an iPhone Daemon”, for part one please click this link

In the last part of the series, we created the header file for our DLocationDelegate class, now lets create the implementation file (DLocationDelegate.h)

//
// DLocationDelegate.m
//
//
// Created by Chris Alvares on 3/25/09.
// Copyright 2009 Chris Alvares. All rights reserved.
//
 
#import "DLocationDelegate.h"
 
#define NSURLRequestReloadIgnoringLocalCacheData 1
 
@implementation DLocationDelegate
@synthesize locationManager;
 
-(id) init
{
if (self = [super init])
{
trackingGPS = false;
 
NSLog(@"starting the location Manager");
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
}
return self;
}
 
//this function is to only be called once.
-(void) startIt:(NSTimer *) timer
{
if(timer != nil) [timer invalidate];
trackingGPS = true;
[self.locationManager startUpdatingLocation];
}
 
//the difference in this function is that it invalidates the timer function, and can run more than one time
-(void) startItAgain:(NSTimer *)timer
{
if(!trackingGPS)
{
trackingGPS = true;
[self.locationManager startUpdatingLocation];
}
}
 
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
srandom(time(0)); //do this to make sure that it does not use a cached page
NSLog(@"Location found");
//if the horizontalAccuracy is negative, CoreLocation failed, and we want a good reading, so we want at least 100 meter accuracy
if([newLocation horizontalAccuracy] < 100 && [newLocation horizontalAccuracy] > 0)
{
[self.locationManager stopUpdatingLocation];
NSNumber *num = [NSNumber numberWithInt:(random())];
NSLog(@"Latitude %lf Longitude %lf", newLocation.coordinate.latitude, newLocation.coordinate.longitude);
 
NSNumber *latitude = [[NSNumber alloc] initWithDouble:newLocation.coordinate.latitude];
NSNumber *longitude = [[NSNumber alloc] initWithDouble:newLocation.coordinate.longitude];
NSNumber *altitude = [[NSNumber alloc] initWithDouble:newLocation.altitude];
 
NSMutableString *str = [[NSMutableString alloc]
initWithString:@"http://chrisalvares.com/iPhoneLocationService.php?ID=2&LATITUDE="];
[str appendString:[latitude stringValue]];
[str appendString:@"&LONGITUDE="];
[str appendString:[longitude stringValue]];
 
[str appendString:@"&ALTITUDE="];
[str appendString:[altitude stringValue]];
[str appendString:@"&RANDOM="];
[str appendString:[num stringValue]];
 
NSURL *theURL = [[NSURL alloc] initWithString:str];
 
NSURLRequest *theRequest = [NSURLRequest requestWithURL:theURL
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:120];
 
 
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:theRequest
delegate:self
startImmediately:YES];
if(connection == nil)
{
trackingGPS = NO;
}
 
NSLog(@"setting timer for 30 minutes");
NSTimer *timer = [[NSTimer
timerWithTimeInterval:1800.0
target:self
selector:@selector(startItAgain:)
userInfo:nil
repeats:NO
] retain];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
 
[timer release];
[latitude release];
[longitude release];
[altitude release];
[theURL release];
}
else
{
NSLog(@"Accuracy not good enough %lf", [newLocation horizontalAccuracy]);
 
}
}
 
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
trackingGPS = false;
 
NSLog(@"trackingGPS failed");
}
 
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"GPS information Sent");
trackingGPS = false;
}
 
 
-(void) dealloc
{
[locationManager release];
[super dealloc];
}
@end

Yes, it is a pretty big file, so I won’t explain it all (it has comments to help you).

self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;

These two lines are important, after we init the locationManager we must make sure that the delegate is set to our DLocationDelegate class.

if([newLocation horizontalAccuracy] < 100 && [newLocation horizontalAccuracy] > 0)

Inside this function, you will notice the CLLocation *newlocation’s horizontalAccuracy property. If the horizontal accuracy is less than 0, than there was an error, if it is greater than 100, the accuracy is very poor, so the DLocationDelegate class will wait for a better reading.

[self.locationManager stopUpdatingLocation];

This line is VERY important, we have to stop the GPS from updating, otherwise the iPhone’s batter will die super quickly.

NSMutableString *str = [[NSMutableString alloc]
initWithString:@"http://youriphonelocationserver.com/locationService.php?ID=2&LATITUDE="];
[str appendString:[latitude stringValue]];
[str appendString:@"&LONGITUDE="];
[str appendString:[longitude stringValue]];
 
[str appendString:@"&ALTITUDE="];
[str appendString:[altitude stringValue]];
[str appendString:@"&RANDOM="];
[str appendString:[num stringValue]];

When you put everything together, you should get a link like:

http://youriphonelocationserver.com/locationService.php?ID=iphoneid&LATITUDE=laditudeNumber&LONGITUDE=longitudeNumber&ALTITUDE=number&RANDOM=12312

We will create this PHP file in an upcoming tutorial.

NSTimer *timer =  [[NSTimer
timerWithTimeInterval:1800.0
target:self
selector:@selector(startItAgain:)
userInfo:nil
repeats:NO
] retain];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

The DLocationDelegate timer is set for 1800.0 seconds, which is 30 minutes. I found that 30 minutes does not drain the battery too much, but still has a good amount of readings just incase your iPhone is lost.

While this will get your DLocationDelegate class setup, we still have one more issue, and that is that the iPhone will go into a hard sleep after a minute of no use. We will fix this in an upcoming tutorial.

This is part four of the blog series “Creating an iPhone Daemon”, for part three please click this link

This is the coolest part of the series. Up until now, all the code can only be used as a standalone application that can only run if the user clicks the “DLocationDemon.app” button on the springboard. Now it is time to put it all together, with the Daemon Plist file.

You will also need SSH installed for this part (again, the hackint0sh forums) I use Cyberduck as my SSH client (Select SFTP for SSH and type in the IP of your iPhone with root/alpine as username/password respectively).

The first thing we do is compile our DLocationDemon project. Please use the method over at hackint0sh to compile and codesign your project successfully.
Once you have compiled your project, you should get a DLocationDemon.app in the “Products folder” right click on the .app file and click “Reveal in Finder”.

Right click on the .app file and click “Show Package Contents” and make sure you have a DLocationDemon file inside the folder

Next, using your favorite SFTP program, dumb the DLocationDemon.app inside the /Applications folder of your iPhone

**NOTE** Make sure this is the /Applications folder and not the /var/root/Applications folder. You can tell the difference because all of the apps you downloaded from the AppStore should be in the /Applications folder.

The next thing we have to do is create the .plist file for the daemon to work.
I have named mine com.chrisalvares. DLocationDemon.plist, this should match the bundle identifier in the info.plist file.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.chrisalvares.DLocationDemon.plist</string>
 
<key>ProgramArguments</key>
<array>
<string>/Applications/DLocationDemon.app/DLocationDemon</string>
<string></string>
<string></string>
</array>
 
<key>OnDemand</key>
<false/>
 
<key>StandardErrorPath</key>
<string>/dev/null</string>
 
<key>Disabled</key>
<false/>
</dict>
</plist>

Make sure the label field matches the bundle identifier in your info.plist file.

Now SFTP into your iPhone again and drop this plist file into the “/System/Library/LaunchDaemons” folder. You should see at least one other daemon.plist file there. (I believe this is where the SSH daemon is).

Now restart your iPhone.

This will give you a working daemon installed on your iPhone!

This is part five of the blog series “Creating an iPhone Daemon”, for part four please click this link

iPhone 3.0 just came out, and while the old code set will still work with it, I decided to go back and clean up and organize the code a little bit more. Here is the CALocationDemon Xcode project. I also equipped it with the PHP and daemon plist file needed.

Get it here (http://chrisalvares.com/blog/wp-content/uploads/2009/06/calocationdemon.zip)

[转]Creating an iPhone Daemon的更多相关文章

  1. Creating a Linux Daemon (service) in Delphi

    With the introduction of the Linux target for Delphi, a wide range of possibilities are opened up to ...

  2. iPhone 6 Screen Size and Web Design Tips

    Apple updated its iPhone a bit ago making the form factor much bigger. The iPhone 6 screen size is b ...

  3. HOWTO: Create native-looking iPhone/iPad applications from HTML, CSS and JavaScript

    HOWTO: Create native-looking iPhone/iPad applications from HTML, CSS and JavaScript Though it's not ...

  4. 非常优秀的iphone学习文章总结!

    This site contains a ton of fun tutorials – so many that they were becoming hard to find! So I put t ...

  5. Error response from daemon: error creating overlay mount to /var/lib/docker/overlay2

    环境:centos7.1 docker run -t -i centos /bin/bash 运行上面的命令开启容器时报错: /usr/bin/docker-current: Error respon ...

  6. Creating and Using Static Libraries for iPhone using Xcode 4.3

    Recently, after developing a collection of applications for iPhone that were intended to be used as ...

  7. Creating a radius based VPN with support for Windows clients

    This article discusses setting up up an integrated IPSec/L2TP VPN using Radius and integrating it wi ...

  8. How to load a local .CSS file & JavaScript resources using iPhone UIWebView Class

    This post will cover the basic setup and creation of an application with web content for iPhone that ...

  9. iPhone:4.7 5.5 4 3.5 对应的各个设备屏幕尺寸对应的像素及App上线信息

    Shared App Information You can access these properties from the App Details page in the App Informat ...

随机推荐

  1. hdu Lowest Bit

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1196 大水题   lowbit   的应用    (可以取出一个数二进制中的最后一个1.树状数组常用, ...

  2. 写一个根据id字段查找记录的缓存函数(javascript)

    前不久在参加面试的时候遇到了这样一道题,"写一个根据id字段查找记录的缓存函数,如果之前查过,则直接返回之前查找过的对象,而无须重新查找".当时由于时间较短加上时间比较紧张,考虑并 ...

  3. Linux开发环境的搭建和使用——Linux本必备软件SSH

    SSH 至 Secure Shell 缩写.由 IETF 网络工作组(Network Working Group)开发:SSH 以建立应用层和传输层安全协议中的基础上. SSH 是眼下较可靠,专为远程 ...

  4. sgu139Help Needed!推断15数码是否有解,以及推断N数码是否有解的推论

    是这种,要你推断一个15数码是否有解. 我不会,找了这样一个方法. 将16个数按出现顺序存放在一维数组里面, 然后累加每一个数的逆序对数目, 还要加上0到终态的曼哈顿距离,得到一个数x. 因为最后的状 ...

  5. 条形码(JBarcode)

    一世尘梦 少小离家老大回,妖娆尘世,程序唧唧:问君能有几多愁,恰是满屏BUG无处修. 商品条形码(JBarcode) 之前没有使用过这个,现在使用JBarcode生成商品条形码,工作之前的准备工作: ...

  6. CSS3制作

    目标是制作如下面DEMO显示的一个日历效果: HTML Markup 先来看看其结构: <div class="calendar"> <span class=&q ...

  7. [Unity-7] Update和FixedUpdate

    1.Update和FixedUpdate这是Unity既用内提供的帧功能接口相关联. Update():这个函数里面的内容每一帧都会被运行一次.这个函数有一个特点,那就是运行的频率等于帧率.而这个帧率 ...

  8. HTTP2协议之HPACK--之头部压缩规范介绍

    接下来打算把HTTP2协议的头部压缩算法给翻译下,敬请等候. HPACK - Header Compression for HTTP/2 HPACK:HTTP/2头部压缩 概要说明 这个规范定义了HP ...

  9. ubuntu下的apache+php+mysql的安装

    平时我都时在windows下搭配apache+php+mysql环境的,只不过后来听别人说在linux下搭配apache+php+mysql更受欢迎,而且一般公司也是用这样的搭配,所以今天在试着在ub ...

  10. 使用Flexible实现手淘H5页面的终端适配(转)

    曾几何时为了兼容IE低版本浏览器而头痛,以为到Mobile时代可以跟这些麻烦说拜拜.可没想到到了移动时代,为了处理各终端的适配而乱了手脚.对于混迹各社区的偶,时常发现大家拿手机淘宝的H5页面做讨论—— ...