読者です 読者をやめる 読者になる 読者になる

プログラマでありたい

おっさんになっても、プログラマでありつづけたい

iPhoneのスリープボタンが効かなくなってきたので、即ロックアプリを作った話

iOS iPhone

 常に手元にあって気がついたら触ってしまうiPhoneですが、最近スリープボタンの効きが悪くなってきました。ホームボタンとスリープボタンは、iPhoneのなかで数少ない物理的なボタンです。特にiOSの設計思想上、ホームボタンは常に押す必要があるので、へたりやすいです。またアプリから即スリープさせることが出来ないので、スリープボタンも同様です。


 ということで、アプリから即スリープ出来ないのか検討してみました。iTunesストアを見る限りは、その手のアプリはありませんでした。ジェイルブレイク(脱獄)前提のQuickLock2というアプリだと実現出来るようなので、非公開APIでは実現出来るようです。ということで、それっぽいのを探しました。GSEventLockDeviceというのがあったので、それを調べてるとGitHubにLockMeというソースが公開されていました。即スリープは出来ないのですが、即ロックは実効できます。ロック後、10秒程でスリープになるので、ほぼ欲しいモノと同じです。
 しかし、このアプリを呼び出す為にホームボタンを押す必要があるので、物理的なボタンを押さないといけないのには変わりありません。通知センター使えばホームボタンいらんやんと思って、アプリを作ってみました。


肝の部分のロックは、下記の通りです。LockMeそのままです。

char *framework = "/System/Library/PrivateFrameworks/GraphicsServices.framework/GraphicsServices";
void *handle= dlopen(framework, RTLD_NOW);
if (handle){
	// Get the symbol address for the screen locking function
	void (*GSEventLockDevice)() = dlsym(handle, "GSEventLockDevice");
	if (GSEventLockDevice){
		// Lock the screen
		GSEventLockDevice();
	}
	dlclose(handle);
}
exit(0);


 ちなみにexit(0)でアプリの終了できます。ホームボタンを押さずに終了ですね。使う時は、警告を出さないとアップルのインターフェースガイドラインを通らないようです。同様に、

[[UIApplication sharedApplication] terminateWithSuccess];

を使えばアプリも終了できます。が、こちらは非公開メソッドなので確実に審査通りません。


 ついでにランチャーも作ろうと思ったのですが、通知センターを使ったランチャーを作ろうとしたのですが、既に一杯あったので今は見送りです。やっつけのソースですが、GitHubに登録しているので興味がある人は見てください。
 登録済みのソースは、即終了になるようになってるので一度通知を受け取るように適当に修正してください。あとLocalNotificationの所を調整しようとしていますが、取得済み&未削除の通知を2回目以降受け取ると下記のようなエラーが出るのでほったらかしです。

LocalNotificationError: data was of an unexpected class -> expected UILocalNotification received (null)


追記:
iOS7にしたら、GSEventLockDevice()が効かなくなりました。
今は、Assistive Touchを使っています。


See Also:
dkfj/SleepLancher


参照:
jadehopper/LockMe