Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions ChatExample/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
1 change: 1 addition & 0 deletions ChatExample/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
53 changes: 53 additions & 0 deletions ChatExample/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion 28
defaultConfig {
applicationId "com.github.dsrees.chatexample"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

compileOptions {
targetCompatibility = "8"
sourceCompatibility = "8"
}
}

dependencies {
/*
To update the JavaPhoenixClient, either use the latest dependency from jcenter
OR run
`./gradlew jar`
and copy
`/build/lib/*.jar` to `/ChatExample/app/libs`
and comment out the jcenter dependency
*/
implementation fileTree(dir: 'libs', include: ['*.jar'])
// implementation 'com.github.dsrees:JavaPhoenixClient:0.2.3'


compile "com.google.code.gson:gson:2.8.5"
compile "com.squareup.okhttp3:okhttp:3.12.2"


implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

}
Binary file added ChatExample/app/libs/JavaPhoenixClient-0.2.6.jar
Binary file not shown.
21 changes: 21 additions & 0 deletions ChatExample/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
24 changes: 24 additions & 0 deletions ChatExample/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" package="com.github.dsrees.chatexample">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package com.github.dsrees.chatexample

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.EditText
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*
import org.phoenixframework.Channel
import org.phoenixframework.Socket

class MainActivity : AppCompatActivity() {

companion object {
const val TAG = "MainActivity"
}

private val messagesAdapter = MessagesAdapter()
private val layoutManager = LinearLayoutManager(this)


// Use when connecting to https://github.com/dwyl/phoenix-chat-example
private val socket = Socket("https://phxchat.herokuapp.com/socket/websocket")
private val topic = "rooms:lobby"

// Use when connecting to local server
// private val socket = Socket("ws://10.0.2.2:4000/socket/websocket")
// private val topic = "room:lobby"

private var lobbyChannel: Channel? = null

private val username: String
get() = username_input.text.toString()

private val message: String
get() = message_input.text.toString()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)


layoutManager.stackFromEnd = true

messages_recycler_view.layoutManager = layoutManager
messages_recycler_view.adapter = messagesAdapter

socket.onOpen {
this.addText("Socket Opened")
runOnUiThread { connect_button.text = "Disconnect" }
}

socket.onClose {
this.addText("Socket Closed")
runOnUiThread { connect_button.text = "Connect" }
}

socket.onError { throwable, response ->
Log.e(TAG, "Socket Errored $response", throwable)
this.addText("Socket Error")
}

socket.logger = {
Log.d(TAG, "SOCKET $it")
}


connect_button.setOnClickListener {
if (socket.isConnected) {
this.disconnectAndLeave()
} else {
this.disconnectAndLeave()
this.connectAndJoin()
}
}

send_button.setOnClickListener { sendMessage() }
}

private fun sendMessage() {
val payload = mapOf("user" to username, "body" to message)
this.lobbyChannel?.push("new:msg", payload)
?.receive("ok") { Log.d(TAG, "success $it") }
?.receive("error") { Log.d(TAG, "error $it") }

message_input.text.clear()
}

private fun disconnectAndLeave() {
// Be sure the leave the channel or call socket.remove(lobbyChannel)
lobbyChannel?.leave()
socket.disconnect { this.addText("Socket Disconnected") }
}

private fun connectAndJoin() {
val channel = socket.channel(topic, mapOf("status" to "joining"))
channel.on("join") {
this.addText("You joined the room")
}

channel.on("new:msg") { message ->
val payload = message.payload
val username = payload["user"] as? String
val body = payload["body"]


if (username != null && body != null) {
this.addText("[$username] $body")
}
}

channel.on("user:entered") {
this.addText("[anonymous entered]")
}

this.lobbyChannel = channel
channel
.join()
.receive("ok") {
this.addText("Joined Channel")
}
.receive("error") {
this.addText("Failed to join channel: ${it.payload}")
}


this.socket.connect()
}

private fun addText(message: String) {
runOnUiThread {
this.messagesAdapter.add(message)
layoutManager.smoothScrollToPosition(messages_recycler_view, null, messagesAdapter.itemCount)
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.github.dsrees.chatexample

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class MessagesAdapter : RecyclerView.Adapter<MessagesAdapter.ViewHolder>() {

private var messages: MutableList<String> = mutableListOf()

fun add(message: String) {
messages.add(message)
notifyItemInserted(messages.size)
}


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_message, parent, false)
return ViewHolder(view)
}

override fun getItemCount(): Int = messages.size

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.label.text = messages[position]
}

inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val label: TextView = itemView.findViewById(R.id.item_message_label)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0"/>
<item
android:color="#00000000"
android:offset="1.0"/>
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1"/>
</vector>
Loading