ACTION_SCREEN_ONを受け取る

ホームスクリーンウィジェット(AppWidget)開発では、省エネ対策が重要になります。

画面がOFFの時は、無駄な処理を省きたいものです。

リファレンスによると
・ACTION_SCREEN_ON : “android.intent.action.SCREEN_ON”
・ACTION_SCREEN_OFF : “android.intent.action.SCREEN_OFF”
というのが定義されているので、これを受信すれば対策できそうです。

http://developer.android.com/reference/android/content/Intent.html

しかし、単にmanifest.xmlのreceiverに書いても、受信してくれません。

ダメな例:

<application android:icon="@drawable/icon" android:label="@string/app_name">
  <receiver android:name="jp.bpsinc.android.test.WidgetProvider">
    <intent-filter>
      <action android:name="android.intent.action.SCREEN_ON" />
      <action android:name="android.intent.action.SCREEN_OFF" />
    </intent-filter>
    <meta-data android:name="android.appwidget.provider" android:resource="@xml/provider" />
  </receiver>
</application></pre>
SCREEN_ONなどを受け取るには、アプリの初期化処理で、コードから登録する必要があります。
<pre class="brush:java">@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
  IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
  context.getApplicationContext().registerReceiver(new BroadcastReceiver() {
    @Override
      public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "RECEIVE");
    }
  }, filter);
}

この際、
・渡されたcontextではなくApplicationContextを使うこと
・AppWidgetProviderもonReceive持っているからいけそうな気がするが、receiverにthisを指定してはいけない
がポイントです。
守らないと、以下のようなエラーが発生します。

android.content.ReceiverCallNotAllowedException: IntentReceiver components are not allowed to register to receive intents

Providerにまとめて処理させたいなら、以下のようにやればOKです。

public class WidgetProvider extends AppWidgetProvider {
  @Override
  public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    context.getApplicationContext().registerReceiver(new BroadcastReceiver() {
      @Override
        public void onReceive(Context context, Intent intent) {
          WidgetProvider.this.onReceive(context, intent);
      }
    }, filter);
  }

  @Override
  public void onReceive(Context context, Intent intent) {
    //なんたらかんたら
  }
}

ただ、単にこの方法を使うと、Receiverが無限に増えていってしまいます。
アプリを終了してもReceiverが残ってしまうので、サービスにbindしないと実質的にはダメですね。

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

baba

ゆとりプログラマー。 高校時代から趣味でプログラミングを初め、そのままコードを書き続けて現在に至る。慶應義塾大学環境情報学部(SFC)卒業。BPS設立初期に在学中から参加している最古参メンバーの一人。Ruby on Rails、PHP、Androidアプリ、Windows/Macアプリ、超縦書の開発などを気まぐれにやる。軽度の資格マニアで、情報処理技術者試験(16区分17回 + 情報処理安全確保支援士試験)、技術士(情報工学部門)、Ruby Programmer Gold、AWSソリューションアーキテクト(アソシエイト)、日商簿記2級、漢検準1級などを保有。

babaの書いた記事

夏のTechRachoフェア2019

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ