バックグラウンド動作中のアプリから前面にアラートを送ってみたのこと



iOS4のマルチタスキングねた第二弾。
(第一弾はこちら: http://d.hatena.ne.jp/epocha/20100608/1276022504)


前回作成した、

(ラーメ…マー)


ことラーメンタイマーが全然タイマーにならないので、
バックグラウンドで動作中、3分たったときに前面にアラートを出してみることにしました。
というわけで、カウントアップのメソッドをいじります。


前回のコード

- (void)countUp {
	count++;
	[timerLabel setText:[NSString stringWithFormat:@"%d", count]];
	[self performSelector:@selector(countUp) withObject:nil afterDelay:1.0];
}



今回のコード

- (void)countUp {
	count++;
	if(count == 180) {
		UILocalNotification *localNotif = [[UILocalNotification alloc] init];
		if (localNotif) {
			localNotif.alertBody = @"ラーメンできたよ!";
			localNotif.alertAction = @"食べない";
			localNotif.soundName = @"alarmsound.caf";
			[[UIApplication sharedApplication] presentLocalNotificationNow:localNotif];
			[localNotif release];
		}
	}
	[timerLabel setText:[NSString stringWithFormat:@"%d", count]];
	[self performSelector:@selector(countUp) withObject:nil afterDelay:1.0];
}



かなり適当な実装ですが、テストなので良しとします。
やっていることは、

  1. UILocalNotificationのインスタンスを作成
  2. alertBody, alertAction, soundNameを指定
  3. アプリのUIApplicationインスタンス([UIApplication sharedApplication]で取得)にpresentLocalNotificationNowで投げる

以上。
alertActionは「OK」ボタンに相応するボタンの文字列を指定します。





こんな感じで表示されます。
「食べない」と書いてあるボタンを押すと、呼び出し元のアプリが起動されます。


ね、簡単でしょ。


http://twitter.com/epoch__


参考にしたページ:
https://devforums.apple.com/community/iphone/40beta/multitasking
(要デベロッパー登録)

iOS4のマルチタスキングを試してみたのこと

1. 普通に作ってみる


ラベルの数字を1秒おきにカウントアップするアプリを作ってみます。

本来ならば起動時刻からの経過時間から測るのが筋だろうと思いますが、

それではバックグラウンドで動かす意味がありませんので、

performSelector:withObject:afterDelay:による動作遅延でカウントアップするようにしました。


(ラーメ…マー)


ビューベースのアプリケーションで、UIViewControllerのサブクラスの実装はこんな感じ。

- (void)viewDidLoad {
	[super viewDidLoad];

	count = 0;

	timerLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 280, 400)];
	[timerLabel setText:[NSString stringWithFormat:@"%d", count]];
	[timerLabel setBackgroundColor:[UIColor clearColor]];
	[timerLabel setFont:[UIFont fontWithName:@"Helvetica-Bold" size:150]];
	[timerLabel setTextAlignment:UITextAlignmentCenter];
	[self.view addSubview:timerLabel];

	[self performSelector:@selector(countUp) withObject:nil afterDelay:1.0];
}

- (void)countUp {
	count++;
	[timerLabel setText:[NSString stringWithFormat:@"%d", count]];
	[self performSelector:@selector(countUp) withObject:nil afterDelay:1.0];
}

簡単ですね。



こんな感じで動きます。



↓ ホームボタンでしまってみる。



↓ 数秒後、再度アプリを起動。



と、二回目の起動で終了前の状態が復元されていることがわかります。


じつは、iOS4SDKでビルドしたアプリはデフォルトでレジューム機能を備えているので、

ホームボタンで閉じたアプリを再度開くことで、終了前の状態に復元することができます。

もちろん、ホームボタンのダブルタップによる他のアプリケーションへの切り替えや、

アプリ内から他のアプリを起動した場合にも有効です。


さて、ここまではデフォルトの実装です。

バックグラウンドでアプリケーションを動かすには、もう少し手間を加える必要があります。


2. バックグラウンドで動かしてみる


OS4.0 のSDKでアプリケーションを作成すると、AppDelegateにバックグラウンド動作周りのデリゲートメソッドが追加されています。

- (void)applicationWillResignActive:(UIApplication *)application {
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
}

- (void)applicationWillTerminate:(UIApplication *)application {
}

ここに色々と実装していきます。

今回使うのは、

  • (void)applicationDidEnterBackground:(UIApplication *)application;


だけ。

他のメソッドどのタイミングで呼ばれているのか、詳しくはわかっていないです。

このメソッドは、アプリケーションがバックグラウンドに入ったとき(ホームボタンを押した・他のアプリケーションを起動した etc...)に呼ばれます。


その前に、下準備としてAppDelegateのメンバ変数を作っておきます。

@interface RTAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    RTViewController *viewController;
    UIBackgroundTaskIdentifier backgroundTask; // これ!
}

UIBackgroundTaskIdentifier型の変数。

名前の通り、バックグラウンドで動作するタスクを捕まえることができるID(のようなもの)です。

で、デリゲートメソッドに戻って実装。

- (void)applicationDidEnterBackground:(UIApplication *)application {
	backgroundTask = 
	[application beginBackgroundTaskWithExpirationHandler: ^{
		[application endBackgroundTask:backgroundTask];
	}];
}

こんな感じ。

^{}の中はObjective-Cのブロッククロージャで、

ブロック内の処理を例外ハンドラに設定しつつ、バックグラウンドタスクを開始しています。


たったこれだけで、アプリが裏にいる間もカウントアップが行われます。



↓ ホームボタンでしまう。



↓ 数十秒後、再度アプリを起動。



じゃじゃーん。簡単ですね。


ちなみに、アプリのバックグラウンド動作には時間制限があるようで、
残り秒数はUIApplicationのインスタンスメソッド、backgroundTimeRemainingで確認できます。


続き: バックグラウンド動作中のアプリから前面にアラートを送ってみたのこと
http://d.hatena.ne.jp/epocha/20100608/1276022408


http://twitter.com/epoch__


参考にしたページ:

https://devforums.apple.com/community/iphone/40beta/multitasking

(要デベロッパー登録)