csschn

Android,你等等我。。。

导航

【实战】广播实践,实现登录强制下线

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

一、建立工具类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存储、广播发送和接收等知识;运行效果图如下:

 

posted on 2016-03-09 15:57  csschn  阅读(600)  评论(0编辑  收藏  举报