• 安卓笔记20170113


    1.广播接收器

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

    本地广播是无法通过静态注册的方式来接收的。因为静态注册主要是为了让程序在未启动的情况下也能收到广播,而发送本地广播时,程序肯定已经启动了。

    本地广播的优势:

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

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

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

    示例代码:

    public class MainActivity extends Activity {
        
        private IntentFilter intentFilter;
        
        private LocalReceiver intentFilter;
        
        private LocalBroadcastManager localBroadcastManager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            localBroadcastManager = LocalBroadcastManager.getInstance(this);
            Button button = (Button) findViewById(R.id.button);
            button.setOnClickListener(new OnClickListener() {
                
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
                    localBroadcastManager.sendBroadcast(intent);
                }
            });
            intentFilter = new IntentFilter();
            intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
            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, "received local broadcast", Toast.LENGTH_SHORT).show();
            }
            
        }
    }

    案例:实现强制下线功能

    public class ActivityCollector {
        
        public static List<Activity> activities = new ArrayList<>();
        
        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();
                }
            }
        }
        
    }
    public class BaseActivity extends Activity {
        
        private ForceOfflineReceiver receiver;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ActivityCollector.addActivity(this);
        }
        
        @Override
        protected void onDestroy() {
            super.onDestroy();
            ActivityCollector.removeActivity(this);
        }
        
        @Override
        protected void onResume() {
            super.onResume();
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction("com.example.broadcastbestpractice.FORCE_OFFLINE");
            receiver = new ForceOfflineReceiver();
            registerReceiver(receiver, intentFilter);
        }
        
        @Override
        protected void onPause() {
            super.onPause();
            if(receiver != null){
                unregisterReceiver(receiver);
                receiver = null;
            }
        }
        
        class ForceOfflineReceiver extends BroadcastReceiver{
    
            @Override
            public void onReceive(final Context context, Intent intent) {
                AlertDialog.Builder builder = new AlertDialog.Builder(context);
                builder.setTitle("Warning");
                builder.setMessage("You are forced to be offline. Please try to login again.");
                builder.setCancelable(false);
                builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ActivityCollector.finishAll();
                        Intent intent = new Intent(context, LoginActivity.class);
                        context.startActivity(intent);
                    }
                });
                builder.show();
            }
            
        }
    }
    public class LoginActivity extends BaseActivity {
    
        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(new OnClickListener() {
                
                @Override
                public void onClick(View v) {
                    String account = accountEdit.getText().toString();
                    String password = passwordEdit.getText().toString();
                    if(account.equals("admin") && password.equals("123456")){
                        Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                        startActivity(intent);
                        finish();
                    }else{
                        Toast.makeText(LoginActivity.this, "account or password is invalid", Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    }
    public class MainActivity extends BaseActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button forceOffline = (Button) findViewById(R.id.force_offline);
            forceOffline.setOnClickListener(new OnClickListener() {
                
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent("com.example.broadcastbestpractice.FORCE_OFFLINE");
                    sendBroadcast(intent);
                }
            });
        }
    }

    最后说明:activity_main.xml布局文件里面只放置了一个按钮,activity_login.xml布局文件里面放置了账户密码框及登录按钮。
    静态注册的广播接收器,是没有办法在onReceive()方法里弹出对话框这样的UI控件的。出于安全原因的考虑,Android是不允许Activity或Dialog凭空出现的,一个Activity的启动必须要建立在另一个Activity的基础之上,也就是以此形成的返回栈。而Dialog则必须在一个Activity上面弹出(除非是System Alert类型的Dialog)。

    使用静态注册广播,只能弹出System Alert类型的Dialog。但google在 6.0加入了运行时权限的概念,需要在Java代码中进行动态申请。为了防止旧的应用程序崩溃,只对targetSDK为23及以上的程序使用新的权限机制。 相应的解决方法有如下几种。

    第一种方式是:targetSDK设为23以下就可以规避问题。

    第二种方式是:设置里面给了这个调试应用【允许悬浮窗】 但是得手动的打开(我是没有找到这个悬浮窗到底在哪里)。

    第三种方式是:使用无需权限显示悬浮窗。参考链接: Android无需权限显示悬浮窗: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/1017/3589.html

    问题解决

    这里使用第三种,简单方便。 1  修改广播接收类中的import包 将

    import android.support.v7.app.AlertDialog;

     修改为:

    import android.app.AlertDialog;

    2  修改AlertDialog的弹窗类型为:TYPE_TOAST 将

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

    修改为:

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

    这样编译运行就可以正常弹出AlertDialog了。

    上面的笔记来自 http://blog.csdn.net/chenHCYJ/article/details/53191675

    继承BaseActivity,避免了在每一个活动中都去注册一个动态的广播接收器。

    最后,因为我们始终需要保证只有处于栈顶的活动才能接收到这条强制下线广播,非栈顶的活动不应该也没有必要去接收这条广播,所以写在onResume()和onPause()方法里就可以很好地解决这个问题,当一个活动失去栈顶位置时就会自动取消广播接收器的注册。

  • 相关阅读:
    1123 Is It a Complete AVL Tree (30分)---如何建立平衡二叉搜索树(LL型RR型LR型RL型)+如何判断完全二叉树
    1021 Deepest Root (25 分)(经典搜索)
    PAT甲 1020 Tree Traversals (树的后序中序->层序)
    (数据结构)如何根据树的后序中序遍历求树的前序遍历
    习题2.3 数列求和-加强版 (模拟)
    PAT甲级 1051 Pop Sequence (25) && 2019天梯赛 L2-032 彩虹瓶 (25 分) (模拟+栈)
    PAT甲级 Are They Equal (25) (恶心模拟)
    PAT甲级1059 Prime Factors (25)(素数筛+求一个数的质因子)
    IO 模型
    Nginx 反向代理
  • 原文地址:https://www.cnblogs.com/919czzl/p/6283488.html
Copyright © 2020-2023  润新知