Tuesday, December 22, 2015

android - How to send and receive local broadcast

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp"
    tools:context=".MainActivity"
    android:background="#fdb571"
    >
    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20dp"
        android:fontFamily="sans-serif-condensed"
        />
    <Button
        android:id="@+id/btn_send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send Local Broadcast"
        android:layout_below="@id/tv"
        />
</RelativeLayout>
MainActivity.java

package com.cfsuman.me.androidcodesnippets;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Random;


public class MainActivity extends AppCompatActivity {
    private Context mContext;
    private Random mRandom = new Random();

    RelativeLayout mRelativeLayout;
    private Button mButtonSend;
    private TextView mTextView;

    /*
        BroadcastReceiver
            Base class for code that will receive intents sent by sendBroadcast().

            If we don't need to send broadcasts across applications, we can consider using this class with
            LocalBroadcastManager instead of the more general facilities described below. This will
            give us a much more efficient implementation (no cross-process communication needed)
            and allow us to avoid thinking about any security issues related to other applications
            being able to receive or send our broadcasts.
    */

    // Initialize a new BroadcastReceiver instance
    private BroadcastReceiver mRandomNumberReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Get the received random number
            int receivedNumber = intent.getIntExtra("RandomNumber",-1);

            // Display a notification that the broadcast received
            Toast.makeText(context,"Received : " + receivedNumber,Toast.LENGTH_SHORT).show();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Request window feature action bar
        requestWindowFeature(Window.FEATURE_ACTION_BAR);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Get the application context
        mContext = getApplicationContext();

        /*
            LocalBroadcastManager
                Helper to register for and send broadcasts of Intents to local objects within your
                process. This is has a number of advantages over sending global broadcasts
                with sendBroadcast(Intent):

                    We know that the data we are broadcasting won't leave our app, so don't need
                        to worry about leaking private data.

                    It is not possible for other applications to send these broadcasts to our app,
                        so we don't need to worry about having security holes they can exploit.

                    It is more efficient than sending a global broadcast through the system.
        */

        /*
            public void registerReceiver (BroadcastReceiver receiver, IntentFilter filter)
                Register a receiver for any local broadcasts that match the given IntentFilter.

            Parameters
                receiver : The BroadcastReceiver to handle the broadcast.
                filter : Selects the Intent broadcasts to be received.

        */
        // Register the local broadcast
        LocalBroadcastManager.getInstance(mContext).registerReceiver(
                mRandomNumberReceiver,
                new IntentFilter("BROADCAST_RANDOM_NUMBER")
        );

        // Change the action bar color
        getSupportActionBar().setBackgroundDrawable(
                new ColorDrawable(Color.parseColor("#FFFF00BF"))
        );

        // Get the widgets reference from XML layout
        mRelativeLayout = (RelativeLayout) findViewById(R.id.rl);
        mButtonSend = (Button) findViewById(R.id.btn_send);
        mTextView = (TextView) findViewById(R.id.tv);

        // Set a click listener for send button
        mButtonSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Generate a random number
                int randomNumber = mRandom.nextInt(500);

                // Initialize a new intent instance
                Intent intent = new Intent("BROADCAST_RANDOM_NUMBER");
                // Put the random number to intent to broadcast it
                intent.putExtra("RandomNumber",randomNumber);

                /*
                    public boolean sendBroadcast (Intent intent)
                        Broadcast the given intent to all interested BroadcastReceivers. This call
                        is asynchronous; it returns immediately, and you will continue executing
                        while the receivers are run.

                    Parameters
                        intent : The Intent to broadcast; all receivers matching this Intent
                            will receive the broadcast.
                */

                // Send the broadcast
                LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);

                // Update the TextView with random number
                mTextView.setText("Random number generated : "
                        + randomNumber
                        + "\nApp also broadcast it."
                );
            }
        });
    }
}