Broadcast使用分析

本文深入探讨了Android系统中的广播机制,包括如何接收系统及自定义广播,以及不同注册方式(代码与XML)的优缺点。重点介绍了如何在发送广播时利用正常广播与粘性广播的区别,确保关键业务逻辑在应用启动前能够接收到广播通知。通过实例代码展示了如何在Activity和Service中注册并处理广播,以及如何在特定场景下有效利用粘性广播的特点。此外,文章还对比了代码注册与XML注册广播的方法,提供了在实际应用中选择注册方式的指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Broadcast(广播)是Android系统四大组件之一,Broadcast的主要作用是接收系统或者自定义的广播,并进行相关的处理工作。在广播中的操作时间不能太长,超过5s将被系统回收,造成ANR;如果需要在onReceive方法中做复杂的业务处理,最好的方法是开启一个线程来处理。

用法一:接收系统广播并进行相应的处理

接收广播的方式有两种:一是通过代码注册接收广播;二是通过xml配置的方式接收广播。

两种注册广播功能的区别:

代码注册的方式必须是该应用的进程已经启动,并且注册该广播的Activity或者Service等已经被实例化,才能接收该注册的广播;

xml配置注册广播则不需要以上的各种限制,只要系统发送了广播,就能接收到注册的广播。

在实际应用中,如果想要监听系统发出的广播,在接收到广播后做出相应的逻辑操作。如果选择代码方式注册广播,就会导致一系列问题,因为可能在系统发出广播的时候,该应用的进程并没有启动,导致应用接收不到广播,逻辑操作不能执行的问题。因此建议选择xml的方式注册广播。同时,如果大量使用XML注册广播,会降低系统性能,所以在选择广播注册方式时,应该根据具体业务需求,选择最适合的注册方式。

一、代码方式注册广播

(1)设置广播过滤器——需要接收的广播

  1. //系统发出Intent.ACTION_MEDIA_MOUNTED的时候注册了scheme 
  2. //因此在注册监听广播的时候IntentFilter必须添加相应的Scheme才能接收相应的广播  
  3. // 接收SDCard mount(安装)广播 
  4. IntentFilter mMountFilter= new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); 
  5. //需要添加Scheme 
  6. mMountFilter.addDataScheme("file"); 
//系统发出Intent.ACTION_MEDIA_MOUNTED的时候注册了scheme
//因此在注册监听广播的时候IntentFilter必须添加相应的Scheme才能接收相应的广播 
// 接收SDCard mount(安装)广播
IntentFilter mMountFilter= new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
//需要添加Scheme
mMountFilter.addDataScheme("file");

(2)声明广播接收器——注册广播信息

  1. // 注册广播监听 
  2. registerReceiver(mReceiver, mMountFilter); 
// 注册广播监听
registerReceiver(mReceiver, mMountFilter);

监听SDcard安装(Mounted)广播的具体代码如下(MainActivity.java):

  1. package com.jony.broadcast; 
  2.  
  3. import android.os.Bundle; 
  4. import android.app.Activity; 
  5. import android.content.BroadcastReceiver; 
  6. import android.content.Context; 
  7. import android.content.Intent; 
  8. import android.content.IntentFilter; 
  9. import android.view.Menu; 
  10. import android.widget.Toast; 
  11.  
  12. public class MainActivity extends Activity { 
  13.     private IntentFilter mMountFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); 
  14.      
  15.     private BroadcastReceiver mReceiver = new BroadcastReceiver() { 
  16.         @Override 
  17.         public void onReceive(Context context, Intent intent) { 
  18.             // do your logic 
  19.             System.out.println("SDcard is mounted"); 
  20.             Toast.makeText(MainActivity.this, "SDcard have mounted", Toast.LENGTH_LONG).show(); 
  21.         } 
  22.     }; 
  23.  
  24.     protected void onStart() { 
  25.         super.onStart(); 
  26.         //系统发出Intent.ACTION_MEDIA_MOUNTED的时候注册了scheme 
  27.         //因此在注册监听广播的时候IntentFilter必须添加相应的Scheme才能接收相应的广播  
  28.         mMountFilter.addDataScheme("file"); 
  29.         registerReceiver(mReceiver, mMountFilter);//注册广播监听 
  30.     }; 
  31.     @Override 
  32.     public void onCreate(Bundle savedInstanceState) { 
  33.         super.onCreate(savedInstanceState); 
  34.         setContentView(R.layout.activity_main); 
  35.     } 
  36.  
  37.     @Override 
  38.     protected void onResume() { 
  39.         super.onResume(); 
  40.     } 
  41.     @Override 
  42.     public boolean onCreateOptionsMenu(Menu menu) { 
  43.         getMenuInflater().inflate(R.menu.activity_main, menu); 
  44.         return true
  45.     } 
  46.  
  47.     @Override 
  48.     protected void onStop() { 
  49.         super.onStop(); 
  50.         unregisterReceiver(mReceiver);// 取消广播监听 
  51.     } 
package com.jony.broadcast;

import android.os.Bundle;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.Menu;
import android.widget.Toast;

public class MainActivity extends Activity {
    private IntentFilter mMountFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
    
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // do your logic
            System.out.println("SDcard is mounted");
            Toast.makeText(MainActivity.this, "SDcard have mounted", Toast.LENGTH_LONG).show();
        }
    };

    protected void onStart() {
        super.onStart();
        //系统发出Intent.ACTION_MEDIA_MOUNTED的时候注册了scheme
        //因此在注册监听广播的时候IntentFilter必须添加相应的Scheme才能接收相应的广播 
        mMountFilter.addDataScheme("file");
        registerReceiver(mReceiver, mMountFilter);//注册广播监听
    };
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onResume() {
        super.onResume();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    @Override
    protected void onStop() {
        super.onStop();
        unregisterReceiver(mReceiver);// 取消广播监听
    }
}

Manifest.xml文件比较简单,在此不再给出源码

二、XML方式注册广播

继承BroadcastReceiver类,实现onReceive方法——该方法中实现相应的业务逻辑即可

MyBroadcasrReceiver代码如下(MyBroadcasrReceiver.java)

  1. package com.jony.broadcast.broadcast_sticky_test; 
  2.  
  3. import android.content.BroadcastReceiver; 
  4. import android.content.Context; 
  5. import android.content.Intent; 
  6. import android.widget.Toast; 
  7.  
  8. public class MyBroadcasrReceiver extends BroadcastReceiver{ 
  9.  
  10.     @Override 
  11.     public void onReceive(Context context, Intent intent) { 
  12.         // do your logic 
  13.         System.out.println("BroadcasrReceiver is starting"); 
  14.         Toast.makeText(context, "BroadcasrReceiver is starting", Toast.LENGTH_LONG).show(); 
  15.     } 
  16.  
package com.jony.broadcast.broadcast_sticky_test;

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

public class MyBroadcasrReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        // do your logic
        System.out.println("BroadcasrReceiver is starting");
        Toast.makeText(context, "BroadcasrReceiver is starting", Toast.LENGTH_LONG).show();
    }

}

在XML中配置自定义BroadcastReceiver的action以及相应的data,在Mainfest中进行如下定义:

  1. <receiver android:name=".MyBroadcasrReceiver" android:label="@string/receiver"
  2.             <intent-filter> 
  3.                 <action android:name="com.jony.normalbroadcast"/> 
  4.                 <data android:scheme="file"/> 
  5.             </intent-filter> 
  6.             <intent-filter> 
  7.                 <action android:name="com.jony.stickybroadcast"/> 
  8.             </intent-filter> 
  9. </receiver> 
<receiver android:name=".MyBroadcasrReceiver" android:label="@string/receiver">
            <intent-filter>
                <action android:name="com.jony.normalbroadcast"/>
                <data android:scheme="file"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.jony.stickybroadcast"/>
            </intent-filter>
</receiver>

小节:以上两种接收广播的方式各有优点,具体选择哪种方式监听广播,需要更具业务需求,做出相应的选择。

用法二:接收自定义广播

首先通过继承BroadcastReceiver类,实现onReceive方法——该方法中实现相应的业务逻辑即可

MyBroadcasrReceiver代码如下(MyBroadcasrReceiver.java)

  1. package com.jony.broadcast.broadcast_sticky_test; 
  2.  
  3. import android.content.BroadcastReceiver; 
  4. import android.content.Context; 
  5. import android.content.Intent; 
  6. import android.widget.Toast; 
  7.  
  8.  
  9. public class MyBroadcasrReceiver extends BroadcastReceiver{ 
  10.  
  11.     @Override 
  12.     public void onReceive(Context context, Intent intent) { 
  13.         // do your logic 
  14.         System.out.println("BroadcasrReceiver is starting"); 
  15.         Toast.makeText(context, "BroadcasrReceiver is starting", Toast.LENGTH_LONG).show(); 
  16.     } 
  17.  
package com.jony.broadcast.broadcast_sticky_test;

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


public class MyBroadcasrReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        // do your logic
        System.out.println("BroadcasrReceiver is starting");
        Toast.makeText(context, "BroadcasrReceiver is starting", Toast.LENGTH_LONG).show();
    }

}

在XML中配置自定义BroadcastReceiver的action以及相应的data,在Mainfest中进行如下定义:

  1. <receiver android:name=".MyBroadcasrReceiver" android:label="@string/receiver"
  2.             <intent-filter> 
  3.                 <action android:name="com.jony.normalbroadcast"/> 
  4.                 <data android:scheme="file"/> 
  5.             </intent-filter> 
  6.             <intent-filter> 
  7.                 <action android:name="com.jony.stickybroadcast"/> 
  8.             </intent-filter> 
  9. </receiver> 
<receiver android:name=".MyBroadcasrReceiver" android:label="@string/receiver">
            <intent-filter>
                <action android:name="com.jony.normalbroadcast"/>
                <data android:scheme="file"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.jony.stickybroadcast"/>
            </intent-filter>
</receiver>

实现BroadcasrReceiver的子类并在Mainfest中进行了以上配置之后,接下来就是见证奇迹的时候了,看看我们怎样启动我们自定义的Broadcast吧……

启动广播的步骤大致可以分为两步:

第一步注册我们自定义的广播;

第二部发送相应的Action——即我们在Mainfest中配置<receiver>时设置的相应action

代码如下所示(MainActivity.java):

  1. package com.jony.broadcast.broadcast_sticky_test; 
  2.  
  3. import android.os.Bundle; 
  4. import android.app.Activity; 
  5. import android.content.Intent; 
  6. import android.content.IntentFilter; 
  7. import android.view.Menu; 
  8.  
  9. public class MainActivity extends Activity { 
  10.     private IntentFilter mFilter; 
  11.     private MyBroadcasrReceiver mReceiver = new MyBroadcasrReceiver(); 
  12.  
  13.     @Override 
  14.     public void onCreate(Bundle savedInstanceState) { 
  15.         super.onCreate(savedInstanceState); 
  16.         setContentView(R.layout.activity_main); 
  17.         mFilter = new IntentFilter(); 
  18.         mFilter.addAction("com.jony.normalbroadcast"); 
  19.         // 注册广播 
  20.          registerReceiver(mReceiver, mFilter);// 在XML中进行广播注册 
  21.         Intent intent = new Intent("com.jony.stickybroadcast"); 
  22.         sendBroadcast(intent);// 发送广播 
  23.     } 
  24.  
  25.     @Override 
  26.     public boolean onCreateOptionsMenu(Menu menu) { 
  27.         getMenuInflater().inflate(R.menu.activity_main, menu); 
  28.         return true
  29.     } 
  30.  
  31.     @Override 
  32.     protected void onPause() { 
  33.         super.onPause(); 
  34.         unregisterReceiver(mReceiver); 
  35.     } 
package com.jony.broadcast.broadcast_sticky_test;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.Menu;

public class MainActivity extends Activity {
    private IntentFilter mFilter;
    private MyBroadcasrReceiver mReceiver = new MyBroadcasrReceiver();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mFilter = new IntentFilter();
        mFilter.addAction("com.jony.normalbroadcast");
        // 注册广播
         registerReceiver(mReceiver, mFilter);// 在XML中进行广播注册
        Intent intent = new Intent("com.jony.stickybroadcast");
        sendBroadcast(intent);// 发送广播
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mReceiver);
    }
}
用法三:Normal Broadcast和Sticky Broadcast的区别用法

StickyBroadcast一般很少用到,但是千万不要忘记小人物也有大用处,所以请尊重身边的每一个人。闲话少说,直接切入正题,在使用代码注册广播(广播被嵌入到Activity中或者是Service中)时,当发送一个广播时,被嵌入的Activity或者Service还没有被启动时,发送的normal广播是接收不到的,这时只有发送sticky广播,在应用程序启动被嵌入广播的Activity或者Service时,会接收到stick广播,因此在这样的业务中stick广播就派上了用处。

举例说明:

在使用sticky广播时,需要在AndroidManifest.xml中赋予发送sticky广播的权限

  1. <uses-permission android:name="android.permission.BROADCAST_STICKY"/> 
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>

首先在被嵌入的Activity中注册广播,具体代码如下(SecondActivity.java):

  1. package com.jony.broadcast.broadcast_sticky_test; 
  2.  
  3. import android.app.Activity; 
  4. import android.content.BroadcastReceiver; 
  5. import android.content.Context; 
  6. import android.content.Intent; 
  7. import android.content.IntentFilter; 
  8. import android.os.Bundle; 
  9. import android.widget.Toast; 
  10.  
  11. public class SecondActivity extends Activity{ 
  12.     private IntentFilter filter; 
  13.     private BroadcastReceiver mReceiver = new BroadcastReceiver() { 
  14.         @Override 
  15.         public void onReceive(Context context, Intent intent) { 
  16.             Toast.makeText(context, intent.getAction(), Toast.LENGTH_LONG).show(); 
  17.         } 
  18.     }; 
  19.     protected void onResume() { 
  20.         super.onResume(); 
  21.     }; 
  22.     @Override 
  23.     protected void onCreate(Bundle savedInstanceState) { 
  24.         super.onCreate(savedInstanceState); 
  25.         setContentView(R.layout.second); 
  26.         filter = new IntentFilter(); 
  27.         filter.addAction("com.jony.normalbroadcast"); 
  28.         filter.addAction("com.jony.stickybroadcast"); 
  29.         registerReceiver(mReceiver, filter); 
  30.     } 
  31.     @Override 
  32.     protected void onPause() { 
  33.         super.onPause(); 
  34.         unregisterReceiver(mReceiver); 
  35.     } 
package com.jony.broadcast.broadcast_sticky_test;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.widget.Toast;

public class SecondActivity extends Activity{
    private IntentFilter filter;
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, intent.getAction(), Toast.LENGTH_LONG).show();
        }
    };
    protected void onResume() {
        super.onResume();
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second);
        filter = new IntentFilter();
        filter.addAction("com.jony.normalbroadcast");
        filter.addAction("com.jony.stickybroadcast");
        registerReceiver(mReceiver, filter);
    }
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mReceiver);
    }
}

在MainActivity中发送广播,代码如下所示(MainActivity.java):

  1. package com.jony.broadcast.broadcast_sticky_test; 
  2.  
  3. import android.os.Bundle; 
  4. import android.app.Activity; 
  5. import android.content.Intent; 
  6. import android.view.Menu; 
  7. import android.view.View; 
  8. import android.widget.Button; 
  9.  
  10. public class MainActivity extends Activity { 
  11.     private Button normal_button,sticky_button,launch_button; 
  12.     @Override 
  13.     public void onCreate(Bundle savedInstanceState) { 
  14.         super.onCreate(savedInstanceState); 
  15.         setContentView(R.layout.activity_main); 
  16.         init_data(); 
  17.         } 
  18.  
  19.     private void init_data() { 
  20.         normal_button = (Button) findViewById(R.id.send_normal_broadcast); 
  21.         sticky_button = (Button) findViewById(R.id.send_sticky_broadcast); 
  22.         launch_button = (Button) findViewById(R.id.receive_broadcast); 
  23.  
  24.         normal_button.setOnClickListener(new Button.OnClickListener() { 
  25.             @Override 
  26.             public void onClick(View v) { 
  27.                 Intent intent = new Intent("com.jony.normalbroadcast"); 
  28.                 sendBroadcast(intent); 
  29.             } 
  30.         }); 
  31.         sticky_button.setOnClickListener(new Button.OnClickListener() { 
  32.             @Override 
  33.             public void onClick(View v) { 
  34.                 Intent intent = new Intent(); 
  35.                 intent.setAction("com.jony.stickybroadcast"); 
  36.                 sendStickyBroadcast(intent); 
  37.             } 
  38.         }); 
  39.         launch_button.setOnClickListener(new Button.OnClickListener() { 
  40.             @Override 
  41.             public void onClick(View v) { 
  42.                 Intent intent = new Intent(getApplicationContext(), SecondActivity.class); 
  43.                 startActivity(intent); 
  44.             } 
  45.         }); 
  46.     } 
  47.  
  48.     @Override 
  49.     public boolean onCreateOptionsMenu(Menu menu) { 
  50.         getMenuInflater().inflate(R.menu.activity_main, menu); 
  51.         return true
  52.     } 
  53.  
  54.     @Override 
  55.     protected void onPause() { 
  56.         super.onPause(); 
  57.     } 
package com.jony.broadcast.broadcast_sticky_test;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {
    private Button normal_button,sticky_button,launch_button;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init_data();
        }

    private void init_data() {
        normal_button = (Button) findViewById(R.id.send_normal_broadcast);
        sticky_button = (Button) findViewById(R.id.send_sticky_broadcast);
        launch_button = (Button) findViewById(R.id.receive_broadcast);

        normal_button.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.jony.normalbroadcast");
                sendBroadcast(intent);
            }
        });
        sticky_button.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setAction("com.jony.stickybroadcast");
                sendStickyBroadcast(intent);
            }
        });
        launch_button.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
                startActivity(intent);
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

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

布局文件和Manifest配置文件都比较简单,在此不再给出。
最后,见证奇迹的时刻就交给大家了……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值