详解广播机制,Broadcast Receiver,Android进阶必备知识(三)。(附使用广播实现一键强制下线功能)

  在前面两节我们发送和接受的都属于系统级别的广播,但是你又没有想过,万一你的应用中的某个广播被别人知道了,人家恶意给你发送各种垃圾广播怎么办?安全性在哪?所以Android为了解决这个问题引入了一套本地广播机制。使用这个机制的广播只能在本应用程序内传播,且接收器也只能接受来自本应用的广播,这样的话刚才说的那个安全问题就已经不算是问题了吧。

  下面给一个关于本地广播的一个例子:

public class MainActivity extends AppCompatActivity {
    private IntentFilter intentFilter;
    private LocalBroadcastManager localBroadcastManager;
    private LocalReceiver localReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btn = (Button) findViewById(R.id.sendlocalbradcast);
 localBroadcastManager = LocalBroadcastManager.getInstance(this);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent it = new Intent("wang.zi.yang.fristBroadcast");
                localBroadcastManager.sendBroadcast(it);
            }
        });
intentFilter = new IntentFilter();
        intentFilter.addAction("wang.zi.yang.fristBroadcast");
        localReceiver = new LocalReceiver();
        localBroadcastManager.registerReceiver(localReceiver, intentFilter);
    }
  @Override
    protected void onDestroy() {
        super.onDestroy();
        localBroadcastManager.unregisterReceiver(localReceiver);
    }

    class LocalReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "接受到广播了", Toast.LENGTH_SHORT).show();
        }
    }

}

  关键的就是使用LocalbroadcastManager的getInstance获取一个实例,然后使用这个实例去操作广播的注册,反注册,发送等。

  注意:因为本地广播只在本应用中传播所以注册的时候只可以使用动态注册法。

  下面给一个使用广播实现强制下线的DEMO,使用的是广播实现的,在刚才的基础上修改:

  

public class MainActivity extends AppCompatActivity {
    private IntentFilter intentFilter;
    private LocalBroadcastManager localBroadcastManager;
    private LocalReceiver localReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btn = (Button) findViewById(R.id.sendlocalbradcast);
        Button downlinebtn = (Button) findViewById(R.id.senddownlinebradcast);

        localBroadcastManager = LocalBroadcastManager.getInstance(this);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent it = new Intent("wang.zi.yang.fristBroadcast");
                localBroadcastManager.sendBroadcast(it);
            }
        });
        downlinebtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent it = new Intent("wang.zi.yang.downline");
                sendBroadcast(it);
            }
        });
        intentFilter = new IntentFilter();
        intentFilter.addAction("wang.zi.yang.fristBroadcast");
        localReceiver = new LocalReceiver();
        localBroadcastManager.registerReceiver(localReceiver, intentFilter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        localBroadcastManager.unregisterReceiver(localReceiver);
    }

    class LocalReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "接受到广播了", Toast.LENGTH_SHORT).show();
        }
    }

}

ActivityControl是用来记录保存每次打开的Activity:

  

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

    public static void addActivity(Activity activity){
        if (!activities.contains(activity)){
            activities.add(activity);
        }
    }

    public static void removeActivity(Activity activity){
        activities.remove(activity);
    }

    public static void finishAll(){
        for (Activity activity:activities){
            if (!activity.isFinishing()){
                activity.finish();
            }
        }
    }
}
MybaseActivity作为本项目中的所有Activity的父Activity:
public class MybaseActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityControl.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityControl.removeActivity(this);
    }
}
LoginActivity在里面我们实现一个模拟的登录环境:
public class LoginActivity extends MybaseActivity implements View.OnClickListener {
    private EditText accountEdit;
    private EditText passwordEdit;
    private Button login;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        accountEdit = (EditText)findViewById(R.id.account);
        passwordEdit = (EditText)findViewById(R.id.password);
        login = (Button) findViewById(R.id.login);

        login.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.login:
                String account = accountEdit.getText().toString();
                String password = passwordEdit.getText().toString();
                if (account.equals("admin") && password.equals("123456")){
                    Intent it = new Intent(LoginActivity.this,MainActivity.class);
                    startActivity(it);
                    finish();
                }else {
                    Toast.makeText(LoginActivity.this,"帐号密码错误",Toast.LENGTH_LONG).show();
                }
                break;
        }
    }
}
activity_login.xml是登录的界面:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:stretchColumns="1">
    <TableRow>
        <TextView
            android:layout_height="wrap_content"
            android:text="Account:"/>
        <EditText
            android:id="@+id/account"
            android:layout_height="wrap_content"
            android:hint="input your account"/>
    </TableRow>
    <TableRow>
        <TextView
            android:layout_height="wrap_content"
            android:text="Password:"/>
        <EditText
            android:id="@+id/password"
            android:layout_height="wrap_content"
            android:inputType="textPassword"/>
    </TableRow>
    <TableRow>
        <Button
            android:id="@+id/login"
            android:layout_height="wrap_content"
            android:layout_span="2"
            android:text="login"/>
    </TableRow>
</TableLayout>
DownLineReceiver用来接受我们发送的强制下线的广播,并在里面做强制下线的操作:
public class DownLineReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, Intent intent) {
        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
        dialogBuilder.setTitle("Warning!");
        dialogBuilder.setMessage("You are forced to be offline. Please tyr to login again.");
        dialogBuilder.setCancelable(false);
        dialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int which) {
                ActivityControl.finishAll();
                Intent it = new Intent(context, LoginActivity.class);
                it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(it);
            }
        });
        AlertDialog alertDialog = dialogBuilder.create();
        alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        alertDialog.show();
    }
}

最后在AndroidManifest.xml中的注册如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="wang.zi.yang.testny">

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.NoActionBar">
        <activity android:name=".MainActivity">
        </activity>
        <activity android:name=".LoginActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name="wang.zi.yang.Receiver.DownLineReceiver">
            <intent-filter>
                <action android:name="wang.zi.yang.downline" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

其中的功能很全,代码很简单,只要把这个DEMO理解透彻了,在工作中懂得变通,基本上就可以应对一般的工作内容了。

时间: 2024-08-10 21:20:49

详解广播机制,Broadcast Receiver,Android进阶必备知识(三)。(附使用广播实现一键强制下线功能)的相关文章

详解广播机制,Broadcast Receiver,Android进阶必备知识(一)。

直奔主题,关于广播的一些定义什么的我觉得只要是一名合格的初级android开发这都知道吧,我下面要做的就是怎么去使用broadcast receiver. 1.怎么去监听系统广播? Android系统有很多内置的系统广播:电话,短信,时间,地区,电池电量,网络变化等等...那么我们怎么去在我们的应用中实现监听呢?下面我们以监听手机网络发生改变的广播进行监听,都知道广播有两种注册方式,在这里我使用的代码注册的方式,为的是能更好的去理解广播运行机制.在代码中注册一定要注意在你使用完毕的时候一定要反注

详解广播机制,Broadcast Receiver,Android进阶必备知识(二)。

唉···昨天写的博客,被博客园管理组嫌弃了...伤心! 昨天就谢了广播的基本用法,今天就往深里扒扒,明天继续写关于广播的博客. 昨天说的多是关于系统广播的接收,也是系统广播的接收,现在说说自定义广播的用法.先说标准广播的,拿昨天静态注册那个例子来说.其他地方都一样知识把清单文件里面的action给替换为我们自己定义的action就行了. <receiver android:name=".BootCompleteReceiver"> <intent-filter>

图文详解如何搭建Windows的Android C++开发环境

原地址:http://www.apkbus.com/android-18595-1-1.html //=====================================================================//TITLE://    图文详解如何搭建Windows的Android C++开发环境(一)//AUTHOR://    norains//DATE://    Thursday  14-April-2011//Environment://    Cygw

Android菜单详解(一)——理解android中的Menu

前言 今天看了pro android 3中menu这一章,对Android的整个menu体系有了进一步的了解,故整理下笔记与大家分享. PS:强烈推荐<Pro Android 3>,是我至今为止看到的最好的一本android书,中文版出到<精通Android 2>. 理解Android的菜单 菜单是许多应用程序不可或缺的一部分,Android中更是如此,所有搭载Android系统的手机甚至都要有一个"Menu"键,由此可见菜单在Android程序中的特殊性.An

抓包工具Fidder详解(主要来抓取Android中app的请求)

抓包工具Fidder详解(主要来抓取Android中app的请求) 今天闲着没吊事,来写一篇关于怎么抓取Android中的app数据包?工欲行其事,必先利其器,上网google了一下,发现了一款神器:Fiddler,这个貌似是所有软件开发者必备神器呀!这款工具不仅可以抓取PC上开发web时候的数据包,而且可以抓取移动端(Android,Iphone,WindowPhone等都可以),太强大了,以前搞web的时候,知道有一款叫做HttpWatch工具,可以抓取web的请求数据包的,但是和这款神器来

QtAndroid详解(5):JNI调用Android系统功能(2)

在"QtAndroid详解(4):JNI调用Android系统功能(1)"中我们给出了一些简单的示例,演示了如何使用 Qt JNI 类库访问网络状态.系统资源目录.当前应用信息等等,这次呢,我们提供一些新的示例,这些示例可能更具实际意义.本文的示例包括: 震动 让屏幕常亮 动态改变应用的显示方向(横屏.竖屏) 调节屏幕亮度 设置铃声模式 示例介绍 图1 我们按照界面上的顺序,一个一个来看这些功能如何实现. 源码分析 构建界面的代码在 Widget 类的构造函数里,不说了.这次我们换个搞

Android学习之基础知识八—Android广播机制实践(实现强制下线功能)

强制下线功能算是比较常见的了,很多的应用程序都具备这个功能,比如你的QQ号在别处登录了,就会将你强制挤下线.实现强制下线功能的思路比较简单,只需要在界面上弹出一个对话框,让用户无法进行任何操作,必须要点击对话框中的确定按钮,然后回到登录界面即可.下面我们就来一步一步的实现这个功能: 第一步:创建一个活动管理器ActivityCollector,用于管理所有的活动 第二步:创建所有活动的父类BaseActivity,继承AppCompatActivity 因为所有的活动都是继承该活动,所有我们在该

android#boardcast#广播实现强制下线功能

参考自<第一行代码>——郭霖 强制下线功能需要先关闭掉所有的活动(Activity),然后回到登录界面.先创建一个ActivityCollector类用于管理所有的活动,代码如下所示: public class ActivityCollector { public static List<Activity> activities = new ArrayList<Activity>(); public static void addActivity(Activity ac

android: 实现强制下线功能

强制下线功能应该算是比较常见的了,很多的应用程序都具备这个功能,比如你的 QQ 号在别处登录了,就会将你强制挤下线.其实实现强制下线功能的思路也比较简单,只需要 在界面上弹出一个对话框,让用户无法进行任何其他操作,必须要点击对话框中的确定按钮, 然后回到登录界面即可.可是这样就存在着一个问题,因为我们被通知需要强制下线时可能 正处于任何一个界面,难道需要在每个界面上都编写一个弹出对话框的逻辑?如果你真的这 么想,那思维就偏远了,我们完全可以借助本章中所学的广播知识,来非常轻松地实现这一 功能.新