起きたこと
表題のとおり。
Camera2 APIをたたこうとするとRuntimeExceptionが発生する機種がある。
原因
Camera APIの実装内でチェックして例外吐いてるっぽい。
バッテリー残量だけで判定されているようなので、充電中であってもお構いなし。
しかもこれAndroidの標準実装というわけではなく、メーカーによって実装が違うようで、エラーになるバッテリー残量がまちまち。
ええい、機種依存か。
ちょろっとインターネットを泳いでみた感じだと、
富士通のarrowsだったり
https://qiita.com/mfks17/items/ed23e7d783d5538beb19
Nokiaだったり
https://forum.xda-developers.com/showthread.php?t=1608186
Galaxyだったり
https://forums.androidcentral.com/samsung-galaxy-s3/190775-camera-app-disabled-low-battery.html
ふむむ。
対策
カメラ起動前に事前チェックしてあげた。
悩み(読み飛ばしてよい)
機種依存問題とはいえ、ほっとくとアプリごと落っこちちゃうので、何かしら対策しなくてはならない。
しかし困ったのが、これRuntimeExceptionなので、catchしてもバッテリーの問題かどうか区別がつかないこと。
一応ログを見るとエラーメッセージも設定されてるんだけど、
camera low battery
やら
low battery disabled
やら、やっぱりメーカーによって内容がまちまちなので、判断材料として使うのは微妙。
まぁそもそもエラーメッセージで判別すること自体アレなんだけど・・・
最終手段はcatchしてそのまま握りつぶしだけど、さすがにそれは気持ちが悪い。
というわけで、起きてからどうこうするのは厳しいので、事前にメッセージを出すのがユーザーには優しそう。
やり方
Camera APIをたたく前に、BatteryManagerさんに問い合わせましょう。
むしろアプリ起動時でもいいかもしれない。
公式のドキュメントはこちら。
バッテリー レベルと充電状態を監視する
詳細は上のドキュメントのとおり。
リンク踏むのが手間な人のために、こっちにも少しサンプル書きます。
開発環境の都合でXamarinで書くけど、ほかの言語でも基本は一緒。
protected override void OnCreate(Bundle savedInstanceState)
{
// 中略
float status = GetBatteryStatus();
// 閾値は要件に合わせて
// 下記は20%未満でエラーとしてる
if (status < 0.2)
{
// 「バッテリー不足です」みたいなポップアップ表示するなどしてアプリ終了
}
}
private float GetBatteryStatus()
{
// バッテリー情報を取得
IntentFilter ifilter = new IntentFilter(Intent.ActionBatteryChanged);
Intent batteryStatus = RegisterReceiver(null, ifilter);
// レベルとスケールを取得して割り算したのがバッテリー残量の割合
int level = batteryStatus.GetIntExtra(BatteryManager.ExtraLevel, -1);
int scale = batteryStatus.GetIntExtra(BatteryManager.ExtraScale, -1);
return (level / scale);
}
BatteryManagerさんがセットしてくれる情報は、上記インテントからいつでも取得できるので、そこまで小難しい実装は不要。
他にもバッテリーに関するいろんな情報が取れるので詳細は先述の公式ドキュメント参照。