【第一行代码】Android的广播机制

Android的广播机制

一、广播的类型

         标准广播:完全异步执行的广播,发出后所有广播接收器都同一时刻接收到这条广播信息,没有先后顺序,效率较高,但也无法截断。

        有序广播:同步执行的广播,发出后同一时刻只有一个广播接收器能够收到这条广播消息,当这个接收器的逻辑执行完毕后才会继续传递,所以接收器是有先后顺序的,优先级高的可以先收到并且可以截断广播。

 

二、广播接收器

        广播接收器可以自由地对自己感兴趣的广播进行注册,这样当有相应的广播发出时,广播接收器就能够收到该广播,并在内部处理相应的逻辑。注册广播的方式一般有两种,在代码中注册和在AndroidManifest.xml中注册,其中前者也被称为动态注册,后者也被称为静态注册。新建一个类,让它继承自BroadcastReceiver,并重写父类的onReceive()方法就行了。这样当有广播到来时,onReceive()方法就会得到执行,具体的逻辑就可以在这个方法中处理。 

 

三、接收系统广播

        可以通过监听Android内置的系统级别的广播来得到各种系统状态信息。

        1.动态注册监听网络变化

       

@Override 

        protected void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState); 

        setContentView(R.layout.activity_main); 

intentFilter = new IntentFilter(); 

//当网络状态发生变化时,系统发出的正是一条值为android.net.conn.CONNECTIVITY_ CHANGE的广播,也就是说我们的广播接收器想要监听什么广播,就在这里添加相应的action就行了

intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); 

networkChangeReceiver = new NetworkChangeReceiver();

//动态注册广播接收器 

registerReceiver(networkChangeReceiver, intentFilter); 

} 

 

class NetworkChangeReceiver extends BroadcastReceiver { 

@Override 

public void onReceive(Context context, Intent intent) { 

//ConnectivityManager是个系统服务类,专门用于管理网络连接的

ConnectivityManager connectionManager = (ConnectivityManager) 

getSystemService(Context.CONNECTIVITY_SERVICE); 

//查询系统的网络状态需要声明权限<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 

NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo(); 

 

if (networkInfo != null && networkInfo.isAvailable()) { 

Toast.makeText(context, "network is available", 

Toast.LENGTH_SHORT).show(); 

} else { 

Toast.makeText(context, "network is unavailable", 

Toast.LENGTH_SHORT).show(); 

} 

} 

} 

@Override 

protected void onDestroy() { 

super.onDestroy(); 

//动态注册的广播接收器一定都要取消注册

unregisterReceiver(networkChangeReceiver); 

} 


        2.静态注册实现开机启动

        使用静态注册让程序在未启动的情况下就能接收到广播

public class BootCompleteReceiver extends BroadcastReceiver { 

@Override 

public void onReceive(Context context, Intent intent) { 

Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show(); 

} 

} 


监听系统开机广播也是需要声明权限的

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

<!-- 由于Android系统启动完成后会发出一条值为android.intent.action.BOOT_COMPLETED的广播,因此我们在这里添加了相应的action。 -->

        <receiver android:name=".BootCompleteReceiver" >

            <intent-filter>

                <action android:name="android.intent.action.BOOT_COMPLETED" />

            </intent-filter>

        </receiver>


        注意:不要在onReceive()方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中是不允许开启线程的,当onReceive()方法运行了较长时间而没有结束时,程序就会报错。因此广播接收器更多的是扮演一种打开程序其他组件的角色,比如创建一条状态栏通知,或者启动一个服务等

 

四、发送自定义广播

        1.自定义接收器和注册(其他程序接收同理)

public class MyBroadcastReceiver extends BroadcastReceiver { 

@Override 

public void onReceive(Context context, Intent intent) { 

Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show(); 

} 

} 

 

<receiver android:name=".MyBroadcastReceiver"> 

<intent-filter> 

<action android:name="com.example.broadcasttest. MY_BROADCAST"/> 

</intent-filter> 

</receiver> 


        2.修改按钮的点击事件发送自定义广播

public void onClick(View v) { 

Intent intent = new Intent("com.example.broadcasttest. MY_BROADCAST"); 

sendBroadcast(intent); 

} 


        五、发送有序广播

        方法:

sendOrderedBroadcast(intent, null); //第二个参数是一个与权限相关的字符串

        优先级设置:

<intent-filter android:priority="100" > 

<action android:name="com.example.broadcasttest.MY_BROADCAST"/> 

</intent-filter> 


        截断广播:

abortBroadcast(); 

 

六、使用本地广播

        使用本地广播机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播。本地广播无法静态注册。

        优势:

        1. 可以明确地知道正在发送的广播不会离开我们的程序,因此不需要担心机密数据泄漏的问题。 

        2. 其他的程序无法将广播发送到我们程序的内部,因此不需要担心会有安全漏洞的隐患。 

        3. 发送本地广播比起发送系统全局广播将会更加高效。 

 

private LocalReceiver localReceiver; 

private LocalBroadcastManager localBroadcastManager; 

localBroadcastManager = LocalBroadcastManager.getInstance(this); // 获取实例 

localBroadcastManager.sendBroadcast(intent); // 发送本地广播 

intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST"); 

localReceiver = new LocalReceiver(); 

localBroadcastManager.registerReceiver(localReceiver, intentFilter); // 注册本地广播监听器 

记得在onDestroy()里localBroadcastManager.unregisterReceiver(localReceiver); 

class LocalReceiver extends BroadcastReceiver { 

@Override 

public void onReceive(Context context, Intent intent) { 

Toast.makeText(context, "received local broadcast", Toast.LENGTH_SHORT).show(); 

} 

} 


七、实践——强制下线

        实现思路:用ActivityController管理全部活动。在需要强制下线的时候发送一个广播,在自定义的接收器的onReceive()中显示对话框,确认后调用ActivityController的finishAll()方法关闭所有活动并回到登录界面。

ActivityController代码:

package com.linh.forceoffline;

import java.util.ArrayList;

import java.util.List;

import android.app.Activity;

public class ActivityCollector {

public static List<Activity> activities = new ArrayList<Activity>();

public static void addActivity(Activity activity) {

activities.add(activity);

}

public static void removeActivity(Activity activity) {

activities.remove(activity);

}

//遍历activities中每个activity,关闭他们

public static void finishAll()

{

for(Activity activity:activities)

{

if(!activity.isFinishing())

{

activity.finish();

}

}

}

 

}


BaseActivity作为所有activity的父类:

package com.linh.forceoffline;

 

import android.app.Activity;

import android.os.Bundle;

 

public class BaseActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

ActivityCollector.addActivity(this);

}

@Override

protected void onDestroy() {

super.onDestroy();

ActivityCollector.removeActivity(this);

}

}


LoginActivity实现简单的登录功能,登录后进入MainActivity

MainActivity中点击按钮则发送一条广播。

自定义广播接收器ForceOfflineReceiver 

package com.linh.forceoffline;

import android.app.AlertDialog;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.DialogInterface;

import android.content.DialogInterface.OnClickListener;

import android.content.Intent;

import android.view.WindowManager;

public class ForceOfflineReceiver extends BroadcastReceiver {

@Override

public void onReceive(final Context context, Intent intent) {

//构建一个对话框

AlertDialog.Builder dialogBuilder=new AlertDialog.Builder(context);

dialogBuilder.setTitle("警告");

dialogBuilder.setMessage("你被强制下线,请重新登录");

//一定要不可取消

dialogBuilder.setCancelable(false);

//注册确认按钮

dialogBuilder.setPositiveButton("确认", new OnClickListener() {

@Override

public void onClick(DialogInterface dialog, int which) {

ActivityCollector.finishAll();//销毁所有活动

Intent intent=new Intent(context,LoginActivity.class);

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

//重新启动LoginActivity

context.startActivity(intent);

}

});

AlertDialog alertDialog=dialogBuilder.create();

//需要设置AlertDialog的类型,保证在广播接收器中可以正常弹出

alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

alertDialog.show();

}

}


最后在AndroidManifest.xml配置:

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

<application 

android:allowBackup="true" 

android:icon="@drawable/ic_launcher" 

android:label="@string/app_name" 

android:theme="@style/AppTheme" > 

<activity 

android:name=".LoginActivity" 

android:label="@string/app_name" > 

<intent-filter> 

<action android:name="android.intent.action.MAIN" /> 

<category android:name="android.intent.category.LAUNCHER" /> 

</intent-filter> 

</activity> 

<activity android:name=".MainActivity" > 

</activity> 

<receiver android:name=".ForceOfflineReceiver" > 

<intent-filter> 

<action android:name="com.example.broadcastbestpractice. FORCE_OFFLINE" /> 

</intent-filter> 

</receiver> 

</application> 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值