#kotlin #chatbot
Вопрос:
Я следил за видео о том, как создать чат-бота в Android studio kotlin. Вот ссылка: https://www.youtube.com/watch?v=4Cg1EuCQxQ4amp;t=601s
Я следил за всем, и в коде не было ошибок. Хотя я не уверен, правильно ли я это сделал, потому что я сделал это внутри фрагмента. Вот весь код для чат-бота:
//ForumFragment.kt
package ui
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.bylaws.R
import kotlinx.android.synthetic.main.fragment_forum.*
import kotlinx.coroutines.*
import ui.data.Message
import utils.BotResponse
import utils.Constants.OPEN_GOOGLE
import utils.Constants.OPEN_SEARCH
import utils.Constants.RECEIVE_ID
import utils.Constants.SEND_ID
import utils.Time
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [ForumFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class ForumFragment : Fragment() {
private lateinit var adapter: MessagingAdapter
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
recyclerView()
clickEvents()
customMessage("Hello, you are speaking with Bogart, how may I help?")
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
private fun clickEvents() {
btn_send.setOnClickListener{
sendMessage()
}
et_message.setOnClickListener {
GlobalScope.launch {
delay(100)
withContext(Dispatchers.Main){
rv_messages.scrollToPosition(adapter.itemCount - 1)
}
}
}
}
private fun sendMessage(){
val message = et_message.text.toString()
val timeStamp = Time.timeStamp()
if (message.isNotEmpty()){
et_message.setText("")
adapter.insertMessage(Message(message, SEND_ID, timeStamp))
rv_messages.scrollToPosition(adapter.itemCount - 1)
botResponse(message)
}
}
private fun botResponse(message: String){
val timeStamp = Time.timeStamp()
GlobalScope.launch {
delay(1000)
withContext(Dispatchers.Main){
val response =BotResponse.basicResponses(message)
adapter.insertMessage(Message(response, RECEIVE_ID, timeStamp))
rv_messages.scrollToPosition(adapter.itemCount -1)
when(response){
OPEN_GOOGLE -> {
val site = Intent(Intent.ACTION_VIEW)
site.data = Uri.parse("https://www.google.com/")
startActivity(site)
}
OPEN_SEARCH -> {
val site = Intent(Intent.ACTION_VIEW)
val searchTerm: String? = message.substringAfter("search")
site.data = Uri.parse("https://www.google.com/search?amp;q=$searchTerm")
startActivity(site)
}
}
}
}
}
private fun recyclerView(){
adapter = MessagingAdapter()
rv_messages.adapter = adapter
}
private fun customMessage(message: String) {
GlobalScope.launch {
delay(1000)
withContext(Dispatchers.Main) {
val timeStamp = Time.timeStamp()
adapter.insertMessage(Message(message, RECEIVE_ID, timeStamp))
rv_messages.scrollToPosition(adapter.itemCount - 1)
}
}
}
override fun onStart(){
super.onStart()
GlobalScope.launch {
delay(1000)
withContext(Dispatchers.Main){
rv_messages.scrollToPosition(adapter.itemCount - 1)
}
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_forum, container, false)
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment ForumFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
ForumFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}
//Message.kt
package ui.data
class Message(val message: String, val id: String, val time: String) {
}
//MessagingAdapter.kt
package ui
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.bylaws.R
import kotlinx.android.synthetic.main.message_item.view.*
import ui.data.Message
import utils.Constants.RECEIVE_ID
import utils.Constants.SEND_ID
class MessagingAdapter: RecyclerView.Adapter<MessagingAdapter.MessageViewHolder>() {
var messagesList = mutableListOf<Message>()
inner class MessageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
init {
itemView.setOnClickListener{
messagesList.removeAt(adapterPosition)
notifyItemRemoved(adapterPosition)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
return MessageViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.message_item, parent, false))
}
override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
val currentMessage = messagesList[position]
when (currentMessage.id){
SEND_ID -> {
holder.itemView.tv_message.apply {
text = currentMessage.message
visibility = View.VISIBLE
}
holder.itemView.tv_bot_message.visibility = View.GONE
}
RECEIVE_ID -> {
holder.itemView.tv_bot_message.apply {
text = currentMessage.message
visibility = View.VISIBLE
}
holder.itemView.tv_message.visibility = View.GONE
}
}
}
override fun getItemCount(): Int {
return messagesList.size
}
fun insertMessage(message: Message){
this.messagesList.add(message)
notifyItemInserted(messagesList.size)
}
}
//BotResponse.kt
package utils
import utils.Constants.OPEN_GOOGLE
import utils.Constants.OPEN_SEARCH
import java.lang.Exception
import java.util.*
object BotResponse {
fun basicResponses(_message: String): String {
val random = (0..2).random()
val message = _message.lowercase(Locale.getDefault())
return when {
//Hello
message.contains("hello") -> {
when (random) {
0 -> "Hello there!"
1 -> "Hello, my name is Bogart"
2 -> "Sup!"
else -> "I did not quite get that."
}
}
//how are you
message.contains("how are you") -> {
when (random) {
0 -> "I'm good"
1 -> "I'm fine, just reading some traffic laws"
2 -> "I'm good, how are you with the laws?"
else -> "I did not quite get that."
}
}
message.contains("flip") amp;amp; message.contains("coin") -> {
val r = (0..1).random()
val result = if (r == 0) "Heads" else "tails"
"I flipped $result"
}
//Solve maths
message.contains("solve") -> {
val equation: String? = message.substringAfter("solve")
return try{
val answer = SolveMath.solveMath(equation ?: "0")
answer.toString()
} catch (e: Exception){
"Sorry, I can't solve that"
}
}
//Gets the current time
message.contains("time") amp;amp; message.contains("?") -> {
Time.timeStamp()
}
message.contains("open") amp;amp; message.contains("google") -> {
OPEN_GOOGLE
}
message.contains("search") -> {
OPEN_SEARCH
}
else -> {
when (random) {
0 -> "I don't understand..."
1 -> "Idk"
2 -> "Try asking something else"
else -> "I did not quite get that."
}
}
}
}
}
//Constants.kt
package utils
object Constants {
const val SEND_ID = "SEND_ID"
const val RECEIVE_ID = "RECEIVE_ID"
const val OPEN_GOOGLE = "Opening Google..."
const val OPEN_SEARCH = "Searching..."
}
//SolveMath.kt
package utils
import android.util.Log
object SolveMath {
fun solveMath(equation: String) : Int{
val newEquation = equation.replace(" ", "")
Log.d("Math", newEquation)
return when {
newEquation.contains(" ") -> {
val split = newEquation.split(" ")
val result = split[0].toInt() split[1].toInt()
result
}
newEquation.contains("-") -> {
val split = newEquation.split("-")
val result = split[0].toInt() - split[1].toInt()
result
}
newEquation.contains("*") -> {
val split = newEquation.split("*")
val result = split[0].toInt() * split[1].toInt()
result
}
newEquation.contains("/") -> {
val split = newEquation.split("/")
val result = split[0].toInt() / split[1].toInt()
result
}
else -> {
0
}
}
}
}
//Time.kt
package utils
import java.sql.Timestamp
import java.text.SimpleDateFormat
import java.util.*
object Time {
fun timeStamp(): String {
val timeStamp = Timestamp(System.currentTimeMillis())
val sdf = SimpleDateFormat("HH:mm")
val time = sdf.format(Date(timeStamp.time))
return time.toString()
}
}
//fragment_forum.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:id="@ id/ll_layout_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#E4E4E4"
android:orientation="horizontal">
<EditText
android:id="@ id/et_message"
android:inputType="textShortMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight=".5"
android:background="@drawable/round_button"
android:backgroundTint="@android:color/white"
android:hint="Type a message..."
android:padding="10dp"
android:singleLine="true" />
<Button
android:id="@ id/btn_send"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:layout_weight="1"
android:background="@drawable/round_button"
android:backgroundTint="#26A69A"
android:text="Send"
android:textColor="@android:color/white" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@ id/rv_messages"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/ll_layout_bar"
android:layout_below="@ id/dark_divider"
tools:itemCount="20"
tools:listitem="@layout/message_item" />
<View
android:layout_width="match_parent"
android:layout_height="10dp"
android:background="#42A5F5"
android:id="@ id/dark_divider"/>
</RelativeLayout>
The problem is that everything in the app works fine but when i click the Forum fragment which is where the the chat bot is coded, the app crashes instantly. I don’t know what’s wrong because there is no error code. Any suggestions and corrections? Thanks!
!NOTE! This is the github of the video i followed: https://github.com/federicocotogno/ChatBot
and this is my github: https://github.com/ItsukiEru/ByLaws2.0-master