Google 致力于为黑人社区推动种族平等。查看具体举措

Firebase Android Codelab - 建立友好的聊天

截屏

图片:工作友好的聊天应用程序。

欢迎来到友好聊天代码实验室。在此 Codelab 中,您将学习如何使用 Firebase 平台在 Android 上创建聊天应用。

你会学到什么

  • 如何使用 Firebase 身份验证来允许用户登录。
  • 如何使用 Firebase 实时数据库同步数据。
  • 如何在 Cloud Storage for Firebase 中存储二进制文件。
  • 如何使用 Firebase 本地模拟器套件通过 Firebase 开发 Android 应用。

你需要什么

  • Android Studio 4.2+ 版。
  • Android 5.0+ 的Android 模拟器
  • Java 7 或更高版本。要安装 Java,请使用这些说明;要检查您的版本,请运行java -version
  • 熟悉 Kotlin 编程语言。

克隆存储库

从命令行克隆 GitHub 存储库:

$ git clone https://github.com/firebase/codelab-friendlychat-android

导入到 Android Studio

在 Android Studio 中,选择File > Open ,然后选择build-android-start目录( android_studio_folder ) 来自您下载示例代码的目录。

您现在应该在 Android Studio 中打开build-android-start项目。如果您看到有关google-services.json文件丢失的警告,请不要担心。将在后面的步骤中添加。

检查依赖项

在此代码实验室中,您需要的所有依赖项都已为您添加,但了解如何将 Firebase SDK 添加到您的应用程序很重要:

构建.gradle

buildscript {
    // ...

    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.2'

        // The google-services plugin is required to parse the google-services.json file
        classpath 'com.google.gms:google-services:4.3.5'
    }
}

应用程序/build.gradle

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'com.google.gms.google-services'
}

android {
    // ...
}

dependencies {
    // ...

    // Google Sign In SDK
    implementation 'com.google.android.gms:play-services-auth:19.0.0'

    // Firebase SDK
    implementation platform('com.google.firebase:firebase-bom:26.6.0')
    implementation 'com.google.firebase:firebase-database-ktx'
    implementation 'com.google.firebase:firebase-storage-ktx'
    implementation 'com.google.firebase:firebase-auth-ktx'

    // Firebase UI Library
    implementation 'com.firebaseui:firebase-ui-auth:7.2.0'
    implementation 'com.firebaseui:firebase-ui-database:7.2.0'
}

为了运行Firebase Emulator Suite ,您需要安装并使用Firebase CLI

安装 CLI

选项 1 - 使用 npm 安装

如果您的机器上已经安装了 Node.js 和 npm,您可以使用以下命令安装 CLI:

npm install -g firebase-tools@latest

选项 2 - 安装独立二进制文件

如果您没有 Node.js/npm 或者您不熟悉应用程序开发,则可以按照此处针对您的平台说明将 CLI 安装为独立的二进制文件。

检查安装

安装 Firebase CLI 后,运行以下命令以确保您拥有9.11.0或更高版本:

firebase --version

启动模拟器

在终端中,从本地codelab-friendlychat-android目录的根目录运行以下命令:

firebase emulators:start --project=demo-friendlychat-android

您应该会看到一些这样的日志。端口值在firebase.json文件中定义,该文件包含在克隆的示例代码中。

$ firebase emulators:start --project=demo-friendlychat-android
i  emulators: Starting emulators: auth, database, storage
i  emulators: Detected demo project ID "demo-friendlychat-android", emulated services will use a demo configuration and attempts to access non-emulated services for this project will fail.
i  database: Database Emulator logging to database-debug.log
i  ui: Emulator UI logging to ui-debug.log

┌─────────────────────────────────────────────────────────────┐
│ ✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://localhost:4000                │
└─────────────────────────────────────────────────────────────┘

┌────────────────┬────────────────┬────────────────────────────────┐
│ Emulator       │ Host:Port      │ View in Emulator UI            │
├────────────────┼────────────────┼────────────────────────────────┤
│ Authentication │ localhost:9099 │ http://localhost:4000/auth     │
├────────────────┼────────────────┼────────────────────────────────┤
│ Database       │ localhost:9000 │ http://localhost:4000/database │
├────────────────┼────────────────┼────────────────────────────────┤
│ Storage        │ localhost:9199 │ http://localhost:4000/storage  │
└────────────────┴────────────────┴────────────────────────────────┘
  Emulator Hub running at localhost:4400
  Other reserved ports: 4500

Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.

在 Web 浏览器中导航到http://localhost:4000以查看 Firebase Emulator Suite UI:

模拟器套件 UI 主页

emulators:start命令在 Codelab 的其余部分运行。

连接您的应用

在 Android Studio 中,打开MainActivity.kt ,然后在onCreate方法中添加以下代码:

// When running in debug mode, connect to the Firebase Emulator Suite.
// "10.0.2.2" is a special IP address which allows the Android Emulator
// to connect to "localhost" on the host computer. The port values (9xxx)
// must match the values defined in the firebase.json file.
if (BuildConfig.DEBUG) {
    Firebase.database.useEmulator("10.0.2.2", 9000)
    Firebase.auth.useEmulator("10.0.2.2", 9099)
    Firebase.storage.useEmulator("10.0.2.2", 9199)
}

添加 google-services.json

为了让您的 Android 应用连接到 Firebase,您必须在 Android 项目的app文件夹中添加一个google-services.json文件。出于本 Codelab 的目的,我们提供了一个模拟 JSON 文件,可让您连接到 Firebase 模拟器套件。

mock-google-services.json文件作为google-services.json复制到build-android-start/app文件夹中:

cp mock-google-services.json build-android-start/app/google-services.json

在此 Codelab 的最后一步中,您将学习如何创建真正的 Firebase 项目和 Firebase Android 应用,以便您可以使用自己的配置替换此模拟 JSON 文件。

运行应用程序

现在您已将项目导入 Android Studio 并添加了 Firebase 配置 JSON 文件,您已准备好首次运行该应用程序。

  1. 启动你的安卓模拟器。
  2. 在 Android Studio 中,单击运行(执行 ) 在工具栏中。

该应用程序应在您的 Android 模拟器上启动。此时,您应该看到一个空的消息列表,并且无法发送和接收消息。在此代码实验室的下一步中,您将对用户进行身份验证,以便他们可以使用友好聊天。

此应用将使用 Firebase 实时数据库来存储所有聊天消息。但是,在我们添加数据之前,我们应该确保应用程序是安全的,并且只有经过身份验证的用户才能发布消息。在这一步中,我们将启用 Firebase 身份验证并配置实时数据库安全规则。

添加基本​​登录功能

接下来,我们将向应用添加一些基本的 Firebase 身份验证代码,以检测用户并实现登录屏幕。

检查当前用户

首先将以下实例变量添加到MainActivity.kt类:

主活动.kt

// Firebase instance variables
private lateinit var auth: FirebaseAuth

现在让我们修改MainActivity以在用户打开应用程序并且未经身份验证时将用户发送到登录屏幕。将binding附加到视图,将以下内容添加到onCreate()方法:

主活动.kt

// Initialize Firebase Auth and check if the user is signed in
auth = Firebase.auth
if (auth.currentUser == null) {
    // Not signed in, launch the Sign In activity
    startActivity(Intent(this, SignInActivity::class.java))
    finish()
    return
}

我们还想检查用户是否在onStart()期间登录:

主活动.kt

public override fun onStart() {
    super.onStart()
    // Check if user is signed in.
    if (auth.currentUser == null) {
        // Not signed in, launch the Sign In activity
        startActivity(Intent(this, SignInActivity::class.java))
        finish()
        return
    }
}

然后实现getUserPhotoUrl()getUserName()方法以返回有关当前经过身份验证的 Firebase 用户的适当信息:

主活动.kt

private fun getPhotoUrl(): String? {
    val user = auth.currentUser
    return user?.photoUrl?.toString()
}

private fun getUserName(): String? {
    val user = auth.currentUser
    return if (user != null) {
        user.displayName
    } else ANONYMOUS
}

然后实现signOut()方法来处理退出按钮:

主活动.kt

private fun signOut() {
    AuthUI.getInstance().signOut()
    startActivity(Intent(this, SignInActivity::class.java))
    finish()
}

现在,我们已具备在必要时将用户发送到登录屏幕的所有逻辑。接下来,我们需要实现登录屏幕以正确验证用户。

实现登录屏幕

打开文件SignInActivity.kt 。这里使用一个简单的登录按钮来启动身份验证。在本节中,您将使用 FirebaseUI 来实现登录逻辑。

SignInActivity类的// Firebase instance variables注释下添加一个 Auth 实例变量:

登录活动.kt

// Firebase instance variables
private lateinit var auth: FirebaseAuth

然后,编辑onCreate()方法以按照您在MainActivity所做的相同方式初始化 Firebase:

登录活动.kt

// Initialize FirebaseAuth
auth = Firebase.auth

ActivityResultLauncher字段添加到SignInActivity

登录活动.kt

// ADD THIS
private val signIn: ActivityResultLauncher<Intent> =
        registerForActivityResult(FirebaseAuthUIActivityResultContract(), this::onSignInResult)

override fun onCreate(savedInstanceState: Bundle?) {
    // ...
}

接下来,编辑onStart()方法以启动 FirebaseUI 登录流程:

登录活动.kt

public override fun onStart() {
    super.onStart()

    // If there is no signed in user, launch FirebaseUI
    // Otherwise head to MainActivity
    if (Firebase.auth.currentUser == null) {
        // Sign in with FirebaseUI, see docs for more details:
        // https://firebase.google.com/docs/auth/android/firebaseui
        val signInIntent = AuthUI.getInstance()
                .createSignInIntentBuilder()
                .setLogo(R.mipmap.ic_launcher)
                .setAvailableProviders(listOf(
                        AuthUI.IdpConfig.EmailBuilder().build(),
                        AuthUI.IdpConfig.GoogleBuilder().build(),
                ))
                .build()

        signIn.launch(signInIntent)
    } else {
        goToMainActivity()
    }
}

接下来,实现onSignInResult方法来处理登录结果。如果登录结果成功,继续MainActivity

登录活动.kt

private fun onSignInResult(result: FirebaseAuthUIAuthenticationResult) {
    if (result.resultCode == RESULT_OK) {
        Log.d(TAG, "Sign in successful!")
        goToMainActivity()
    } else {
        Toast.makeText(
                this,
                "There was an error signing in",
                Toast.LENGTH_LONG).show()

        val response = result.idpResponse
        if (response == null) {
            Log.w(TAG, "Sign in canceled")
        } else {
            Log.w(TAG, "Sign in error", response.error)
        }
    }
}

就是这样!您只需通过几个方法调用即可使用 FirebaseUI 实现身份验证,而无需管理任何服务器端配置。

测试你的工作

在您的 Android 模拟器上运行该应用程序。您应该立即被发送到登录屏幕。点击使用电子邮件登录按钮,然后创建一个帐户。如果一切都正确实施,您应该被发送到消息屏幕。

登录后,在浏览器中打开 Firebase Emulator Suite UI,然后单击Authentication选项卡以查看第一个登录的用户帐户。

在此步骤中,我们将添加读取和显示存储在实时数据库中的消息的功能。

导入示例消息

  1. 在 Firebase Emulator Suite UI 中,选择实时数据库选项卡。
  2. initial_messages.json文件从 codelab 存储库的本地副本拖放到数据查看器中。

您现在应该在数据库的messages节点下有一些消息。

读取数据

同步消息

在本节中,我们添加了通过以下方式将新添加的消息同步到应用程序 UI 的代码:

  • 初始化 Firebase 实时数据库并添加一个侦听器来处理对数据所做的更改。
  • 更新RecyclerView适配器以便显示新消息。
  • 将 Database 实例变量与MainActivity类中的其他 Firebase 实例变量一起添加:

主活动.kt

// Firebase instance variables
// ...
private lateinit var db: FirebaseDatabase
private lateinit var adapter: FriendlyMessageAdapter

在注释// Initialize Realtime Database and FirebaseRecyclerAdapter使用下面定义的代码修改 MainActivity 的onCreate()方法。此代码添加来自实时数据库的所有现有消息,然后侦听 Firebase 实时数据库中messages路径下的新子条目。它为每条消息向 UI 添加一个新元素:

主活动.kt

// Initialize Realtime Database
db = Firebase.database
val messagesRef = db.reference.child(MESSAGES_CHILD)

// The FirebaseRecyclerAdapter class and options come from the FirebaseUI library
// See: https://github.com/firebase/FirebaseUI-Android
val options = FirebaseRecyclerOptions.Builder<FriendlyMessage>()
    .setQuery(messagesRef, FriendlyMessage::class.java)
    .build()
adapter = FriendlyMessageAdapter(options, getUserName())
binding.progressBar.visibility = ProgressBar.INVISIBLE
manager = LinearLayoutManager(this)
manager.stackFromEnd = true
binding.messageRecyclerView.layoutManager = manager
binding.messageRecyclerView.adapter = adapter

// Scroll down when a new message arrives
// See MyScrollToBottomObserver for details
adapter.registerAdapterDataObserver(
    MyScrollToBottomObserver(binding.messageRecyclerView, adapter, manager)
)

接下来在FriendlyMessageAdapter.kt类中实现内部类MessageViewHolder()bind()方法:

友好消息适配器.kt

inner class MessageViewHolder(private val binding: MessageBinding) : ViewHolder(binding.root) {
    fun bind(item: FriendlyMessage) {
        binding.messageTextView.text = item.text
        setTextColor(item.name, binding.messageTextView)

        binding.messengerTextView.text = if (item.name == null) ANONYMOUS else item.name
        if (item.photoUrl != null) {
            loadImageIntoView(binding.messengerImageView, item.photoUrl!!)
        } else {
            binding.messengerImageView.setImageResource(R.drawable.ic_account_circle_black_36dp)
        }
    }
    ...
}

我们还需要显示图像消息,因此还要在内部类ImageMessageViewHolder()实现bind()方法:

友好消息适配器.kt

inner class ImageMessageViewHolder(private val binding: ImageMessageBinding) :
    ViewHolder(binding.root) {
    fun bind(item: FriendlyMessage) {
        loadImageIntoView(binding.messageImageView, item.imageUrl!!)

        binding.messengerTextView.text = if (item.name == null) ANONYMOUS else item.name
        if (item.photoUrl != null) {
            loadImageIntoView(binding.messengerImageView, item.photoUrl!!)
        } else {
            binding.messengerImageView.setImageResource(R.drawable.ic_account_circle_black_36dp)
        }
    }
}

最后,回到MainActivity ,开始和停止监听来自 Firebase 实时数据库的更新。更新MainActivityonPause()onResume()方法,如下所示:

主活动.kt

public override fun onPause() {
    adapter.stopListening()
    super.onPause()
}

public override fun onResume() {
    super.onResume()
    adapter.startListening()
}

测试同步消息

  1. 单击运行(执行 )。
  2. 在 Emulator Suite UI 中,返回到Realtime Database选项卡,然后手动添加新消息。确认消息显示在您的 Android 应用中:

恭喜,您刚刚为您的应用添加了一个实时数据库!

实现短信发送

在本节中,您将添加应用程序用户发送文本消息的功能。下面的代码片段侦听发送按钮上的单击事件,使用消息字段的内容创建一个新的FriendlyMessage对象,并将消息推送到数据库。 push()方法将自动生成的 ID 添加到推送对象的路径中。这些 ID 是连续的,以确保将新消息添加到列表的末尾。

更新MainActivity类的onCreate()方法中发送按钮的点击监听器。此代码已位于onCreate()方法的底部。更新onClick()主体以匹配以下代码:

主活动.kt

// Disable the send button when there's no text in the input field
// See MyButtonObserver for details
binding.messageEditText.addTextChangedListener(MyButtonObserver(binding.sendButton))

// When the send button is clicked, send a text message
binding.sendButton.setOnClickListener {
    val friendlyMessage = FriendlyMessage(
        binding.messageEditText.text.toString(),
        getUserName(),
        getPhotoUrl(),
        null /* no image */
    )
    db.reference.child(MESSAGES_CHILD).push().setValue(friendlyMessage)
    binding.messageEditText.setText("")
}

实现图片消息发送

在本节中,您将添加应用程序用户发送图像消息的功能。通过以下步骤创建图像消息:

  • 选择图片
  • 处理图像选择
  • 将临时图像消息写入实时数据库
  • 开始上传所选图片
  • 上传完成后,将图片消息 URL 更新为上传图片的 URL

选择图像

为了添加图像,此代码实验室使用 Cloud Storage for Firebase。 Cloud Storage 是存储应用程序二进制数据的好地方。

处理图像选择和写入临时消息

一旦用户选择了图像,就会启动图像选择Intent 。这已经在onCreate()方法末尾的代码中实现了。完成后,它调用MainActivityonImageSelected()方法。使用下面的代码片段,您将向数据库写入一条带有临时图像 url 的消息,指示正在上传图像。

主活动.kt

private fun onImageSelected(uri: Uri) {
    Log.d(TAG, "Uri: $uri")
    val user = auth.currentUser
    val tempMessage = FriendlyMessage(null, getUserName(), getPhotoUrl(), LOADING_IMAGE_URL)
    db.reference
            .child(MESSAGES_CHILD)
            .push()
            .setValue(
                    tempMessage,
                    DatabaseReference.CompletionListener { databaseError, databaseReference ->
                        if (databaseError != null) {
                            Log.w(
                                    TAG, "Unable to write message to database.",
                                    databaseError.toException()
                            )
                            return@CompletionListener
                        }

                        // Build a StorageReference and then upload the file
                        val key = databaseReference.key
                        val storageReference = Firebase.storage
                                .getReference(user!!.uid)
                                .child(key!!)
                                .child(uri.lastPathSegment!!)
                        putImageInStorage(storageReference, uri, key)
                    })
}

上传图片和更新消息

将方法putImageInStorage()添加到MainActivity 。在onImageSelected()调用它以启动所选图像的上传。上传完成后,您将更新消息以使用适当的图像。

主活动.kt

private fun putImageInStorage(storageReference: StorageReference, uri: Uri, key: String?) {
    // First upload the image to Cloud Storage
    storageReference.putFile(uri)
        .addOnSuccessListener(
            this
        ) { taskSnapshot -> // After the image loads, get a public downloadUrl for the image
            // and add it to the message.
            taskSnapshot.metadata!!.reference!!.downloadUrl
                .addOnSuccessListener { uri ->
                    val friendlyMessage =
                        FriendlyMessage(null, getUserName(), getPhotoUrl(), uri.toString())
                    db.reference
                        .child(MESSAGES_CHILD)
                        .child(key!!)
                        .setValue(friendlyMessage)
                }
        }
        .addOnFailureListener(this) { e ->
            Log.w(
                TAG,
                "Image upload task was unsuccessful.",
                e
            )
        }
}

测试发送消息

  1. 在 Android Studio 中,单击执行运行按钮。
  2. 在您的 Android 模拟器中,输入一条消息,然后点击发送按钮。新消息应该在应用 UI 和 Firebase Emulator Suite UI 中可见。
  3. 在 Android 模拟器中,点击“+”图像以从您的设备中选择图像。新消息应首先显示为占位符图像,然后在图像上传完成后显示为所选图像。新消息也应该在 Emulator Suite UI 中可见,特别是作为实时数据库选项卡中的对象和存储选项卡中的 blob。

您刚刚使用 Firebase 构建了一个实时聊天应用程序!

你学到了什么

  • Firebase 身份验证
  • Firebase 实时数据库
  • Firebase 云存储

接下来,尝试使用您在此 Codelab 中学到的知识将 Firebase 添加到您自己的 Android 应用中!要了解有关 Firebase 的更多信息,请访问firebase.google.com

如果您想了解如何设置真实的Firebase 项目并使用真实的Firebase 资源(而不是演示项目和模拟资源),请继续下一步。

注意:即使在您设置了真正的 Firebase 项目之后,尤其是当您开始构建真正的应用程序时,我们仍建议您使用 Firebase 本地模拟器套件进行开发和测试。

在此步骤中,您将创建一个真实的 Firebase 项目和一个 Firebase Android 应用以用于此 Codelab。您还将向您的应用添加特定于应用的 Firebase 配置。最后,您将设置真实的 Firebase 资源以与您的应用一起使用。

创建 Firebase 项目

  1. 在浏览器中,转到Firebase 控制台
  2. 选择添加项目
  3. 选择或输入项目名称。您可以使用任何您想要的名称。
  4. 您不需要为此 Codelab 使用 Google Analytics,因此您可以跳过为您的项目启用它。
  5. 单击创建项目。当您的项目准备好后,点击Continue

将 Firebase 添加到您的 Android 项目

在开始此步骤之前,请获取应用的 SHA1 哈希值。从本地build-android-start目录运行以下命令以确定调试密钥的 SHA1:

./gradlew signingReport

Store: /Users/<username>/.android/debug.keystore
Alias: AndroidDebugKey
MD5: A5:88:41:04:8F:06:59:6A:AE:33:76:87:AA:AD:19:23
SHA1: A7:89:F5:06:A8:07:A1:22:EC:90:6A:A6:EA:C3:D4:8B:3A:30:AB:18
SHA-256: 05:A2:2A:35:EE:F2:51:23:72:4D:72:67:A5:6A:8A:58:22:2C:00:A6:AB:F6:45:D5:A1:82:D8:90:A4:69:C8:FE
Valid until: Wednesday, August 10, 2044

您应该会看到一些类似上面的输出。重要的一行是SHA1哈希。如果您找不到您的 SHA1 哈希,请参阅此页面了解更多信息。

返回 Firebase 控制台,并按照以下步骤将您的 Android 项目注册到您的 Firebase 项目:

  1. 在新项目的概览屏幕中,单击 Android 图标以启动设置工作流程:添加安卓应用
  2. 在下一个屏幕上,输入com.google.firebase.codelab.friendlychat作为您的应用程序的包名称。
  3. 点击Register App ,然后点击Download google-services.json以下载您的 Firebase 配置文件。
  4. google-services.json文件复制到您的 Android 项目的app目录中。
  5. 跳过控制台设置工作流程中显示的后续步骤(它们已在build-android-start项目中为您完成)。
  6. 通过将您的项目与 Gradle 文件同步,确保您的应用程序可以使用所有依赖项。从 Android Studio 工具栏中,选择File > Sync Project with Gradle Files

配置 Firebase 身份验证

在您的应用可以代表您的用户访问 Firebase 身份验证 API 之前,您需要启用 Firebase 身份验证以及要在应用中使用的登录提供程序。

  1. Firebase 控制台中,从左侧导航面板中选择身份验证
  2. 选择登录方法选项卡。
  3. 点击电子邮件/密码,然后将开关切换到启用(蓝色)。
  4. 点击Google ,然后将开关切换到启用(蓝色)并设置项目支持电子邮件。

如果您稍后在此 Codelab 中收到错误消息“CONFIGURATION_NOT_FOUND”,请返回此步骤并仔细检查您的工作。

配置实时数据库

此 Codelab 中的应用将聊天消息存储在 Firebase 实时数据库中。在本节中,我们将创建一个数据库并通过称为 Firebase 安全规则的 JSON 配置语言配置其安全性。

  1. Firebase 控制台中,从左侧导航面板中选择实时数据库
  2. 单击创建数据库以创建新的实时数据库实例。出现提示时,选择us-central1区域,然后单击Next
  3. 当提示有关安全规则时,选择锁定模式,然后单击启用
  4. 创建数据库实例后,选择规则选项卡,然后使用以下内容更新规则配置:
     {
       "rules": {
         "messages": {
           ".read": "auth.uid != null",
           ".write": "auth.uid != null"
         }
       }
     }
    

有关安全规则如何工作的更多信息(包括有关“auth”变量的文档),请参阅实时数据库安全文档

为 Firebase 配置 Cloud Storage

  1. Firebase 控制台中,从左侧导航面板中选择存储
  2. 单击开始为您的项目启用 Cloud Storage。
  3. 按照对话框中的步骤使用建议的默认值设置您的存储桶。

连接到 Firebase 资源

在本 Codelab 的前面步骤中,您将以下内容添加到MainActivity.kt 。此条件块将您的 Android 项目连接到 Firebase Emulator Suite。

// REMOVE OR DISABLE THIS
if (BuildConfig.DEBUG) {
    Firebase.database.useEmulator("10.0.2.2", 9000)
    Firebase.auth.useEmulator("10.0.2.2", 9099)
    Firebase.storage.useEmulator("10.0.2.2", 9199)
}

如果您想将您的应用连接到新的真实Firebase 项目及其真实的Firebase 资源,您可以删除此块或以发布模式运行您的应用,以便BuildConfig.DEBUGfalse