Tech Racho エンジニアの「?」を「!」に。
  • 開発

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しないと実質的にはダメですね。


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。