Loading leonApp/app/build.gradle +14 −13 Original line number Diff line number Diff line Loading @@ -7,8 +7,8 @@ android { buildToolsVersion "29.0.3" defaultConfig { applicationId "com.poc.leonapp" minSdkVersion 15 applicationId "com.poc.eleon" minSdkVersion 16 targetSdkVersion 29 versionCode 1 versionName "1.0" Loading @@ -22,25 +22,26 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation ('io.socket:socket.io-client:1.0.0') { // excluding org.json which is provided by Android exclude group: 'org.json', module: 'json' } implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation fileTree(dir: "libs", include: ["*.jar"]) implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.3.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.recyclerview:recyclerview:1.1.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation 'androidx.recyclerview:recyclerview:1.1.0' // To create custom view implementation ('io.socket:socket.io-client:1.0.0') { // excluding org.json which is provided by Android exclude group: 'org.json', module: 'json' } implementation "com.xwray:groupie:2.1.0" implementation "org.jsoup:jsoup:1.11.3" compile 'com.kailashdabhi:om-recorder:1.1.5' } No newline at end of file leonApp/app/src/androidTest/java/com/poc/leonapp/ExampleInstrumentedTest.kt→leonApp/app/src/androidTest/java/com/poc/eleon/ExampleInstrumentedTest.kt +3 −3 Original line number Diff line number Diff line package com.poc.leonapp package com.poc.eleon import androidx.test.platform.app.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4 Loading @@ -19,6 +19,6 @@ class ExampleInstrumentedTest { fun useAppContext() { // Context of the app under test. val appContext = InstrumentationRegistry.getInstrumentation().targetContext assertEquals("com.poc.leonapp", appContext.packageName) assertEquals("com.poc.eleon", appContext.packageName) } } No newline at end of file leonApp/app/src/main/AndroidManifest.xml +6 −4 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.poc.leonapp"> package="com.poc.eleon"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" android:usesCleartextTraffic="true"> android:theme="@style/AppTheme"> <activity android:name=".ChatActivity"></activity> <activity android:name=".MainActivity"> <intent-filter> Loading leonApp/app/src/main/java/com/poc/eleon/ChatActivity.kt 0 → 100644 +248 −0 Original line number Diff line number Diff line package com.poc.eleon import android.Manifest import android.content.pm.PackageManager import android.media.MediaRecorder import android.net.Uri import android.os.Build import android.os.Bundle import android.util.Log import android.view.View import android.view.animation.AccelerateDecelerateInterpolator import android.view.animation.TranslateAnimation import android.widget.ImageView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import com.xwray.groupie.GroupAdapter import com.xwray.groupie.Item import com.xwray.groupie.ViewHolder import io.socket.client.IO import io.socket.client.Socket import io.socket.emitter.Emitter import kotlinx.android.synthetic.main.activity_chat.* import kotlinx.android.synthetic.main.activity_chat.view.* import kotlinx.android.synthetic.main.bubble_leon.view.* import kotlinx.android.synthetic.main.bubble_user.view.* import org.json.JSONObject import org.jsoup.Jsoup import java.io.ByteArrayOutputStream import java.io.File import java.io.IOException import java.io.InputStream class ChatActivity : AppCompatActivity() { private var socket: Socket = IO.socket("http://192.168.0.14:1337") var mediaRecorder: MediaRecorder? = null private var FILE_RECORDING = "" private val PERMISSION_GRANTED = PackageManager.PERMISSION_GRANTED private val AUDIO_PERMISSION = Manifest.permission.RECORD_AUDIO private val PERMISSION_REQUEST_CODE = 100 override fun onCreate(savedInstanceState: Bundle?) { val adapter = GroupAdapter<ViewHolder>() var showHideKeyboard:Boolean = true super.onCreate(savedInstanceState) setContentView(R.layout.activity_chat) initRecyclerViewAdapter(adapter) FILE_RECORDING = "${externalCacheDir?.absolutePath}/recorder.mp3" var tmp:Boolean = true VoiceRecord.setOnClickListener { tmp = if (tmp) { startRecord() false } else { stopRecord() true } } userLand.chatActivity_userSend.setOnClickListener { val userText = userLand.chatActivity_userKeyboard.text.toString() if (userText.isNotEmpty()) { addBubbleToView(adapter, R.layout.bubble_user, userText) userLand.chatActivity_userKeyboard.text.clear() sendQueryToLeon(userText) } } HideShowKeyboard.setOnClickListener { showHideKeyboard = if (!showHideKeyboard) { slideUp(findViewById(R.id.userLand)) userLand.chatActivity_userKeyboard.visibility = View.VISIBLE rescaleImageView(VoiceRecord, 1f, 1f, 1000) true; } else { slideDown(findViewById(R.id.userLand)) userLand.chatActivity_userKeyboard.visibility = View.INVISIBLE rescaleImageView(VoiceRecord, 1.5f, 1.5f, 1000) false; } } socket.on(Socket.EVENT_DISCONNECT, Emitter.Listener { Log.d("ChatActivity", "User has been disconnected from Leon") }) socket.on(Socket.EVENT_CONNECT, Emitter.Listener { Log.d("ChatActivity", "User is now connected to Leon") socket.emit("init", "webapp") }) socket.on("answer", Emitter.Listener { args -> var leonText:String = args[0].toString() leonText = Jsoup.parse(leonText).text() runOnUiThread { addBubbleToView(adapter, R.layout.bubble_leon, leonText) } }) socket.on("recognized", Emitter.Listener { args -> var userAudioText = args[0].toString() userAudioText = Jsoup.parse(userAudioText).text() runOnUiThread { addBubbleToView(adapter, R.layout.bubble_user, userAudioText) } sendQueryToLeon(userAudioText) }) socket.connect() } private fun rescaleImageView(view: ImageView, x: Float, y: Float, duration: Long) { view.animate().scaleY(y).setInterpolator(AccelerateDecelerateInterpolator()).duration = duration view.animate().scaleX(x).setInterpolator(AccelerateDecelerateInterpolator()).duration = duration } private fun isPermissionGranted(): Boolean{ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) checkSelfPermission(AUDIO_PERMISSION) == PERMISSION_GRANTED else return true } private fun requestAudioPermission(){ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ requestPermissions(arrayOf(AUDIO_PERMISSION), PERMISSION_REQUEST_CODE) } } private fun startRecord() { Log.d("ChatActivity", "Start") rescaleImageView(VoiceRecord, 1.5f, 1.5f, 500) if(!isPermissionGranted()){ requestAudioPermission() return } mediaRecorder = MediaRecorder() mediaRecorder!!.setAudioSource(MediaRecorder.AudioSource.MIC) mediaRecorder!!.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) mediaRecorder!!.setOutputFile(FILE_RECORDING) mediaRecorder!!.setAudioEncoder(MediaRecorder.AudioEncoder.AAC) mediaRecorder!!.prepare() mediaRecorder!!.start() } private fun stopRecord() { Log.d("ChatActivity", "Stop") rescaleImageView(VoiceRecord, 1f, 1f, 500) if (mediaRecorder == null) return mediaRecorder?.stop() mediaRecorder?.release() mediaRecorder = null sendAudio(FILE_RECORDING) } private fun initRecyclerViewAdapter(adapter: GroupAdapter<ViewHolder>) { ChatActivity_RecyclerView.adapter = adapter } private fun addBubbleToView(adapter: GroupAdapter<ViewHolder>, layoutId: Int, text: String) { adapter.add(Bubble(layoutId, text)) ChatActivity_RecyclerView.scrollToPosition(adapter.itemCount - 1) } private fun sendQueryToLeon(text: String) { val obj = JSONObject() obj.put("value", text) socket.emit("query", obj) } private fun slideUp(view: View) { view.visibility = View.VISIBLE val animate = TranslateAnimation( 0F, // fromXDelta 0F, // toXDelta view.height.toFloat(), // fromYDelta 0F ) // toYDelta animate.duration = 200 animate.fillAfter = true view.startAnimation(animate) } private fun slideDown(view: View) { val animate = TranslateAnimation( 0F, // fromXDelta 0F, // toXDelta 0F, // fromYDelta view.height.toFloat() ) // toYDelta animate.duration = 200 animate.fillAfter = true view.startAnimation(animate) } private fun sendAudio(outputFile:String) { Log.d("ChatActivity", "Path to audio record : $outputFile") var soundBytes: ByteArray if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { val permissions = arrayOf(android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_EXTERNAL_STORAGE) ActivityCompat.requestPermissions(this, permissions,0) } else { try { val r1 = Uri.fromFile(File(outputFile)) val inputStream = contentResolver.openInputStream(r1) Log.d("ChatActivity", "inputStream : $inputStream") soundBytes = ByteArray(inputStream!!.available()) soundBytes = toByteArray(inputStream!!)!! Log.d("ChatActivity", "Audio converted") Toast.makeText(this, "Recording Finished $soundBytes", Toast.LENGTH_LONG).show() socket.emit("recognize", soundBytes) Log.d("ChatActivity", "Audio sent") } catch (e: Exception) { Log.d("ChatActivity", "Got an error : $e.message") e.printStackTrace() } } } @Throws(IOException::class) fun toByteArray(`in`: InputStream): ByteArray? { val out = ByteArrayOutputStream() var read = 0 val buffer = ByteArray(1024) while (read != -1) { read = `in`.read(buffer) if (read != -1) out.write(buffer, 0, read) } out.close() return out.toByteArray() } } class Bubble(private val layoutId: Int, private val text: String): Item<ViewHolder>() { override fun getLayout(): Int { return (layoutId) } override fun bind(viewHolder: ViewHolder, position: Int) { if (layoutId == R.layout.bubble_leon) viewHolder.itemView.TextView_bubbleLeon.text = text else viewHolder.itemView.TextView_bubbleUser.text = text } } leonApp/app/src/main/java/com/poc/leonapp/MainActivity.kt→leonApp/app/src/main/java/com/poc/eleon/MainActivity.kt +9 −10 Original line number Diff line number Diff line package com.poc.leonapp package com.poc.eleon import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import com.xwray.groupie.GroupAdapter import com.xwray.groupie.ViewHolder import io.socket.client.IO import io.socket.client.Socket import io.socket.emitter.Emitter import android.view.View import android.view.animation.TranslateAnimation import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { val intent = Intent(this, ChatActivity::class.java) val intent: Intent = Intent(this, ChatActivity::class.java) super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) } } No newline at end of file Loading
leonApp/app/build.gradle +14 −13 Original line number Diff line number Diff line Loading @@ -7,8 +7,8 @@ android { buildToolsVersion "29.0.3" defaultConfig { applicationId "com.poc.leonapp" minSdkVersion 15 applicationId "com.poc.eleon" minSdkVersion 16 targetSdkVersion 29 versionCode 1 versionName "1.0" Loading @@ -22,25 +22,26 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation ('io.socket:socket.io-client:1.0.0') { // excluding org.json which is provided by Android exclude group: 'org.json', module: 'json' } implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation fileTree(dir: "libs", include: ["*.jar"]) implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.3.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.recyclerview:recyclerview:1.1.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation 'androidx.recyclerview:recyclerview:1.1.0' // To create custom view implementation ('io.socket:socket.io-client:1.0.0') { // excluding org.json which is provided by Android exclude group: 'org.json', module: 'json' } implementation "com.xwray:groupie:2.1.0" implementation "org.jsoup:jsoup:1.11.3" compile 'com.kailashdabhi:om-recorder:1.1.5' } No newline at end of file
leonApp/app/src/androidTest/java/com/poc/leonapp/ExampleInstrumentedTest.kt→leonApp/app/src/androidTest/java/com/poc/eleon/ExampleInstrumentedTest.kt +3 −3 Original line number Diff line number Diff line package com.poc.leonapp package com.poc.eleon import androidx.test.platform.app.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4 Loading @@ -19,6 +19,6 @@ class ExampleInstrumentedTest { fun useAppContext() { // Context of the app under test. val appContext = InstrumentationRegistry.getInstrumentation().targetContext assertEquals("com.poc.leonapp", appContext.packageName) assertEquals("com.poc.eleon", appContext.packageName) } } No newline at end of file
leonApp/app/src/main/AndroidManifest.xml +6 −4 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.poc.leonapp"> package="com.poc.eleon"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" android:usesCleartextTraffic="true"> android:theme="@style/AppTheme"> <activity android:name=".ChatActivity"></activity> <activity android:name=".MainActivity"> <intent-filter> Loading
leonApp/app/src/main/java/com/poc/eleon/ChatActivity.kt 0 → 100644 +248 −0 Original line number Diff line number Diff line package com.poc.eleon import android.Manifest import android.content.pm.PackageManager import android.media.MediaRecorder import android.net.Uri import android.os.Build import android.os.Bundle import android.util.Log import android.view.View import android.view.animation.AccelerateDecelerateInterpolator import android.view.animation.TranslateAnimation import android.widget.ImageView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import com.xwray.groupie.GroupAdapter import com.xwray.groupie.Item import com.xwray.groupie.ViewHolder import io.socket.client.IO import io.socket.client.Socket import io.socket.emitter.Emitter import kotlinx.android.synthetic.main.activity_chat.* import kotlinx.android.synthetic.main.activity_chat.view.* import kotlinx.android.synthetic.main.bubble_leon.view.* import kotlinx.android.synthetic.main.bubble_user.view.* import org.json.JSONObject import org.jsoup.Jsoup import java.io.ByteArrayOutputStream import java.io.File import java.io.IOException import java.io.InputStream class ChatActivity : AppCompatActivity() { private var socket: Socket = IO.socket("http://192.168.0.14:1337") var mediaRecorder: MediaRecorder? = null private var FILE_RECORDING = "" private val PERMISSION_GRANTED = PackageManager.PERMISSION_GRANTED private val AUDIO_PERMISSION = Manifest.permission.RECORD_AUDIO private val PERMISSION_REQUEST_CODE = 100 override fun onCreate(savedInstanceState: Bundle?) { val adapter = GroupAdapter<ViewHolder>() var showHideKeyboard:Boolean = true super.onCreate(savedInstanceState) setContentView(R.layout.activity_chat) initRecyclerViewAdapter(adapter) FILE_RECORDING = "${externalCacheDir?.absolutePath}/recorder.mp3" var tmp:Boolean = true VoiceRecord.setOnClickListener { tmp = if (tmp) { startRecord() false } else { stopRecord() true } } userLand.chatActivity_userSend.setOnClickListener { val userText = userLand.chatActivity_userKeyboard.text.toString() if (userText.isNotEmpty()) { addBubbleToView(adapter, R.layout.bubble_user, userText) userLand.chatActivity_userKeyboard.text.clear() sendQueryToLeon(userText) } } HideShowKeyboard.setOnClickListener { showHideKeyboard = if (!showHideKeyboard) { slideUp(findViewById(R.id.userLand)) userLand.chatActivity_userKeyboard.visibility = View.VISIBLE rescaleImageView(VoiceRecord, 1f, 1f, 1000) true; } else { slideDown(findViewById(R.id.userLand)) userLand.chatActivity_userKeyboard.visibility = View.INVISIBLE rescaleImageView(VoiceRecord, 1.5f, 1.5f, 1000) false; } } socket.on(Socket.EVENT_DISCONNECT, Emitter.Listener { Log.d("ChatActivity", "User has been disconnected from Leon") }) socket.on(Socket.EVENT_CONNECT, Emitter.Listener { Log.d("ChatActivity", "User is now connected to Leon") socket.emit("init", "webapp") }) socket.on("answer", Emitter.Listener { args -> var leonText:String = args[0].toString() leonText = Jsoup.parse(leonText).text() runOnUiThread { addBubbleToView(adapter, R.layout.bubble_leon, leonText) } }) socket.on("recognized", Emitter.Listener { args -> var userAudioText = args[0].toString() userAudioText = Jsoup.parse(userAudioText).text() runOnUiThread { addBubbleToView(adapter, R.layout.bubble_user, userAudioText) } sendQueryToLeon(userAudioText) }) socket.connect() } private fun rescaleImageView(view: ImageView, x: Float, y: Float, duration: Long) { view.animate().scaleY(y).setInterpolator(AccelerateDecelerateInterpolator()).duration = duration view.animate().scaleX(x).setInterpolator(AccelerateDecelerateInterpolator()).duration = duration } private fun isPermissionGranted(): Boolean{ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) checkSelfPermission(AUDIO_PERMISSION) == PERMISSION_GRANTED else return true } private fun requestAudioPermission(){ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ requestPermissions(arrayOf(AUDIO_PERMISSION), PERMISSION_REQUEST_CODE) } } private fun startRecord() { Log.d("ChatActivity", "Start") rescaleImageView(VoiceRecord, 1.5f, 1.5f, 500) if(!isPermissionGranted()){ requestAudioPermission() return } mediaRecorder = MediaRecorder() mediaRecorder!!.setAudioSource(MediaRecorder.AudioSource.MIC) mediaRecorder!!.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) mediaRecorder!!.setOutputFile(FILE_RECORDING) mediaRecorder!!.setAudioEncoder(MediaRecorder.AudioEncoder.AAC) mediaRecorder!!.prepare() mediaRecorder!!.start() } private fun stopRecord() { Log.d("ChatActivity", "Stop") rescaleImageView(VoiceRecord, 1f, 1f, 500) if (mediaRecorder == null) return mediaRecorder?.stop() mediaRecorder?.release() mediaRecorder = null sendAudio(FILE_RECORDING) } private fun initRecyclerViewAdapter(adapter: GroupAdapter<ViewHolder>) { ChatActivity_RecyclerView.adapter = adapter } private fun addBubbleToView(adapter: GroupAdapter<ViewHolder>, layoutId: Int, text: String) { adapter.add(Bubble(layoutId, text)) ChatActivity_RecyclerView.scrollToPosition(adapter.itemCount - 1) } private fun sendQueryToLeon(text: String) { val obj = JSONObject() obj.put("value", text) socket.emit("query", obj) } private fun slideUp(view: View) { view.visibility = View.VISIBLE val animate = TranslateAnimation( 0F, // fromXDelta 0F, // toXDelta view.height.toFloat(), // fromYDelta 0F ) // toYDelta animate.duration = 200 animate.fillAfter = true view.startAnimation(animate) } private fun slideDown(view: View) { val animate = TranslateAnimation( 0F, // fromXDelta 0F, // toXDelta 0F, // fromYDelta view.height.toFloat() ) // toYDelta animate.duration = 200 animate.fillAfter = true view.startAnimation(animate) } private fun sendAudio(outputFile:String) { Log.d("ChatActivity", "Path to audio record : $outputFile") var soundBytes: ByteArray if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { val permissions = arrayOf(android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_EXTERNAL_STORAGE) ActivityCompat.requestPermissions(this, permissions,0) } else { try { val r1 = Uri.fromFile(File(outputFile)) val inputStream = contentResolver.openInputStream(r1) Log.d("ChatActivity", "inputStream : $inputStream") soundBytes = ByteArray(inputStream!!.available()) soundBytes = toByteArray(inputStream!!)!! Log.d("ChatActivity", "Audio converted") Toast.makeText(this, "Recording Finished $soundBytes", Toast.LENGTH_LONG).show() socket.emit("recognize", soundBytes) Log.d("ChatActivity", "Audio sent") } catch (e: Exception) { Log.d("ChatActivity", "Got an error : $e.message") e.printStackTrace() } } } @Throws(IOException::class) fun toByteArray(`in`: InputStream): ByteArray? { val out = ByteArrayOutputStream() var read = 0 val buffer = ByteArray(1024) while (read != -1) { read = `in`.read(buffer) if (read != -1) out.write(buffer, 0, read) } out.close() return out.toByteArray() } } class Bubble(private val layoutId: Int, private val text: String): Item<ViewHolder>() { override fun getLayout(): Int { return (layoutId) } override fun bind(viewHolder: ViewHolder, position: Int) { if (layoutId == R.layout.bubble_leon) viewHolder.itemView.TextView_bubbleLeon.text = text else viewHolder.itemView.TextView_bubbleUser.text = text } }
leonApp/app/src/main/java/com/poc/leonapp/MainActivity.kt→leonApp/app/src/main/java/com/poc/eleon/MainActivity.kt +9 −10 Original line number Diff line number Diff line package com.poc.leonapp package com.poc.eleon import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import com.xwray.groupie.GroupAdapter import com.xwray.groupie.ViewHolder import io.socket.client.IO import io.socket.client.Socket import io.socket.emitter.Emitter import android.view.View import android.view.animation.TranslateAnimation import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { val intent = Intent(this, ChatActivity::class.java) val intent: Intent = Intent(this, ChatActivity::class.java) super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) } } No newline at end of file