用户注册和登录

更新时间:2024-01-10 08:38:15下载pdf

本文介绍启动页、用户注册和用户登录。

启动页

判断用户是否已经登录。

  • 如果用户已经登录,进入 App 首页。
  • 如果用户没有登录,则跳转到登录注册页面。
  1. 单击右键,新增一个 Activity 页面,选择 Empty Activity,Activity 名称设置为 SplashActivity,在 /app/src/main/res/layout/activity_splash.xml 替换 UI 代码。

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
    
    <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textSize="20dp"
       android:layout_marginTop="50dp"
       android:layout_marginLeft="20dp"
       android:text="@string/user_guide_title" />
    
    <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical"
       android:paddingLeft="20dp"
       android:paddingRight="20dp"
       android:layout_gravity="bottom"
       android:layout_marginBottom="40dp"
       android:paddingBottom="20dp">
    
       <Button
           android:id="@+id/btnLogin"
           android:layout_width="match_parent"
           android:layout_height="48dp"
           android:text="@string/user_login" />
    
       <Button
           android:id="@+id/btnRegister"
           android:layout_width="match_parent"
           android:layout_height="48dp"
           android:text="@string/user_register" />
    </LinearLayout>
    </FrameLayout>
    
  2. SplashActivity.kt 文件替换成如下代码:

    class SplashActivity : AppCompatActivity(), View.OnClickListener {
     override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
    
       // If login, then navigate to MainSampleList
       if (ThingHomeSdk.getUserInstance().isLogin) {
           startActivity(Intent(this, MainActivity::class.java))
           finish()
       }
       setContentView(R.layout.activity_splash)
    
       findViewById<Button>(R.id.btnRegister).setOnClickListener(this)
       findViewById<Button>(R.id.btnLogin).setOnClickListener(this)
    
    }
    
    override fun onClick(v: View?) {
       v?.id?.let {
           if (it == R.id.btnRegister) {
               // Register
               startActivity(Intent(this, UserRegisterActivity::class.java))
           } else if (it == R.id.btnLogin) {
               // Login
               startActivity(Intent(this, UserLoginActivity::class.java))
           }
       }
    }
    }
    
  3. /app/src/main/AndroidManifest.xml 文件中,设置 SplashActivity 未启动页面,AndroidManifest.xml 示例代码:

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:name=".BaseApplication"
        android:theme="@style/Theme.MaterialComponents.Light.NoActionBar"
        tools:replace="android:allowBackup,android:supportsRtl">
        <activity
            android:name=".MainActivity"
            android:exported="false"
            android:screenOrientation="portrait" />
        <activity
            android:name=".SplashActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".UserRegisterActivity"
            android:exported="false"
            android:screenOrientation="portrait" />
        <activity
            android:name=".UserLoginActivity"
            android:exported="false"
            android:screenOrientation="portrait" />
    
    </application>
    

用户注册

  1. 新建 Activity,名称为 UserRegisterActivity,用户注册 UI 示例代码:

     <?xml version="1.0" encoding="utf-8"?>
    <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <com.google.android.material.appbar.MaterialToolbar
            android:id="@+id/topAppBar"
            style="@style/Widget.MaterialComponents.Toolbar.Primary"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:navigationIcon="?attr/homeAsUpIndicator"
            app:title="@string/user_register" />
    
    </com.google.android.material.appbar.AppBarLayout>
    
    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="20dp"
            android:paddingRight="20dp"
            android:paddingBottom="20dp">
    
            <com.google.android.material.textfield.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_marginTop="20dp"
                android:hint="@string/user_country_code"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent">
    
                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/etCountryCode"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />
            </com.google.android.material.textfield.TextInputLayout>
    
            <com.google.android.material.textfield.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:hint="@string/user_account_tips"
                app:endIconMode="clear_text"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent">
    
                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/etAccount"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />
            </com.google.android.material.textfield.TextInputLayout>
    
            <com.google.android.material.textfield.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:hint="@string/user_password"
                app:endIconMode="clear_text"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent">
    
                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/etPassword"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />
            </com.google.android.material.textfield.TextInputLayout>
    
            <com.google.android.material.textfield.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:hint="@string/user_verification_code"
                app:endIconMode="clear_text"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent">
    
                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/etCode"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />
            </com.google.android.material.textfield.TextInputLayout>
    
            <Button
                android:id="@+id/btnCode"
                android:layout_width="match_parent"
                android:layout_height="48dp"
                android:text="@string/user_send_code" />
    
            <Button
                android:id="@+id/btnRegister"
                android:layout_width="match_parent"
                android:layout_height="48dp"
                android:text="@string/user_register" />
        </LinearLayout>
    
    </androidx.core.widget.NestedScrollView>
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    
  2. 用户注册逻辑实现。

    在账号注册登录方法中,您需要提供 countryCode 参数,即国家区号,用于就近选择涂鸦 IoT 开发平台的可用区。用户注册可以使用邮箱和手机号两种方式。

    如果您想为 App 启用手机号码验证服务,那您需要开通和配置 手机号码短信验证服务。该服务让您的 App 用户可以通过手机号码直接注册账号或绑定已有的 App 账号,并可以直接通过手机号码完成登录 App、找回密码等操作。详细操作说明,参考 开通和配置手机号码短信验证服务

    用户注册示例代码:

    class UserRegisterActivity : AppCompatActivity(), View.OnClickListener {
    private val check =
        "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"
    private val regex: Pattern = Pattern.compile(check)
    private val mRegisterType = 1
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.user_activity_register)
    
        val toolbar: Toolbar = findViewById<View>(R.id.topAppBar) as Toolbar
        toolbar.setNavigationOnClickListener {
            finish()
        }
    
        findViewById<Button>(R.id.btnRegister).setOnClickListener(this)
        findViewById<Button>(R.id.btnCode).setOnClickListener(this)
    }
    
    override fun onClick(v: View?) {
        val strAccount = findViewById<EditText>(R.id.etAccount).text.toString()
        val strCountryCode = findViewById<EditText>(R.id.etCountryCode).text.toString()
        val strPassword = findViewById<EditText>(R.id.etPassword).text.toString()
        val strCode = findViewById<EditText>(R.id.etCode).text.toString()
    
        val matcher: Matcher = regex.matcher(strAccount)
        val isEmail: Boolean = matcher.matches()
    
        v?.id?.let {
            if (it == R.id.btnRegister) {
                val callback = object : IRegisterCallback {
                    override fun onSuccess(user: User?) {
                        Toast.makeText(
                            this@UserRegisterActivity,
                            "Register success",
                            Toast.LENGTH_LONG
                        ).show()
                    }
    
                    override fun onError(code: String?, error: String?) {
                        Toast.makeText(
                            this@UserRegisterActivity,
                            "Register error->$error",
                            Toast.LENGTH_LONG
                        ).show()
                    }
                }
    
                if (isEmail) {
                    // Register by email
                    ThingHomeSdk.getUserInstance().registerAccountWithEmail(
                        strCountryCode,
                        strAccount,
                        strPassword,
                        strCode,
                        callback
                    )
                } else {
                    // Register by phone
                    ThingHomeSdk.getUserInstance().registerAccountWithPhone(
                        strCountryCode,
                        strAccount,
                        strPassword,
                        strCode,
                        callback
                    )
                }
    
            } else if (it == R.id.btnCode) {
                // Get verification code code
                ThingHomeSdk.getUserInstance().sendVerifyCodeWithUserName(
                    strAccount,
                    "",
                    strCountryCode,
                    mRegisterType,
                    object : IResultCallback {
                        override fun onSuccess() {
                            Toast.makeText(
                                this@UserRegisterActivity,
                                "Got validateCode",
                                Toast.LENGTH_LONG
                            ).show()
                        }
    
                        override fun onError(code: String?, error: String?) {
                            Toast.makeText(
                                this@UserRegisterActivity,
                                "getValidateCode error->$error",
                                Toast.LENGTH_LONG
                            ).show()
                        }
    
                    })
            }
        }
      }
    }
    

    效果展示:

    用户注册和登录

用户登录

  1. 新建 Activity,名称为 UserLoginActivity

     <?xml version="1.0" encoding="utf-8"?>
     <androidx.coordinatorlayout.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:app="http://schemas.android.com/apk/res-auto"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
    
    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <com.google.android.material.appbar.MaterialToolbar
            android:id="@+id/topAppBar"
            style="@style/Widget.MaterialComponents.Toolbar.Primary"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:navigationIcon="?attr/homeAsUpIndicator"
            app:title="@string/user_login" />
    
    </com.google.android.material.appbar.AppBarLayout>
    
    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="20dp">
    
            <com.google.android.material.textfield.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:layout_marginTop="20dp"
                android:hint="@string/user_country_code"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent">
    
                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/etCountryCode"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />
            </com.google.android.material.textfield.TextInputLayout>
    
            <com.google.android.material.textfield.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:hint="@string/user_account_tips"
                app:endIconMode="clear_text"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent">
    
                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/etAccount"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />
            </com.google.android.material.textfield.TextInputLayout>
    
            <com.google.android.material.textfield.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:hint="@string/user_password"
                app:endIconMode="clear_text"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent">
    
                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/etPassword"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />
            </com.google.android.material.textfield.TextInputLayout>
    
            <Button
                android:id="@+id/btnLogin"
                android:layout_width="match_parent"
                android:layout_height="48dp"
                android:layout_marginTop="10dp"
                android:text="@string/user_login" />
        </LinearLayout>
    
    </androidx.core.widget.NestedScrollView>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    
    
  2. 上一步注册成功后,返回启动页进入登录页。用户登录功能逻辑实现如下:

    class UserLoginActivity : AppCompatActivity(), View.OnClickListener {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.user_activity_login)
    
        val toolbar: Toolbar = findViewById<View>(R.id.topAppBar) as Toolbar
        toolbar.setNavigationOnClickListener {
            finish()
        }
    
        findViewById<Button>(R.id.btnLogin).setOnClickListener(this)
    }
    
    override fun onClick(v: View?) {
        val strAccount = findViewById<EditText>(R.id.etAccount).text.toString()
        val strCountryCode = findViewById<EditText>(R.id.etCountryCode).text.toString()
        val strPassword = findViewById<EditText>(R.id.etPassword).text.toString()
    
        v?.id?.let {
            if (it == R.id.btnLogin) {
                // Login with phone
              val callback =  object : ILoginCallback {
                    override fun onSuccess(user: User?) {
                        Toast.makeText(
                            this@UserLoginActivity,
                            "Login success",
                            Toast.LENGTH_LONG
                        ).show()
    
                        startActivity(
                            Intent(
                                this@UserLoginActivity,
                                MainActivity::class.java
                            )
                        )
                    }
    
                    override fun onError(code: String?, error: String?) {
                        Toast.makeText(
                            this@UserLoginActivity,
                            "login error->$error",
                            Toast.LENGTH_LONG
                        ).show()
                    }
                }
                if (ValidatorUtil.isEmail(strAccount)) {
                    ThingHomeSdk.getUserInstance()
                        .loginWithEmail(strCountryCode, strAccount, strPassword, callback)
                } else {
                    ThingHomeSdk.getUserInstance()
                        .loginWithPhonePassword(strCountryCode, strAccount, strPassword, callback)
                }
            }
        }
     }
    }
    

    效果展示:

    用户注册和登录