zoukankan      html  css  js  c++  java
  • Android学习总结——强制下线功能(广播)

          最近一口气买了好几本书,其中Android的《第一行代码》觉得真心不错,学到这个内容,顺便做个总结,加深印象。

         强制下线的基本思想就是在界面上弹出一个对话框,让用户必须点击确定按钮跳转到登录界面,这里就有一个问题,通知强制下线时可能处于任何一个界面,我们总不能在每个界面都要实现弹出对话框的逻辑,所以这里可以利用广播来实现。

      首先强制下线需要关闭所有活动,然后回到登录界面,所以我们这里创建一个ActivityCollector集合类来管理所有的活动,代码如下:

    package com.example.xch.broadcastpractice;
    
    import android.app.Activity;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by xch on 2016/12/15.
     */
    
    public class ActivityCollector {
        public static List<Activity> activityList=new ArrayList<Activity>();
        //将Activity加入集合
        public static void addActivity(Activity activity){
            activityList.add(activity);
        }
        //将Activity移除集合
        public static void removeActivity(Activity activity){
            activityList.remove(activity);
        }
        //关闭所有Activity
        public static void finishAll(){
            for(Activity activity:activityList){
                if(!activity.isFinishing()){
                    activity.finish();
                }
            }
        }
    }

       然后创建BaseActivity类作为所有活动的父类:这个类继承自Activity,然后重写onCreate()方法调用ActivityCollector的addActivity()方法将当前正在创建的活动添加到活动管理器中,同理在onDestroy()中移除活动。

    package com.example.xch.broadcastpractice;
    
    import android.app.Activity;
    import android.os.Bundle;
    
    /**
     * 作为所有活动的父类
     * Created by xch on 2016/12/15.
     */
    
    public class BaseActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ActivityCollector.addActivity(this);//将Activity加入集合
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            ActivityCollector.removeActivity(this);//将Activity从集合移除
        }
    }

    现在我们就可以随时随地将所有活动移除了。

    下面我们模拟一个简单的登录功能,首先创建登录布局:activity_login.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.example.xch.broadcastpractice.LoginActivity">
    
        <!-- Login progress -->
        <ProgressBar
            android:id="@+id/login_progress"
            style="?android:attr/progressBarStyleLarge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:visibility="gone" />
    
        <ScrollView
            android:id="@+id/login_form"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <LinearLayout
                android:id="@+id/email_login_form"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">
    
                <android.support.design.widget.TextInputLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">
    
                    <AutoCompleteTextView
                        android:id="@+id/username"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:hint="@string/prompt_email"
                        android:inputType="textEmailAddress"
                        android:maxLines="1"
                        android:singleLine="true" />
    
                </android.support.design.widget.TextInputLayout>
    
                <android.support.design.widget.TextInputLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">
    
                    <EditText
                        android:id="@+id/password"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:hint="@string/prompt_password"
                        android:imeActionId="@+id/login"
                        android:imeActionLabel="@string/action_sign_in_short"
                        android:imeOptions="actionUnspecified"
                        android:inputType="textPassword"
                        android:maxLines="1"
                        android:singleLine="true" />
    
                </android.support.design.widget.TextInputLayout>
    
                <Button
                    android:id="@+id/login"
                    style="?android:textAppearanceSmall"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="16dp"
                    android:text="@string/action_sign_in"
                    android:textStyle="bold" />
    
            </LinearLayout>
        </ScrollView>
    </LinearLayout>

    接下来编写登录界面的活动,新建LoginActivity继承自BaseActivity,代码如下:

    package com.example.xch.broadcastpractice;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    /**
     * Created by xch on 2016/12/15.
     */
    
    public class LoginActivity extends BaseActivity {
        private TextView usename;
        private EditText password;
        private Button login;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login);
            usename= (TextView) findViewById(R.id.username);
            password= (EditText) findViewById(R.id.password);
            login= (Button) findViewById(R.id.login);
            login.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String account=usename.getText().toString();
                    String pwd=password.getText().toString();
                    if(account.equals("xch_yang@126.com")&&pwd.equals("123456")){
                        Intent intent=new Intent(LoginActivity.this,MainActivity.class);
                        startActivity(intent);
                        finish();
                    }else{
                        Toast.makeText(LoginActivity.this,"用户名或密码错误!",Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    }

    这里直接使用一个默认值,如果登录成功就跳到MainActivity,否则就登录失败。所以我们在MainActivity中添加强制下线的功能。activity_main:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.example.xch.broadcastpractice.MainActivity">
    
        <TextView
            android:text="恭喜你,登录成功!"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="119dp"
            android:layout_marginStart="119dp"
            android:layout_marginTop="15dp"
            android:id="@+id/textView"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true" />
    
        <Button
            android:text="强制下线"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="35dp"
            android:id="@+id/force_offline"
            android:layout_below="@+id/textView"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_marginLeft="105dp"
            android:layout_marginStart="105dp" />
    </RelativeLayout>

    MainActivity.class:

    package com.example.xch.broadcastpractice;
    
    import android.content.Intent;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends BaseActivity {
        private Button force_offline;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            force_offline=(Button) findViewById(R.id.force_offline);
            force_offline.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent=new Intent("com.example.FORCE_OFFLINE");//发送广播,在广播接收器里实现强制下线的逻辑
                    sendBroadcast(intent);
                }
            });
        }
    }

    这里很简单,就是在按钮事件里发送了一条广播,然后在广播接收器里实现强制下线的逻辑。接下来创建广播接收器ForceOfflineReceiver继承自Broadcast。

    package com.example.xch.broadcastpractice;
    
    import android.app.AlertDialog;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.view.WindowManager;
    
    /**
     * Created by xch on 2016/12/15.
     */
    
    public class ForceOfflineReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(final Context context, Intent intent) {
            //实现强制下线的逻辑
            AlertDialog.Builder dialogBuilder=new AlertDialog.Builder(context);//使用AlertDialog.Builder构建一个对话框
            dialogBuilder.setTitle("warning");
            dialogBuilder.setMessage("你已经被强制下线,请重新登录");
            dialogBuilder.setCancelable(false);//将对话框设置为不可取消
            dialogBuilder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    ActivityCollector.finishAll(); //销毁所有活动
                    Intent intent=new Intent(context,LoginActivity.class);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(intent); //重新启动登录界面
                }
            });
            AlertDialog alertDialog=dialogBuilder.create();
            //设置AlertDialog类型,保证在广播接收器中可以正常弹出
            alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
            alertDialog.show();
        }
    }

       这里要注意的是,由于我们是在广播中启动活动LoginActivity,因此一定要给Intent加上FLAG_ACTIVITY_NEW_TASK标志。最后还要把对话框的类型设置成TYPE_SYSTEM_ALERT,不然它将无法在广播接受器中弹出。

       接下来对AndroidManifest.xml进行配置:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.xch.broadcastpractice">
    
        <!-- To auto-complete the email text field in the login form with the user's emails -->
        <uses-permission android:name="android.permission.GET_ACCOUNTS" />
        <uses-permission android:name="android.permission.READ_PROFILE" />
        <uses-permission android:name="android.permission.READ_CONTACTS" />
    
        <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/AppTheme">
            <activity android:name=".LoginActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity android:name=".MainActivity"></activity>
            <receiver android:name=".ForceOfflineReceiver">
                <intent-filter>
                    <action android:name="com.example.FORCE_OFFLINE"/>
                </intent-filter>
            </receiver>
        </application>
    
    </manifest>

       由于我们在广播接收器里弹出了一个系统级别的对话框,因此要声明权限:android.permission.SYSTEM_ALERT_WINDOW,最后别忘了注册广播ForceOfflineReceiver和活动LoginActivity。

     运行程序,进入登录界面:

     成功登录之后进入程序主界面:

     点击强制下线按钮,就会发出一条强制下线的广播,广播接受器接收广播之后就会弹出提示框,用户点击确定之后就会重新回到登录界面:

     

     

  • 相关阅读:
    rest_framework 认证组件 权限组件
    Django rest_framework 序列化组件
    django 跨域问题
    python的magic methods
    RESTful规范
    BBS论坛 后台管理
    BBS论坛 文章详情、点赞、评论
    BBS论坛 home主页与个人站点主页
    好用的SqlParamterList
    教你如何在实战项目中使用WCF
  • 原文地址:https://www.cnblogs.com/xch-yang/p/6182848.html
Copyright © 2011-2022 走看看