zoukankan      html  css  js  c++  java
  • 【实战】广播实践,实现登录强制下线

    本章学习了广播的机制,通过一个强制下线登陆用户的功能进行实战。

    一、建立工具类ActivityCollector,实现关闭所有活动的功能,

     1 package Tools;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 import android.app.Activity;
     7 
     8 //工具类
     9 public class ActivityCollector {
    10     public static List<Activity> activities = new ArrayList<>();//新建列表存储活动
    11     public static void addActivity(Activity activity)//新增活动到列表
    12     {
    13         activities.add(activity);
    14     }
    15     public static void removeActivity(Activity activity)//移除活动出列表
    16     {
    17         activities.remove(activity);
    18     }
    19     public static void finishAll()//移除所有活动
    20     {
    21         for(Activity activity : activities)
    22         {
    23             if(!activity.isFinishing())
    24             {
    25                 activity.finish();
    26             }
    27         }
    28     }
    29 }
    ActivityCollector

     二、新建基类BaseActivity继承于Activity,重写父类的onCreate方法和onDestory方法如下,其他的活动均继承于此基类,代码如下:

     1 package BaseActivity;
     2 
     3 import Tools.ActivityCollector;
     4 import android.app.Activity;
     5 import android.os.Bundle;
     6 
     7 public class BaseActivity extends Activity {
     8     @Override
     9     protected void onCreate(Bundle savedInstanceState) {
    10         // TODO Auto-generated method stub
    11         super.onCreate(savedInstanceState);
    12         ActivityCollector.addActivity(this);//添加此活动
    13     }
    14     
    15     @Override
    16     protected void onDestroy() {
    17         // TODO Auto-generated method stub
    18         super.onDestroy();
    19         ActivityCollector.removeActivity(this);//移除此活动
    20     }
    21 }
    BaseActivity

    三、使用表格布局TableLayout创建登陆界面,并且使用SharedPreferences实现记住密码功能,创建登陆界面的xml代码如下:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:id="@+id/TableLayout1"
     4     android:layout_width="match_parent"
     5     android:layout_height="match_parent"
     6     android:stretchColumns="1" >
     7 
     8     <TableRow>
     9        <TextView 
    10            android:layout_height="wrap_content"
    11            android:text="Account:"/>
    12        <EditText 
    13            android:id="@+id/account"
    14            android:layout_height="wrap_content"
    15            android:hint="Input your account"/>
    16     </TableRow>
    17     
    18     <TableRow>
    19        <TextView 
    20            android:layout_height="wrap_content"
    21            android:text="Password:"/>
    22        <EditText 
    23            android:id="@+id/password"
    24            android:layout_height="wrap_content"
    25            android:hint="Input your password"
    26            android:inputType="textPassword"/>
    27     </TableRow>
    28     
    29     <TableRow >
    30         <CheckBox 
    31             android:id="@+id/remember_pass"
    32             android:layout_height="wrap_content"/>
    33         <TextView 
    34             android:layout_height="wrap_content"
    35             android:text="Remember password"/>
    36     </TableRow>
    37     
    38     <TableRow>
    39         <Button    
    40             android:id="@+id/login"
    41             android:layout_height="wrap_content"
    42             android:layout_span="2"
    43             android:text="Login"/>
    44     </TableRow>
    45     
    46 </TableLayout>

    四、做好了登陆界面,就要创建登陆对应的活动LoginActivity继承于BaseActivity;在代码中实现了记住密码功能;

     1 package com.example.broadcastbestpractice;
     2 
     3 import android.content.Intent;
     4 import android.content.SharedPreferences;
     5 import android.os.Bundle;
     6 import android.preference.PreferenceManager;
     7 import android.view.View;
     8 import android.view.View.OnClickListener;
     9 import android.widget.Button;
    10 import android.widget.CheckBox;
    11 import android.widget.EditText;
    12 import android.widget.Toast;
    13 import BaseActivity.BaseActivity;
    14 
    15 public class LoginActivity extends BaseActivity {
    16     
    17     private SharedPreferences pref;//定义私有类型的SharedPreferences
    18     private SharedPreferences.Editor editor;//定义私有类型的SharedPreferences.Editor
    19     
    20     private EditText accountEdit;//定义私有类型四个控件
    21     private EditText passwordEdit;
    22     private Button login;
    23     private CheckBox rememberPass;
    24     
    25     @Override
    26     protected void onCreate(Bundle savedInstanceState) {
    27         // TODO Auto-generated method stub
    28         super.onCreate(savedInstanceState);
    29         setContentView(R.layout.login);
    30         
    31         //获取PreferenceManager对象
    32         pref = PreferenceManager.getDefaultSharedPreferences(this);
    33         
    34         //实例化控件
    35         accountEdit = (EditText) findViewById(R.id.account);
    36         passwordEdit = (EditText) findViewById(R.id.password);
    37         rememberPass = (CheckBox) findViewById(R.id.remember_pass);
    38         login = (Button) findViewById(R.id.login);
    39         
    40         //调用PreferenceManager的getBoolean方法获取存放起来的键值对,刚开始为false;
    41         boolean isRemember = pref.getBoolean("remember_password", false);
    42         
    43         //isRemember如果是真,则把存放起来的值取出来,赋值给控件,初始化让控件中显示存储的值
    44         if(isRemember)
    45         {
    46             String account = pref.getString("account", "");
    47             String password = pref.getString("password", "");
    48             accountEdit.setText(account);
    49             passwordEdit.setText(password);
    50             rememberPass.setChecked(true);
    51         }
    52         
    53         //设置登录按钮的点击事件
    54         login.setOnClickListener( new OnClickListener() {
    55             
    56             @Override
    57             public void onClick(View v) {
    58                 // TODO Auto-generated method stub
    59                 String account = accountEdit.getText().toString();
    60                 String password = passwordEdit.getText().toString();
    61                 if(account.equals("admin") && password.equals("123456"))
    62                 {
    63                     editor = pref.edit();
    64                     if(rememberPass.isChecked())//检查复选框是否被选中,选中的话存储到editor中
    65                     {
    66                         editor.putBoolean("remember_password", true);
    67                         editor.putString("account", account);
    68                         editor.putString("password", password);
    69                     }
    70                     else//没选中的话清楚editor中的值
    71                     {
    72                         editor.clear();
    73                     }
    74                     editor.commit();//提交editor
    75                     
    76                     //使用Intent实现页面的跳转
    77                     Intent intent = new Intent(LoginActivity.this , MainActivity.class);
    78                     startActivity(intent);
    79                     finish();//销毁本活动
    80                 }
    81                 else//如果密码错误,使用Toast进行提示
    82                 {
    83                     Toast.makeText(LoginActivity.this, "account or password is invalid", Toast.LENGTH_SHORT).show();
    84                 }
    85             }
    86         });
    87     }
    88 }
    LoginActivity

    五、布局登陆好的界面,这里用系统自动生成的页面来修改,简单起见,只添加一个按钮来实现销毁所有活动,实现强制下线;

     1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     android:id="@+id/LinearLayout1"
     4     android:layout_width="match_parent"
     5     android:layout_height="match_parent"
     6     android:paddingBottom="@dimen/activity_vertical_margin"
     7     android:paddingLeft="@dimen/activity_horizontal_margin"
     8     android:paddingRight="@dimen/activity_horizontal_margin"
     9     android:paddingTop="@dimen/activity_vertical_margin"
    10     tools:context="com.example.broadcastbestpractice.MainActivity" >
    11 
    12     <Button
    13         android:id="@+id/force_offline"
    14         android:layout_width="match_parent"
    15         android:layout_height="wrap_content"
    16         android:text="Send force offline broadcast" />
    17 
    18 </LinearLayout>

    六、编写MainActivity中的代码,发送广播实现强制下线功能;需要注意的是强制用户下线的代码不在这里,而在接收这条广播的广播接收器里面,这样强制下线就不会依赖于任何界面;只要收到广播就可以实现强制下线

     1 package com.example.broadcastbestpractice;
     2 
     3 import BaseActivity.BaseActivity;
     4 import android.content.Intent;
     5 import android.os.Bundle;
     6 import android.view.View;
     7 import android.view.View.OnClickListener;
     8 import android.widget.Button;
     9 
    10 public class MainActivity extends BaseActivity {
    11     @Override
    12     protected void onCreate(Bundle savedInstanceState) {
    13         super.onCreate(savedInstanceState);
    14         setContentView(R.layout.activity_main);
    15         Button forceOffline = (Button) findViewById(R.id.force_offline);
    16         
    17         //在点击事件里发送一条广播,广播的值为com.example.broadcastbestpractice.FORCE_OFFLINE,用于通知用户强制下线
    18         forceOffline.setOnClickListener(new OnClickListener() {
    19             @Override
    20             public void onClick(View v) {
    21                 Intent intent = new Intent("com.example.broadcastbestpractice.FORCE_OFFLINE");
    22                 sendBroadcast(intent);//发出一条广播
    23             }
    24         });
    25     }
    26 
    27     
    28 }
    MainActivity

    七、接下来就要创建一个广播接收器了,用于实现强制下线;新建类ForceOfflineReceiver继承于BroadcastReceiver,代码如下:

     1 package com.example.broadcastbestpractice;
     2 
     3 import com.example.broadcastbestpractice.LoginActivity;
     4 import Tools.ActivityCollector;
     5 import android.app.AlertDialog;
     6 import android.content.BroadcastReceiver;
     7 import android.content.Context;
     8 import android.content.DialogInterface;
     9 import android.content.Intent;
    10 import android.view.WindowManager;
    11 
    12 public class ForceOfflineReceiver extends BroadcastReceiver {
    13 
    14     //重写BroadcastReceiver的onReceive方法,这里的Context一定要定义为final
    15     public void onReceive(final Context context, Intent intent) {
    16         // TODO Auto-generated method stub
    17         
    18         //定义弹出框!
    19         AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
    20         dialogBuilder.setTitle("Warning");
    21         dialogBuilder.setMessage("You are force to be offline, Please try to login again!");
    22         dialogBuilder.setCancelable(false);//设置不可取消,不然强制下线没有意义
    23         
    24         //使用弹框的setPositiveButton方法设置对话框的确定按钮事件,
    25         //具体的操作:“销毁所有活动,跳转到其他页面,往intent中加入标签FLAG_ACTIVITY_NEW_TASK,然后启动新活动
    26         dialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
    27             @Override
    28             public void onClick(DialogInterface dialog, int which) {
    29                 // TODO Auto-generated method stub
    30                 ActivityCollector.finishAll();//销毁所有活动!
    31                 Intent intent = new Intent(context,LoginActivity.class);
    32                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    33                 context.startActivity(intent);//必须要加上前面的
    34             }
    35         });
    36         AlertDialog alertDialog = dialogBuilder.create();
    37         //设置AlertDialog的类型,保证在广播接收器中正常弹出
    38         //系统提示。它总是出现在应用程序窗口之上。
    39         //public static final int TYPE_SYSTEM_ALERT      =  FIRST_SYSTEM_WINDOW +3;
    40         
    41         //需要注意的是这种类型的AlterDialog必须要在AndroidManifedt中进行注册,不然不能使用
    42         alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
    43         //调用AlterDialog的show方法显示弹出框
    44         alertDialog.show();
    45     }
    46 
    47 }
    ForceOfflineReceiver

    八、最后我们只要设置下AndroidManifedt.xml就可以实现该功能了,主要要获取弹出框权限、注册活动、设置主活动、设置广播接收

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     3     package="com.example.broadcastbestpractice"
     4     android:versionCode="1"
     5     android:versionName="1.0" >
     6 
     7     <uses-sdk
     8         android:minSdkVersion="14"
     9         android:targetSdkVersion="21" />
    10     
    11 <!--     android.permission.SYSTEM_ALERT_WINDOW -->
    12 <!-- 允许一个程序打开窗口使用 TYPE_SYSTEM_ALERT,显示在其他所有程序的顶层 -->
    13     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    14     
    15     <application
    16         android:allowBackup="true"
    17         android:icon="@drawable/ic_launcher"
    18         android:label="@string/app_name"
    19         android:theme="@style/AppTheme" >
    20         <activity
    21             android:name=".LoginActivity"
    22             android:label="@string/app_name" >
    23             <intent-filter>
    24                 <action android:name="android.intent.action.MAIN" />
    25 
    26                 <category android:name="android.intent.category.LAUNCHER" />
    27             </intent-filter>
    28         </activity>
    29         
    30         <activity android:name=".MainActivity"></activity>
    31         
    32         <receiver android:name=".ForceOfflineReceiver"
    33                      >
    34             <intent-filter>
    35                 <action android:name="com.example.broadcastbestpractice.FORCE_OFFLINE"/>
    36             </intent-filter>
    37         </receiver>
    38         
    39     </application>
    40 
    41 </manifest>

    至此,此次实现用户登录强制下线的功能已经全部实现,用到了UI设计、活动、SharePreferences存储、广播发送和接收等知识;运行效果图如下:

     

  • 相关阅读:
    APICloud联合腾讯云推出“云主机解决方案“,各种福利等你拿
    WiFi模块Demo(新手教程)图文详解模块使用教程
    移动APP 微信支付完整过程(wxPay 方案一)
    APICloud开发者进阶之路 | txLive模块(直播类)试用分享
    解决R语言临时文件目录的问题(tempdir、tempfile)
    CentOS下SparkR安装部署:hadoop2.7.3+spark2.0.0+scale2.11.8+hive2.1.0
    Extending sparklyr to Compute Cost for K-means on YARN Cluster with Spark ML Library
    Running R jobs quickly on many machines(转)
    R语言快速深度学习进行回归预测(转)
    sparklyr包:实现Spark与R的接口
  • 原文地址:https://www.cnblogs.com/csschn/p/5258535.html
Copyright © 2011-2022 走看看