*BroadcastReceiver`は、システム全体のブロードキャストイベントやインテントをリッスンする役割を持つアンドロイドコンポーネントです。

Androidでは、ほとんどのシステムイベントは Intent オブジェクトによってブロードキャストされます。これを行うために、これらのIntentオブジェクトは、Context.sendBroadcast()メソッドを使ってBroadcastReceiversに送られます。

このようなイベントがブロードキャストされると、BroadcastReceiverはイベントを受信し、ステータスバーに通知を作成するか、指定されたタスクを実行することで反応します。

BroadcastReceiver "は、"Activity "や "Service "と同様にアンドロイドのコンポーネントであるため、ほとんどの場合、アンドロイドのマニフェストファイルに登録する必要があります。

しかし、Activityとは異なり、BroadcastReceiverにはユーザーインターフェースがありません。

クラスとしてのBroadcastReceiverは抽象的で、通常はonReceive()と呼ばれるメソッドを持ち、タスクが受信されたときに発生させたいタスクを実行するためにオーバーライドします。

標準的なシステムイベントのほとんどは、アクション文字列として定義されており、IntentクラスのAPIドキュメントに記載されています。

例えば、ユーザーがデバイスに充電器を接続したり、切断したりしたときに、アプリが通知を受ける必要があるとすると、Intentクラスで定義された2つのブロードキャストアクションがそれを行います。

  1. 1.アクション_パワーディスコネクト
    1. action_power_connected です。

以下に例を示します。

public class PhoneChargerConnectedListener extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (Intent.ACTION_POWER_CONNECTED.equals(action)) {
            context.startService(
            new Intent(MyService.ACTION_POWER_CONNECTED));
        } else if (Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
        context.startService(
        new Intent(MyService.ACTION_POWER_DISCONNECTED));
        }
    }
}

このメソッドでは、Context.startService()を呼び出して、イベントを実際の作業を行うサービスに委譲するだけです。

BroadcastReceiver はどうやって登録するのですか?

ブロードキャストレシーバーを登録するには2つの方法があります。

1. AndroidManifest.xml経由

BroadcastReceivers**を実装するためのデフォルトの方法は、android manifestで宣言することです。
そのため、ユーザーがアプリケーションを起動していなくても、BroadcastReceiverserviceを通知することが可能になります。

これは、ユーザーの操作なしに特定のシステムイベントで起動する必要があるアプリケーションの場合に特に有効です。

<receiver android_name=".PhoneChargerConnectedListener">
    <intent-filter>
        <action android_name="android.intent.action.ACTION_POWER_CONNECTED"/>
        <action android_name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
    </intent-filter>
</receiver>

この方法は最も簡単な方法でもあります。

AndroidManifest.xmlを使用してBroadcastReceiverを登録することで、アプリケーションをアンインストールするまで、アプリケーションはブロードキャストを取得し続けます。これは、BroadcastReceiver`のライフサイクルのコントロールを少し犠牲にしていることを意味します。

そのためには、次のブロードキャストレシーバーの登録方法を確認します。

2. プログラムで登録する

BroadcastReceiversは、Activityやサービスの中でプログラム的に登録することもできます。

実際、ブロードキャストインテントの中には、プログラムでしか登録できないものもあります。その一方で、マニフェストで宣言しないと動作しないものもあります。

BroadcastReceiver**をプログラムで登録する場合、マッチングするコールバックで登録を解除することも忘れてはいけません。

以下はその例です。

public class MyActivity extends AppCompatActivity {
    private PhoneChargerConnectedListener myPhoneChargerConnectedListener;
    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
        intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
        myPhoneChargerConnectedListener = new PhoneChargerConnectedListener();
        registerReceiver(myPhoneChargerConnectedListener, intentFilter);
    }
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(myPhoneChargerConnectedListener);
    }
}

このケースでは、ContextクラスのregisterReceiver()メソッドを使って、プログラム的にBroadcastReceiverを登録しています。このメソッドを使用することで、必要に応じて登録登録解除を行うことで、BroadcastReceiverのライフサイクルを制御することができます。

AlarmManagerを使ったブロードキャストレシーバーの例

ここでは、アラームマネージャーを使ったシンプルなブロードキャストレシーバーの例を見てみましょう。

ここでは、1つの activity と1つのクラスを用意します。

(a). MainActivity.java

まず、アンドロイドスタジオで「アクティビティ」を作成します。

ここでは「MainActivity」クラスを作成します。このクラスは、サポートライブラリに存在するAppCompatActivityから派生します。

3つのメソッドを用意しました。

  1. onCreate()`です。
  2. initializeViews()`である。
  3. go()`です。

この activity のユーザインタフェースは、setContentView() メソッドを用いて content_main.xml からインフレーションされます。

使用するビューはEditTextsとButtonsです。
findViewById()`を使用して、レイアウト仕様からこれらを参照します。

go()`メソッドでアラームの初期化と起動を行います。

package com.tutorials.hp.alarmmanagerstarter;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    Button startBtn;
    EditText timeTxt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

         initializeViews();

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

    }

    /*
    INITIALIZE VIEWS
     */
    private void initializeViews()
    {
        timeTxt= (EditText) findViewById(R.id.timeTxt);
        startBtn= (Button) findViewById(R.id.startBtn);

        startBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               go();
            }
        });
    }

    /*
    INITIALIZE AND START OUR ALARM
     */
    private void go()
    {
        //GET TIME IN SECONDS AND INITIALIZE INTENT
        int time=Integer.parseInt(timeTxt.getText().toString());
        Intent i=new Intent(this,MyReceiver.class);

        //PASS CONTEXT,YOUR PRIVATE REQUEST CODE,INTENT OBJECT AND FLAG
        PendingIntent pi=PendingIntent.getBroadcast(this,0,i,0);

        //INITIALIZE ALARM MANAGER
        AlarmManager alarmManager= (AlarmManager) getSystemService(ALARM_SERVICE);

        //SET THE ALARM
        alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+(time*1000),pi);
        Toast.makeText(MainActivity.this, "Alarm set in "+time+" seconds", Toast.LENGTH_SHORT).show();
    }

}

(b). MyReciever.java

  • MyRecieverクラスです。
  • android.content.BroadcastReceiverクラスから派生しています。
  • メソッド: onReceive().
  • onReceive()`メソッドでは、アラーム音をシミュレートするために、トーストメッセージを表示しています。

package com.tutorials.hp.alarmmanagerstarter;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {
    /*
    RING ALARM WHEN IN WHEN WE RECEIVE OUR BROADCAST
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "Alarm Ringing...", Toast.LENGTH_SHORT).show();
    }
}

(c) activity_main.xml

  • メインの activity レイアウトファイルです。
  • MainActivityにインフレーションされるものとします。
  • ルートタグはrelativeLayoutです。
  • EditTextとボタンを含みます。

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    tools_context="com.tutorials.hp.alarmmanagerstarter.MainActivity"
    >

    <EditText
        android_id="@+id/timeTxt"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_alignParentLeft="true"
        android_layout_alignParentTop="true"
        android_layout_marginTop="28dp"
        android_ems="10"
        android_hint="Number of seconds"
        android_inputType="numberDecimal" />

    <Button
        android_id="@+id/startBtn"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_alignRight="@+id/timeTxt"
        android_layout_below="@+id/timeTxt"
        android_layout_marginRight="60dp"
        android_layout_marginTop="120dp"
        android_text="Start" />
</RelativeLayout>

(d). AndroidManifest.xml

BroadcastReceiver」クラスをアンドロイドマニフェストに登録する必要があります。

これが私のマニフェストの全文です。

<?xml version="1.0" encoding="utf-8"?>
<manifest
    package="com.tutorials.hp.alarmmanagerstarter">
    <application
        android_allowBackup="true"
        android_icon="@mipmap/ic_launcher"
        android_label="@string/app_name"
        android_supportsRtl="true"
        android_theme="@style/AppTheme">
        <activity
            android_name=".MainActivity"
            android_label="@string/app_name"
            android_theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android_name="android.intent.action.MAIN" />

                <category android_name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android_name="MyReceiver" >
        </receiver>
    </application>

</manifest>

Quick BroadcastReceiver Examples

1. BroadcastReceiver`を使ってネットワークの状態変化を聞く

まず、Javaクラスを作成し、android.content.BroadcastReceiverから派生させる必要があります。

インスタンスフィールドとして、ネットワークが接続されているかどうかを示す真偽値を保持するブーリアン型の isNetWorkConnected を用意します。

また,Contextオブジェクトも用意しています.

2つのコンストラクタを用意しました。1つはクラスに Context オブジェクトを注入します。
次に、BroadcastReceiverクラスのonReceive()メソッドをオーバーライドします。通常、このメソッドは2つのオブジェクトを受け取ります。1つは Context オブジェクトで、もう1つは Intent オブジェクトです。

ここでは,ContextクラスのgetSystemService() ,メソッドを用いてConnectivityManagerを初期化する。

ConnectivityManagerのインスタンスを使って、getActiveNetworkInfo()メソッドを呼び出し、android.net.NetworkInfo`オブジェクトに保持されているネットワーク情報を受け取ります。

最終的には、isNetWorkConnectedのブール値に`isConnected()の値を設定します。

次に、isNetWorkAvailable()メソッドがあり、基本的にネットワークが利用可能かどうかをチェックします。

これは単なるパブリックメソッドで、後ほど説明するように、このクラスのインスタンスが呼び出される必要があります。

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.widget.Toast;
import java.util.concurrent.CopyOnWriteArrayList;

public class NetWorkStateReceiver extends BroadcastReceiver {
    public boolean isNetWorkConnected;
    private Context mContext;

    public NetWorkStateReceiver() {
        super();
    }
    public NetWorkStateReceiver(Context context) {
        mContext = context;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager connectivityManager = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

        if (networkInfo != null && networkInfo.isConnected()) {
            isNetWorkConnected = true;
        } else {
            isNetWorkConnected = false;
            Toast.makeText(context, "No network Connection", Toast.LENGTH_SHORT).show();
        }

    }

    /**
     * Check if network is available
     * @return boolean value
     */
    public boolean isNetWorkAvailable() {
        ConnectivityManager connectivityManager = (ConnectivityManager)
                mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        if (networkInfo != null) {
            return networkInfo.isConnected();
        }
        return false;
    }
}

MainActivityでもどこでも、上記のクラスをインスタンス化することで始めることができます。

    publi class MainActivity extends AppCompatActivity{
        NetWorkStateReceiver receiver;
        @Override
        public void onCreate(Bundle savedInstanceState){
            .....
           receiver = new NetWorkStateReceiver(this);
           if(receiver.isNetWorkAvailable())
           {
               //do something network is available
           }
        }
    }

AndroidManifest.xmlでは、適切なパーミッションを追加して、BroadcastReceiver`を登録する必要があります。

<?xml version="1.0" encoding="utf-8"?>
<manifest
    >

    <uses-permission android_name="android.permission.INTERNET" />
    <uses-permission android_name="android.permission.ACCESS_NETWORK_STATE" />
    <application>
        ....
        <receiver
            android_name=".broadcasts.NetWorkStateReceiver"
            android_enabled="true"
            android_exported="true" />
        ....
    </application>

2. カスタムBroadcastReceiverの作成方法

ここでは、カスタムの抽象的なBroadcastRecieverクラスを紹介します。明らかに BroadcastReceiver から派生しています。このクラスの重要なメソッドである registerReceiver(), unregisterReceiver(), sendBroadcast() を再定義します。


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;

public abstract class LocalBroadcastCommunicator extends BroadcastReceiver {

    // The action name used to send and alsoe receive intents
    private static String sAction = null;

    private static <T> void registerReceiver(LocalBroadcastCommunicator receiver, Context context) {
        sAction = receiver.getClass().getName();
        LocalBroadcastManager.getInstance(context).registerReceiver(receiver, new IntentFilter(sAction));
    }

    private static <T> void unregisterReceiver(LocalBroadcastCommunicator receiver, Context context) {
        LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver);
    }

    public static void sendBroadcast(Context context, Intent intent) {
        if(sAction == null) {
            /* If sAction is null at this point, no receiver has been registered yet and there's no
             * point in sending a broadcast. */
            return;
        }

        intent.setAction(sAction);
        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
    }

    public void registerReceiver(Context context) {
        registerReceiver(this, context);
    }

    public void unregisterReceiver(Context context) {
        unregisterReceiver(this, context);
    }
}

完全な例

1. BroadcastReceiver`を使ってバッテリー残量が少ないことを通知する方法

BroadcasteReceiver クラスを使用して、シンプルな BatteryManager を作成します。バッテリー残量をテキストビューで表示し、進捗状況をプログレスバーで表示します。

以下は、私たちが使用しているAPIの一部です。

(a). BroadcastReceiver`(ブロードキャストレシーバー

これは、sendBroadcast()によって送られたインテントを受信するコードの基本クラスです。

(b). IntentFilter (インテントフィルタ)

IntentFilter は、マッチさせるべき Intent の値を構造的に記述したものです。IntentFilterは、Intent内のactionscategoriesdata(タイプ、スキーム、パスのいずれか)とマッチさせることができます。

**(c). バッテリーマネージャー

このクラスは ACTION_BATTERY_CHANGED Intent の値に使用される文字列と定数を含みます。

MainActivity.java (メインアクティビティ

これはメインの activity です。

package com.example.ankitkumar.broadcastreceiver_batterymanager;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    TextView batteryLevel;
    ProgressBar myProgressBar;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        batteryLevel = (TextView)findViewById(R.id.textView);
        myProgressBar = (ProgressBar)findViewById(R.id.progressBar);
        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(myBroadcastReceiver, intentFilter);

    }

    BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            context.unregisterReceiver(this);
            int currentLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
            int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
            int level = -1;
            if (currentLevel >= 0 && scale > 0) {
                level = (currentLevel * 100) / scale;
            }
            batteryLevel.setText("Battery Level remaining :"+  level +"%");
            myProgressBar.setProgress(level);
        }
    };
}

activity_main.xml これはメインの activity です。

これはメインの activity のレイアウトです。
ここでは、バッテリー残量を表示するTextViewと、バッテリー残量の割合を表示するプログレスバーを用意しています。

<?xml version="1.0" encoding="UTF-8"?>

<RelativeLayout
        tools_context="com.example.ankitkumar.broadcastreceiver_batterymanager.MainActivity" android_paddingTop="@dimen/activity_vertical_margin" android_paddingRight="@dimen/activity_horizontal_margin" android_paddingLeft="@dimen/activity_horizontal_margin" android_paddingBottom="@dimen/activity_vertical_margin" android_layout_height="match_parent" android_layout_width="match_parent" android_id="@+id/activity_main"  >

<TextView
        android_layout_height="wrap_content" android_layout_width="wrap_content" android_id="@+id/textView" android_layout_centerHorizontal="true" android_layout_centerVertical="true" android_textSize="20sp" android_text="Hello World!"/>

<ProgressBar
        android_layout_height="20dp" android_layout_width="match_parent" android_id="@+id/progressBar" android_layout_alignParentRight="true" android_layout_alignParentEnd="true" android_layout_below="@+id/textView" android_layout_marginTop="25dp" android_max="100" style="?android:attr/progressBarStyleHorizontal"/>

</RelativeLayout>

**ダウンロード

No. 場所 リンク
1. GitHub ダウンロード
2. GitHub Browse
2. GitHub Original Creator: @AnkitKumar111

2. BroadcastReceiver`を使って、受信したSMSを聞いて、それを表示する

  1. BroadcastReceiver を使用して、受信した SMS を受信し、それを読み込んで Toast メッセージに表示します。

MainActivity.java (メインアクティビティ)

これがメインの activity です。

package com.example.ankitkumar.msgreceive;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //checking wether the permission is already granted
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_SMS}, 1);

        }

    }

}

IcomingSMS.java これは、メインの activity です。

私たちの IncomingSMS.java ファイルです。使用しているAPIの一部を紹介します。

(a). SmsManager

これは android.telephony パッケージで定義されたクラスで、データ、テキスト、および pdu の SMS メッセージの送信など、SMS 操作の管理を行います。

(b). SmsMessage (SMSメッセージ)

ショートメッセージサービスのメッセージを表します。

package com.example.ankitkumar.msgreceive;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
import static android.telephony.SmsMessage.createFromPdu;

public class IncomingSms extends BroadcastReceiver {

    // Get the object of SmsManager
    final SmsManager sms = SmsManager.getDefault();

    @Override
    public void onReceive(Context context, Intent intent) {

        // Retrieves a map of extended data from the intent.
        final Bundle bundle = intent.getExtras();

        try {

            if (bundle != null) {

                final Object[] pdusObj = (Object[]) bundle.get("pdus");

                for (int i = 0; i < pdusObj.length; i++) {

                    SmsMessage currentMessage = createFromPdu((byte[]) pdusObj[i]);
                    String phoneNumber = currentMessage.getDisplayOriginatingAddress();

                    String senderNum = phoneNumber;
                    String message = currentMessage.getDisplayMessageBody();

                    Log.i("SmsReceiver", "senderNum: " + senderNum + "; message: " + message);

                    int duration = Toast.LENGTH_LONG;
                    final Toast toast = Toast.makeText(context, "senderNum: " + senderNum + ", message: " + message, duration);
                    toast.show();

                    //Countdown Timer for extending normal time of toast notification
                    new CountDownTimer(9000, 1000) {

                        public void onTick(long millisUntilFinished) {
                            toast.show();
                        }

                        public void onFinish() {
                            toast.show();
                        }

                    }.start();
                } // end for loop
            } // bundle is null

        } catch (Exception e) {
            Log.e("SmsReceiver", "Exception smsReceiver" + e);

        }
    }

}

activity_main.xml (日本語)

メインの activity のレイアウトです。

<?xml version="1.0" encoding="UTF-8"?>

<RelativeLayout
        tools_context="com.example.ankitkumar.msgreceive.MainActivity" android_background="#f2f2f2" android_layout_height="match_parent" android_layout_width="match_parent"  >

<ImageView
        android_background="@drawable/ic_sms" android_layout_height="200sp" android_layout_width="200sp" android_contentDescription="@string/app_name" android_layout_centerInParent="true" android_alpha="0.4"/>

</RelativeLayout>

**ダウンロード

No. 場所 リンク
1. GitHub ダウンロード
2. GitHub Browse
2. GitHub Original Creator: @AnkitKumar111

Android LocalBroadcastManager

Android LocalBroadcastManager with IntentService Tutorial and Example.

これは、アンドロイドの LocalBroadcastManager のチュートリアルと例です。LocalBroadcastManager "とは何か、そして "IntentService "とどのように併用するのかを見てみましょう。

ビデオチュートリアル

ビデオチュートリアルを好む人もいます。その場合は、このチュートリアルのビデオバージョンをご覧ください。

What You Learn in This Tutorial

このチュートリアルでは、以下のことを学びます。

  1. LocalBroadcastManager "とは何か、そしてその API 定義。
  2. LocalBroadcastManager "の利点。
  3. IntentServiceLocalBroadcastManager`を併用する方法。

LocalBroadcastManager とは何ですか?

LocalBroadcastManager` はヘルパークラスで、プロセス内のローカルオブジェクトにインテントのブロードキャストを登録・送信することができます。

これがそのAPI定義です。

public final class LocalBroadcastManager
extends Object

java.lang.Object
   ↳    android.support.v4.content.LocalBroadcastManager

LocalBroadcastManager の利点

SendBroadcast(Intent)メソッドでグローバルなブロードキャストを送信するのに比べて、LocalBroadcastManager`の利点は以下の通りです。

    1. このクラスはアプリケーションプロセス内の限られたオブジェクトのみを扱うので、アプリケーションデータはプライベートに保たれます。
    1. アプリケーションプロセス内でのみ動作するので、より安全です。
    1. システムを通してグローバルなブロードキャストを送信するよりも効率的です。

(a). BroadcastSenderIntentService

これは私たちの IntentService クラスです。ここでは、android.app.IntentServiceを継承し、onHandleIntent()メソッドをオーバーライドします。このメソッドの中では、threadクラスのsleep()メソッドを呼び出して、重いタスクをシミュレートします。

package info.camposha.localbroadcastandintentservice;

import android.app.IntentService;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;

public class BroadcastSenderIntentService extends IntentService {

    public BroadcastSenderIntentService() {
        super("BroadcastSenderIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        String message = getString(R.string.running);
        Intent broadcastIntent = new Intent();
        broadcastIntent.setAction(MainActivity.MESSAGE_SENT_ACTION);
        broadcastIntent.putExtra(MainActivity.MESSAGE_EXTRA, message);
        LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }

        message = getString(R.string.finished);
        broadcastIntent = new Intent();
        broadcastIntent.setAction(MainActivity.MESSAGE_SENT_ACTION);
        broadcastIntent.putExtra(MainActivity.MESSAGE_EXTRA, message);
        LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
    }

}

(b). MainActivity.java

これが私たちのメインの activity です。まず、いくつかの文字列定数を定義することから始めます。これらの定数は、識別子として機能するため、インテントを送受信する際に役立ちます。

package info.camposha.localbroadcastandintentservice;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    public static final String MESSAGE_SENT_ACTION = "info.camposha.MESSAGE_RECEIVED_ACTION";
    public static final String MESSAGE_EXTRA = "info.camposha.MESSAGE_EXTRA";

    private static final String MESSAGE_FROM_SERVICE_KEY = "info.camposha.MESSAGE_FROM_SERVICE_KEY";

    private BroadcastReceiver receiver;
    private TextView serviceMessageView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        serviceMessageView = findViewById(R.id.service_message_textview);

        if (savedInstanceState != null) {
            serviceMessageView.setText(savedInstanceState.getString(MESSAGE_FROM_SERVICE_KEY));
        }else{
            serviceMessageView.setText("Null");
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        receiver = new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {
                Bundle bundle = intent.getExtras();
                String message = bundle.getString(MESSAGE_EXTRA);

                serviceMessageView.setText(message);
            }
        };

        LocalBroadcastManager.getInstance(this).registerReceiver(receiver, new IntentFilter(MESSAGE_SENT_ACTION));
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (receiver != null) {
            LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
            receiver = null;
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(MESSAGE_FROM_SERVICE_KEY, serviceMessageView.getText().toString());
    }

    public void onStartServiceClicked(View view) {
        startService(new Intent(this, BroadcastSenderIntentService.class));
    }

}

activity_main.xml

これがメインの activity のレイアウトです。ここには、テキストビューとボタンがあります。

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout

        android_layout_width="match_parent"
        android_layout_height="match_parent"
        tools_context=".MainActivity">

        <TextView
            android_id="@+id/headerLabel"
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_layout_alignParentTop="true"
            android_layout_centerHorizontal="true"
            android_fontFamily="casual"
            android_text="LocalBroadcastReceiver"
            android_textAllCaps="true"
            android_textSize="24sp"
            android_textStyle="bold" />

        <LinearLayout
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_layout_centerHorizontal="true"
            android_layout_centerVertical="true"
            android_gravity="center"
            android_orientation="vertical" >

            <TextView
                android_id="@+id/textView1"
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_text="@string/service_status"
                android_textSize="16dp" />

            <TextView
                android_id="@+id/service_message_textview"
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_text="@string/not_running"
                android_textSize="16dp" />
        </LinearLayout>

        <Button
            android_id="@+id/button1"
            android_onClick="onStartServiceClicked"
            android_text="@string/start_service"
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_layout_alignParentBottom="true"
            android_layout_centerHorizontal="true"
            android_layout_marginBottom="12dp"
            android_fontFamily="serif-monospace" />

</RelativeLayout>

AndroidManifest.xml

アンドロイドマニフェストでは、serviceの登録を確認しなければなりません。これが私のマニフェストです。

<?xml version="1.0" encoding="utf-8"?>
<manifest
    package="info.camposha.localbroadcastandintentservice">

    <application
        android_allowBackup="true"
        android_icon="@mipmap/ic_launcher"
        android_label="@string/app_name"
        android_roundIcon="@mipmap/ic_launcher_round"
        android_supportsRtl="true"
        android_theme="@style/AppTheme">
        <activity android_name=".MainActivity">
            <intent-filter>
                <action android_name="android.intent.action.MAIN" />

                <category android_name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android_name=".BroadcastSenderIntentService" />
    </application>

</manifest>

Kotlin LocalBroadcastManager の例

kotlinによるAndroidXのlocalbroadcastmanagerの例で、IntentServiceBroadcastReceiverを使っています。

ビデオチュートリアルはこちら。

Step 1: 依存関係の追加

gradleファイルにAndroiX localbroadcastmanagerを依存関係として追加します。

    implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'

ステップ2:レイアウトの設計

テキストビューとボタンのあるレイアウトをデザインします。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/dateText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Initial value"
        android:textSize="20dp"
        android:textStyle="bold"/>

    <Button
        android:id="@+id/startButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="Start Service"/>

</LinearLayout>

ステップ 3: IntentService の作成

インテントサービスのクラスを作成し、onHandleIntentメソッドをオーバーライドします。

package info.camposha.ms_localbroadcastmanager

import android.app.IntentService
import android.content.Intent
import android.util.Log
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import java.util.*

//IntentService is a ntentService is a base class for Services that handle asynchronous
// requests (expressed as Intents) on demand.
class MyIntentService : IntentService("MyIntentService") {
    override fun onHandleIntent(arg0: Intent?) {
        val intent = Intent(CUSTOM_ACTION)
        //get date to send
        intent.putExtra("DATE", Date().toString())
        Log.d(MyIntentService::class.java.simpleName, "sending broadcast")

        // send local broadcast
        //LocalBroadcastManager is a Helper to register for and send broadcasts of Intents
        // to local objects within your process.
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
    }

    companion object {
        const val CUSTOM_ACTION = "YOUR_CUSTOM_ACTION"
    }
}

Step 4: MainActivityの作成

ランチャーである activity を作成します。

package info.camposha.ms_localbroadcastmanager

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import kotlinx.android.synthetic.main.activity_main.*

//Our main activity
class MainActivity : AppCompatActivity(), View.OnClickListener {
    //override onCreate
    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        startButton.setOnClickListener(this)
    }

    //when activity is paused
    override fun onPause() {
        super.onPause()
        // unregister local broadcast
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver)
    }

    //when activity is resumed
    override fun onResume() {
        super.onResume()

        // register local broadcast
        val filter = IntentFilter(MyIntentService.CUSTOM_ACTION)
        LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filter)
    }

    /**
    Create a BroadcastReceiver

     * BroadcastReceiver is a Base class for code that will receive intents sent by sendBroadcast().
     * Broadcast receiver to receive the data
     */
    private val mReceiver: BroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val date = intent.getStringExtra("DATE")
            dateText.text = date
        }
    }

    //when user clicks the start button, start our intent service
    override fun onClick(view: View) {
        if (view.id == R.id.startButton) {
            // start intent service
            val intent = Intent(this, MyIntentService::class.java)
            startService(intent)
        }
    }
}

ステップ5:コンポーネントの登録

android manifextファイルに2つのコンポーネントを登録します。

  1. MainActivity
  2. IntentService` (インテントサービス)

 <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".MyIntentService"/>

ステップ6: 実行

プロジェクトを実行すると、以下のようになります。

Android <code>LocalBroadcastManager</code> Example

コードのダウンロード

コードのダウンロードはこちら(https://github.com/Oclemy/MsLocalBroadcastManager/archive/refs/heads/master.zip)から