2.2.1でビルドしたアプリから、3.0で追加されたAPIを使ってみました
先ほど、SysStats Liteに、バッテリ残量の表示を追加して、アップデートを申請しました。
やることは非常に簡単なのですが、その中で、少しだけ悩んだことがありました。バッテリ残量取得のAPIは、OS3.0以降で追加されたので、ふつうにコーディングすると、OS2.2.1環境では、コンパイルが通りません。かといって、3.0でビルドしてしまっては、2.2.1では動作させることができなくなってしまいます。
ということで、2.2.1でビルドしたアプリから、3.0で追加されたAPIを使う方法を、メモを兼ねて書いておきたいと思います。
これと同じようなことをしたい場合、3.0以降で追加されたAPIについては、NSInvocationクラスを使って、動的に呼び出してやることで、回避することができます。*1
バッテリー残量を取得するためには、UIDeviceクラスに定義されている、以下の2つのプロパティにアクセスする必要があるので、これらを動的に呼び出します。
- batteryMonitoringEnabled
- batteryLevel
あと、これらのプロパティは、3.0以降で実行されている場合にのみ存在しているので、存在チェックが必要となります。
以下に、実際のコーディング例を示します。
+ (float)batteryLevel { float batteryLevel = -1; UIDevice *device = [UIDevice currentDevice]; if([device respondsToSelector:@selector(batteryLevel)]) { // batteryLevelプロパティの存在チェック // batteryMonitoringEnabledプロパティのメッセージ定義 NSMethodSignature *setBatteryMonitoringEnabledSig = [UIDevice instanceMethodSignatureForSelector:@selector(setBatteryMonitoringEnabled:)]; NSInvocation *setBatteryMonitoringEnabledInv = [NSInvocation invocationWithMethodSignature:setBatteryMonitoringEnabledSig]; [setBatteryMonitoringEnabledInv setTarget:device]; [setBatteryMonitoringEnabledInv setSelector:@selector(setBatteryMonitoringEnabled:)]; BOOL batteryMonitoringEnabled = YES; [setBatteryMonitoringEnabledInv setArgument:&batteryMonitoringEnabled atIndex:2]; // batteryLevelプロパティのメッセージ定義 NSMethodSignature *batteryLevelSig = [UIDevice instanceMethodSignatureForSelector:@selector(batteryLevel)]; NSInvocation *batteryLevelInv = [NSInvocation invocationWithMethodSignature:batteryLevelSig]; [batteryLevelInv setSelector:@selector(batteryLevel)]; [batteryLevelInv setTarget:device]; // batteryMonitoringEnabledプロパティにYESを設定 [setBatteryMonitoringEnabledInv invoke]; // batteryLevelプロパティから値を取得 [batteryLevelInv invoke]; [batteryLevelInv getReturnValue:&batteryLevel]; } return batteryLevel; }
他にも、OSのバージョンをチェックして、処理を振り分けるなど、いくつか方法はあると思いますが、今回の場合は、使用するAPIが限定的なので、上記のような形で実装しました。
とりあえず、非公開APIや、偶然の実行結果を使用しているわけではなく、正式にサポートされている方法なので、審査でリジェクトされることはないと思っていますが、とりあえず、これで結果待ち状態です。