zoukankan      html  css  js  c++  java
  • 广播的最佳实践-实现强制下线功能

    主体思想

    使用ActivityCollector来收集所有活动,所有的活动均继承自BaseActivity,使得每个活动在onCreate方法执行时,都会被加入到AcrivityCollector中。在每个活动onDestroy时都会从ActivityCollector中移除。这样就可以一次性将所有的活动全部销毁。在登陆界面输入账号密码,代码的设定是只有当敲击Login按钮时才会去获取两个EditText中,符合逻辑

    交互的流程是,输入账号密码,无误后跳转到MainActivity,点击按钮发送广播,app中的recreiver接收到广播执行onReceive方法,弹出AlertDialog窗口,给ok按钮设置监听。按下ok之后,用ActivityCollector销毁所有活动,重新加载login活动

    值得注意

    因为是从接收器中弹出活动,intent需加入FLAG_ACTIVITY_NEW_TASK,形如intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),在接受器里启动活动,需以这样的格式:context.startActivity(intent),而intent的初始化是以这样的形式:Intent intent = new Intent(context,MainActivity.class),似乎在接收器里都用context来表示接收器的上下文

    再有,因为提示框是从广播接收器中弹出的,所以需要把对话框的类型设置为TYPE_SYSTEM_ALERT,形如:alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT),由于都调用了系统级别的对话框,也需要在Manifest文件下注册<user-permission android:name="android.permission.SYSTEM_ALERT_WINDOW">,该应用才能使用该对话框

    另外需要注意的是,AlertDialog的造法:

    1
    2
    3
    4
    5
    6
    7
    AlertDialog.Builder builder = new AlertDialog.Builder(context)
    builder.setTitle
    builder.setMessage
    builder.setPositiveButton("OK",new OnclickListener{....})
    AlertDialog alertDialog = builder.create();
    alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
    alertDialog.show()

    先弄个builder,再用这个builder去建一个AlertDialog,接着再设置这个AlertDialog的类型,最后让他show出来

    代码结构

    代码结构代码结构

    上代码

    ActivityCollector.class

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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);
    }

    public static void finishAll(){
    for(Activity activity : activities){
    if(!activity.isFinishing()){
    activity.finish();
    }
    }
    }
    }

    BaseActivity.class

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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);
    }
    }

    forceReceiver.class

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public class ForceOffReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(final Context context, final Intent intent) {
    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder.setTitle("Waring");
    builder.setCancelable(false);
    builder.setMessage("you are forced to offline");
    builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
    ActivityCollector.finishAll();
    Intent intent1 = new Intent(context,loginActivity.class);
    intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(intent1);
    }
    });

    AlertDialog alertDialog = builder.create();
    alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
    alertDialog.show();
    }
    }

    loginActivity.class

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30

    public class loginActivity extends BaseActivity {

    EditText accountEdit;

    EditText passwordEdit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    accountEdit = (EditText) findViewById(R.id.content_account);
    passwordEdit = (EditText) findViewById(R.id.content_password);
    Button btn = (Button) findViewById(R.id.btn_login);
    btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    String account = accountEdit.getText().toString();
    String password = passwordEdit.getText().toString();
    if(account.equals("guojiale") && password.equals("123456")){
    Intent intent = new Intent(loginActivity.this,MainActivity.class);
    startActivity(intent);
    } else{
    Toast.makeText(loginActivity.this, "Check your account and password", Toast.LENGTH_SHORT).show();
    }
    }
    });
    }

    }

    MainActivity.class

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class MainActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button button = (Button) findViewById(R.id.btn_sendBrodcast);
    button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    Intent intent = new Intent("forceOff");
    sendBroadcast(intent);
    }
    });
    }

    }

    零散笔记

    广播接收器中不允许开线程,如果广播接收器中有太多操作,耗时太长,程序会报错

    在一个应用的Manifest文件中,配置
    使得该应用获得监听系统开机广播的权限,在中,写 rr这是在注册监听器

    在manifest中receiver(接收器)的intent-filter中的action是表示该接收器监听的广播类型一旦收到相应类型的广播,就会执行该接收器中的逻辑

    在一个活动中发送广播,sendBroadcast为发送标准广播,sendOrderedBroadcast为发送有序广播,在Manifest文件下配置receiver需要的intentFilter,用priority来判断接收器的接收顺序

    使用abortBroadcast() 截断广播

    1
    2
    3
    4
    LocalBroadcastManager l = LocalBraodcastManager.getInstace(this)
    l.registerReceiver(localReceiver,intentFilter);
    l.sendBroadcast(intent)
    l.unregisterReceiver(localReceiver)

    抛出异常:
    java.lang.RuntimeException: Unable to start receiver com.example.gaby.broadcastbestpractice.ForceOffReceiver: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@d5bf998 – permission denied for this window type

    原因:使用了系统级别的对话框,但没有在Manifest文件下声明该权限
    解决办法:在Manifest文件下声明< user-permission android:name=”android.permission.SYSTEM_ALERT_WINDOW” />

  • 相关阅读:
    函数定义、调用
    条件语句和循环语句
    eclipse中安装pydev插件出现duplicate location
    编码类型
    除法
    数据类型
    命令和python模式转换
    前言
    SpringMVC_json
    解决eclipse中Tomcat服务器的server location选项不能修改的问题
  • 原文地址:https://www.cnblogs.com/gabygoole/p/5299869.html
Copyright © 2011-2022 走看看