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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解广播机制,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理解透彻了,在工作中懂得变通,基本上就可以应对一般的工作内容了。

以上是关于详解广播机制,Broadcast Receiver,Android进阶必备知识。(附使用广播实现一键强制下线功能)的主要内容,如果未能解决你的问题,请参考以下文章

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

Android面试收集录2 Broadcast Receiver详解

Android Broadcast Receiver (广播接收者)

品茗论道说广播(Broadcast内部机制讲解)(下)

Android中Intent具体解释之使用Intent广播事件及Broadcast Receiver简单介绍

广播——broadcast