One, foreword

Recently a project into the end of the first stage, although the login function basically has completed development, but is a mess, such as QQ login third-party login has its own cache mechanism, local account password is a way, email login phone number is another way, finally after several hours of logical deduction, For the first time, I completed the development of this login system without running the code, and finally succeeded in running it. I modified the situation that there was no initialization, and there were some minor episodes in the process. Finally, I completed the development of this system.

Ii. Flow chart

This flow chart contains the whole process of login system design, which is also the step by step process of simulation at that time

Briefly comb through the login process with words

  1. First enter the program, need to determine whether the login cache exists and is valid, if yes, directly jump MainActivity, otherwise jump LoginActivity
  2. After entering the LoginActivity, various forms of caching are performed. Here, the caching is processed in its own part, and finally the Json data is cached in a uniform form. However, it is important to ensure that this work is done when entering the MainActivity, because these credentials will be used later
  3. Then you can carry some data or perform some animation before jumping to MainActivity
  4. If you log in to MainActivity for the first time, you need to set the login credentials for the global application and read the login credentials for subsequent logins at the start of the startup
  5. After logging out, clear the cache, including the login cache, and other temporarily saved JSON data, such as personal information, when exiting the application
  6. Regarding the validity of cache, third-party login like QQ has its own special verification mechanism. I only did the time verification for unified login and email login, and I can also consider setting a self-defined verification mechanism. Finally, as long as the form of login credentials is unified, it is ok

Here, the startup interface is presented in Lottie View instead of slash Screen. The main reason is to make the animation cool. Then, BootActivity is also created to process the startup logic. Hit a pit (more on that later)

Three, the main design part analysis

Due to personal development restrictions, the following login methods to QQ, mailbox, unified account login as an example

1. Login cache design

The unified login behavior is at the heart of the system design, so the design of this section is based on the principles of simplicity and information minimization. The following four fields are sufficient and can be extended

This field can be the openId of the third party or any other data, as long as the data is unique
// Expiration time This can be set. The login method is related to the program startup and unified account generation
data class LoginInfo(var id:String = "".var expireTime:Long = 0.var loginWay:String = "".var loginToken:String = "")
Copy the code

Design such a unified cache bean, and then use MMKV to store the relevant JSON data with key values. Here, Gson is simply encapsulated and Kotlin’s extension function is used to complete the conversion between JSON and objects. For details, please refer to this article: JSON-to-object conversion Encapsulation (Gson)

// string.tomyObject <>() is converted to an object
// any.tomyjson () is a wrapper to convert to JSON data

val kv = MMKV.defaultMMKV()
val loginInfo = LoginInfo(...)
kv.encode("login_info",loginInfo.toMyJson())
Copy the code

This section completes the caching operation after successful login through various channels

2. Data communication design

The login cache

This is very important, design cache is often convenient for each activity to communicate, before the activity is the way of value transmission, each transfer to write a code, but also prone to error, considering the login part of the cache has a strong reuse, So this part needs to be placed in the global application and then called directly to the Application when needed. Therefore, the login cache is the data stored for a long time. Set the cache related to application after the successful login, and also consider the operations after the first login or logout

companion object{
    @SuppressLint("StaticFieldLeak").lateinit var login_info:LoginInfo
    ...
}

override fun onCreate(a) {
    super.onCreate()
    ...
    login_info = if (MMKV.defaultMMKV().containsKey("login_info")) {// it can be read without null
        login_info = MMKV.defaultMMKV().decodeString("login_info").toMyObject<LoginInfo>()[0]}else{
        // If the object is not initialized, an error is reported
        login_info = LoginInfo()
    }
    ...
}
Copy the code

The derived cache for the LOGIN section

This part needs to be operated in the MainActivity to ensure that there is a cache of the login part, which can be carried out according to their own needs. My approach is to return to the login interface once failure, of course, no network or weak network will trigger this, this is their own personalized choice. At present, my own project can hardly complete any operation without network, so I choose this method. The derived cache can also be persisted as needed or stored only in memory. I’m doing the same thing here as I did with the Login part, except that it is destroyed every time you exit the application (mainly for information security). The Login part is not destroyed

For example, to obtain personal information of this QQ, qqToken is required, that is, accessToken in previous login credentials

private fun getQQInfo(a){
    val qqToken = mTencent.qqToken
    val info = UserInfo(Application.context,qqToken)
    info.getUserInfo(object : DefaultUiListener(mTencent){
        override  fun onComplete(response: Any?).{
            kv.encode("qq_info",response.toString())
        }
    })
}
Copy the code

When you exit MainActivity, you can remove this part of the cache. If you have some immutable data, you can consider persistence. Here kv is used for convenience, it can communicate globally, and global application is also ok, the effect is the same

kv.remove("qq_info")
Copy the code

3. Data exception processing

Some potholes about BootActivity

Here mainly consider a scenario, when the user waiting to start the animation, due to the accident to switch to the background, then enter again, because the animation is a conditional jump, or jump logic has not been processed, lead to quit after the animation has been in circulation (jump this part be skipped), the solution is to adjust the position of the logical processing If onPause is started and the onStart part of the login is valid, jump to MainActivity directly, omit the animation (actually can also record the time to give the best experience). If not, restart the onStart logic. Some simple logical judgments

private var loginValid = false
private var onPause = false.override fun onCreate(savedInstanceState: Bundle?). {
    super.onCreate(savedInstanceState)
    ...
    // Here onCreate recommends doing some lightweight tasks, otherwise this situation is likely to happen again
}
override fun onStart(a) {
    super.onStart()
    if(! onPause){// Jump logic
        // If the login is valid in the jump logic
        //loginValid = true
        // Otherwise, no processing
    }else{
        // The startActivity here refers to the overloaded function in the first line of Guo God's code
        startActivity<MainActivity>(Application.context){}
    }
}

override fun onPause(a) {
    super.onPause()
    if (loginValid){
        onPause = true}}Copy the code

Some login cache data is damaged

The processing of this part is relatively simple, possibly due to the MMKV cache error (I heard that this probability is extremely low, but just in case), once the data cannot be found in a certain request, for example, you can destroy the key and jump to the login interface to log in again

// The reason for destroying all keys is that if the most important key in the login_info section is broken, you must log out
kv.clearAll()
startActivity<LoginActivity>(context){}
finish()
Copy the code

If you fail to obtain other data that depends on login_INFO, the fault may be caused by the server or MMKV. In this case, you are advised to login again

val retry = 0
// Network request.if(retry > 5){
    kv.clearAll()
    startActivity<LoginActivity>(context){}
    finish()
}
Copy the code

The most important part of this section is the login_info key. If this data is corrupted, you can only login again

4. The activities involved and their respective tasks

  • BootActivity is responsible for the jump processing of the next entry and initialization of the first entry. At the same time, some animations can be played, such as Lottie View. For details, see the use of the official website

     <com.airbnb.lottie.LottieAnimationView
                android:id="@+id/animation_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:lottie_autoPlay="true"
                app:lottie_fileName="boot.json"
                app:lottie_loop="true" />
    Copy the code
  • The LoginActivity handles entry processing for various login paths, not specific login logic

    class LoginActivity :BaseActivity<ActivityLoginBinding>(ActivityLoginBinding::inflate) {
        ...
        override fun onCreate(savedInstanceState: Bundle?). {
            super.onCreate(savedInstanceState)
            ...
            viewBinding.qqLogin.setOnClickListener {
                ...
                // Qqlogin part processing. } viewBinding.mailLogin.setOnClickListener { ... startActivity<MyLoginActivity>(FundTestApplication.context){ putExtra("way"."mailLogin")}... } viewBinding.passwordLogin.setOnClickListener { ... startActivity<MyLoginActivity>(FundTestApplication.context){ putExtra("way"."passwordLogin")}... }}}Copy the code
  • MyLoginActivity handles the specific logic

    • QQ here uses UIListener for processing, at the same time the SDK built-in activity to complete the login logic processing

    • Mailbox and unified account login Two tasks need to be completed for this activity to process

      • Validation of local data (reduces the burden on the server)

      • Send the local account password/email verification code for server authentication

Four, three login methods specific design

1. Third-party login design

Here to QQ for example, interested friends can refer to the QQ login integration written last time

Generally, third-party platforms such as QQ will generate their own credentials after login and extract useful information as the cached login credentials, such as the unique openId, Access Token and expiration time. Other information can be extracted by themselves if necessary. These three are the most basic. AccessToken ensures the accuracy of the data. QQ platform has a corresponding mechanism to verify whether the login is valid, so we do not need to verify the processing.

Set third-party login credentials

This section begins after a successful login

val qqLogin = loginData.toMyObject<QQLogin>()

// First set the credentials required for QQ login
mTencent.setAccessToken(qqLogin.access_token, qqLogin.expires_in.toString())
mTencent.openId = qqLogin.openid
Copy the code

Set the cached login credentials

val loginInfo = LoginInfo(qqLogin.openid,qqLogin.expires_time,"qq",qqLogin.access_token)
kv.encode("login_info",loginInfo.toMyJson())
Copy the code

When you log in for the first time, you need to set it to the global application

Application.login_info = loginInfo
Copy the code

2. Verify login

First of all, the security factor of verifying login is actually quite high. At present, the mainstream method is to add whether it is a robot test. This part has not been done for the time being, but only the verification of verification code

  • Several common forms

    Currently, individual developers can only use email to send verification codes, while mobile phone numbers require enterprise users to send SMS messages

  • Verification code generation

    Here we just use random number method to generate 6 digits, but this is the job of the server side

  • Generation of additional fields in unified login credentials

    val loginInfo = LoginInfo(mail,expires_time,"mail"."")
    The id field uses the login mailbox as the unique ID
    
    // Expiration time Here the cache time + the current time to generate the expiration timestamp, here the cache for a month
    // Compare the current time with the expiration time
    val expireTime = 30*86400*1000L + System.currentTimeMillis()
    
    // Log in via mail
    
    //accessToken null if there is no design
    Copy the code

3. Log in using a unified account

The need for each of the third party to process the account login or verify logged in, here refer to CSDN id name, way of + 8 digits unique id, this id account password can be done, so there is no design account registration system, mainly considering the most registered also need email phone number verification, There are also a lot of platforms do not have their own account registration system, but they can give their own to create some test accounts for easy login

  • Unified Account Design

    Here, the login method + 8-bit pure digits constitute a unified ID, which is repeated for re-generation

    fun uid(platform:String):String{
        return "${platform}_${(Random().nextInt(99999999 - 10000000 + 1) +10000000)}"
    }
    
    / / such as qq_36725737
    // Indicates the login from qq platform
    Copy the code
  • Login credentials Settings

    In this case, the id can be replaced with the unified account, which is unique, and there is no need to worry about duplication. The expiration time refers to the authentication login, the way is set to password, accessToken is also used to authenticate login, and if the password is used to log in, there is no need to register

  • Then it provides the option to forget the password, directly guides the user to the mailbox login prompt, and then enters the main interface to set the password, after all, the reset password still needs the verification code

Five, the summary

The design of the login process benefits a lot. The unified login behavior is the most core part of the design, which can be extended and easy to manage. However, there are still some shortcomings, such as the consideration and design of remote login and the design of anti-robot

6. Application interface

At present, the app developed by using this login system has been online in Google App Store. You can search VFund, which is the first application on the shelves. Welcome to come and experience

Partial Interface display

// Alternate download link
https:/ / res. Dreamstudio. Online/apk/VFund1.2.2 apk
Copy the code