diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1106d15..397095d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -40,8 +40,10 @@
-
-
+
+
diff --git a/app/src/main/java/com/example/markmoussa/meshchatapplication/ConversationListActivity.kt b/app/src/main/java/com/example/markmoussa/meshchatapplication/ConversationListActivity.kt
index abf75cc..24f3b3c 100644
--- a/app/src/main/java/com/example/markmoussa/meshchatapplication/ConversationListActivity.kt
+++ b/app/src/main/java/com/example/markmoussa/meshchatapplication/ConversationListActivity.kt
@@ -135,7 +135,6 @@ class ConversationListActivity : AppCompatActivity(), Store.Delegate, LifecycleO
var currentlyOnline: Boolean
val contactsList = hypeFramework.getAllContacts()
val onlinePeers = hypeFramework.getOnlinePeers()
- Log.d("ConversationListActivit", "Length of hypeFramework.getAllMessages(): ${hypeFramework.getAllMessages().size}")
for(x in hypeFramework.getAllMessages()) {
currentlyOnline = onlinePeers.containsKey(x.key)
// val nickname: String?
diff --git a/app/src/main/java/com/example/markmoussa/meshchatapplication/ConversationListAdapter.kt b/app/src/main/java/com/example/markmoussa/meshchatapplication/ConversationListAdapter.kt
index 2a83c27..b815ba8 100644
--- a/app/src/main/java/com/example/markmoussa/meshchatapplication/ConversationListAdapter.kt
+++ b/app/src/main/java/com/example/markmoussa/meshchatapplication/ConversationListAdapter.kt
@@ -53,6 +53,10 @@ class ConversationListAdapter(private val mContext: Context, private val mConver
onlineStatusIcon = itemView.findViewById(R.id.onlineStatusIcon) as ImageView
}
internal fun bind(conversation: Conversation) {
+ if(conversation.user == null) {
+ Log.e("ConvoListAdapter", "Problem with User being null here")
+ return
+ }
if(conversation.user!!.nickname != null) {
usernameText.text = conversation.user.nickname
} else {
diff --git a/app/src/main/java/com/example/markmoussa/meshchatapplication/HypeLifeCycle.kt b/app/src/main/java/com/example/markmoussa/meshchatapplication/HypeLifeCycle.kt
index 8693d36..5c8dd7f 100644
--- a/app/src/main/java/com/example/markmoussa/meshchatapplication/HypeLifeCycle.kt
+++ b/app/src/main/java/com/example/markmoussa/meshchatapplication/HypeLifeCycle.kt
@@ -4,9 +4,12 @@ package com.example.markmoussa.meshchatapplication
// ALL CREDIT FOR THIS FILE GOES DIRECTLY TO HYPELABS
// link: https://github.com/Hype-Labs/HypeChatDemo.android
-import android.app.Application
+import android.app.*
import android.content.Context
+import android.content.Intent
import android.content.SharedPreferences
+import android.os.Build
+import android.support.v4.app.NotificationCompat
import android.util.Log
import com.hypelabs.hype.Error
import com.hypelabs.hype.Hype
@@ -21,6 +24,8 @@ import kotlin.collections.HashMap
import kotlin.properties.Delegates
+
+
class HypeLifeCycle : StateObserver, NetworkObserver, MessageObserver, Application() {
// TODO: DO THIS SECOND - Figure out why these observables aren't working sometimes (such as messageDatabase in setMessageDatabase()
@@ -52,13 +57,32 @@ class HypeLifeCycle : StateObserver, NetworkObserver, MessageObserver, Applicati
// by creating a new app. Copy the given identifier here.
// ChatApplication
- Hype.setAppIdentifier("f370ac17")
+// Hype.setAppIdentifier("f370ac17")
// MeshNetworkApplication
- // Hype.setAppIdentifier("9a96baaa")
+ Hype.setAppIdentifier("9a96baaa")
// MeshNetworkApp2
- Hype.setAppIdentifier("b056a7af")
+// Hype.setAppIdentifier("b056a7af")
+
+ // MeshNetwork3
+// Hype.setAppIdentifier("d74214ee")
+
+ // MeshNetwork4
+// Hype.setAppIdentifier("ba3ae1ae")
+
+ //MeshNetworkApplication5
+// Hype.setAppIdentifier("9cb5496c")
+
+ // PleaseWork
+// Hype.setAppIdentifier("f26a3372")
+
+ // PleaseIBegYou
+// Hype.setAppIdentifier("ad9b29f5")
+
+ //ChatAppEgyptianMarkos
+// Hype.setAppIdentifier("aba7c2aa")
+
val sharedPreferences: SharedPreferences = applicationContext.getSharedPreferences("sp", Context.MODE_PRIVATE)
val userIdentifier = sharedPreferences.getInt("USER_IDENTIFIER", Hype.DefaultUserIdentifier)
Hype.setUserIdentifier(userIdentifier)
@@ -155,6 +179,7 @@ class HypeLifeCycle : StateObserver, NetworkObserver, MessageObserver, Applicati
// Storing the message triggers a reload update in the MessageList activity
store.add(Pair(message.data.toString(charset("UTF-8")), false), this)
setMessageDatabase(instance.userIdentifier, store)
+ sendNotification(message, instance)
}
@@ -181,14 +206,33 @@ class HypeLifeCycle : StateObserver, NetworkObserver, MessageObserver, Applicati
override fun onHypeRequestAccessToken(i: Int): String {
// Access the app settings (https://hypelabs.io/apps/) to find an access token to use here.
+
// This one is for chatApplication
// return "903cbdd53f59e2f771cbf2a9429c91"
// MeshNetworkApplication
-// return "4e5936b294a88cf2"
+ return "4e5936b294a88cf2"
// MeshNetworkApp2
- return "4e5936b294a88cf2"
+// return "4e5936b294a88cf2"
+
+ //MeshNetwork3
+// return "9f05c13eb9276473"
+
+ //MeshNetwork4
+// return "bf80129c2ae5e7df"
+
+ // MeshNetworkApplication5
+// return "9f05c13eb9276473"
+
+ // PleaseWork
+// return "bf80129c2ae5e7df"
+
+ // PleaseIBegYou
+// return "bf80129c2ae5e7df"
+
+ //ChatAppEgyptianMarkos
+ return "bf80129c2ae5e7df"
}
override fun onCreate() {
@@ -379,6 +423,10 @@ class HypeLifeCycle : StateObserver, NetworkObserver, MessageObserver, Applicati
}
if(!(readContactsDatabase().containsKey(instance.userIdentifier))) {
// restoring User object from serialized byteArray
+ if(instance.announcement == null) {
+ Log.d("Announcement null", "The Instance announcement is null")
+ }
+ Log.d("Instance announcement: ", "${instance.announcement.toString(charset("UTF-8"))}")
val bis = ByteArrayInputStream(instance.announcement)
val ois = ObjectInputStream(bis)
val newUser: User = ois.readObject() as User
@@ -406,6 +454,40 @@ class HypeLifeCycle : StateObserver, NetworkObserver, MessageObserver, Applicati
// conversationListActivity.notifyOnlinePeersChanged()
}
+ private fun sendNotification(message: Message, instance: Instance) {
+ if(!(LifecycleObserverActivity.isAppInForeground)) {
+ val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ if(Build.VERSION.SDK_INT >= 26) {
+ val notificationChannel = NotificationChannel("hypeMessageReceived", "Message Received", NotificationManager.IMPORTANCE_DEFAULT)
+ notificationManager.createNotificationChannel(notificationChannel)
+ }
+ // change messageReceivedNotificationID to something more robust in the future
+ val messageReceivedNotificationID = 1234321
+ val notificationBuilder = NotificationCompat.Builder(applicationContext, "hypeMessageReceived")
+
+ var contentText: String? = message.data.toString(charset("UTF-8"))
+
+ if(message.data.toString(charset("UTF-8")).length > 25) {
+ contentText = message.data.toString(charset("UTF-8")).substring(0, 25) + "..."
+ }
+ val nickname = getAllContacts()[instance.userIdentifier]?.nickname
+ val contentTitle: String? = if(nickname.isNullOrEmpty()) instance.userIdentifier.toString() else nickname
+ val notification = notificationBuilder.setAutoCancel(true)
+ .setDefaults(Notification.DEFAULT_ALL)
+ .setWhen(System.currentTimeMillis())
+ .setSmallIcon(R.drawable.ic_launcher_foreground)
+ .setTicker("New message received!")
+ .setContentTitle(contentTitle)
+ .setContentText(contentText)
+
+ val intent = Intent(this, MessageListActivity::class.java)
+ intent.putExtra("userIdentifier", instance.userIdentifier)
+ val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
+ notification.setContentIntent(pendingIntent)
+ notificationManager.notify(messageReceivedNotificationID, notificationBuilder.build())
+ }
+ }
+
companion object {
private const val TAG = "HypeServices"
diff --git a/app/src/main/java/com/example/markmoussa/meshchatapplication/LifecycleObserverActivity.kt b/app/src/main/java/com/example/markmoussa/meshchatapplication/LifecycleObserverActivity.kt
index cd51b1e..a3d22ca 100644
--- a/app/src/main/java/com/example/markmoussa/meshchatapplication/LifecycleObserverActivity.kt
+++ b/app/src/main/java/com/example/markmoussa/meshchatapplication/LifecycleObserverActivity.kt
@@ -6,6 +6,7 @@ import android.arch.lifecycle.LifecycleObserver
import android.arch.lifecycle.OnLifecycleEvent
import android.arch.lifecycle.ProcessLifecycleOwner
import android.content.Context
+import android.content.SharedPreferences
import android.util.Log
class LifecycleObserverActivity(context: Context) : LifecycleObserver {
@@ -20,25 +21,37 @@ class LifecycleObserverActivity(context: Context) : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onAppForegrounded() {
Log.i("DEBUG ", "ON APP FOREGROUNDED CALLED")
- val hypeFramework = mContext as HypeLifeCycle
- hypeFramework.requestHypeToStart()
+ isAppInForeground = true
+ // Don't want to start Hype immediately if it's their first time opening the app (because they need to sign up first)
+ val sharedPreferences: SharedPreferences = mContext.getSharedPreferences("sp", Context.MODE_PRIVATE)
+ if(sharedPreferences.contains("USERNAME") && sharedPreferences.getString("USERNAME", null).isNotEmpty()) {
+ val hypeFramework = mContext as HypeLifeCycle
+ hypeFramework.requestHypeToStart()
+ }
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppBackgrounded() {
- Log.i("DEBUG ", "ON APP BACKGROUNDED CALLED")
+// Log.i("DEBUG ", "ON APP BACKGROUNDED CALLED")
+ isAppInForeground = false
// Commenting this out because if Hype stops when app backgrounded, messages would only get sent
// when the user has the app open
- val hypeFramework = mContext as HypeLifeCycle
- hypeFramework.requestHypeToStop()
+// val hypeFramework = mContext as HypeLifeCycle
+// hypeFramework.requestHypeToStop()
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onAppDestroyed() {
+ Log.i("DEBUG ", "ON APP DESTROYED CALLED")
+ isAppInForeground = false
// Commenting this part out for demo tomorrow
-// val hypeFramework = mContext as HypeLifeCycle
-// hypeFramework.requestHypeToStop()
+ val hypeFramework = mContext as HypeLifeCycle
+ hypeFramework.requestHypeToStop()
+ }
+
+ companion object {
+ var isAppInForeground: Boolean = true
}
diff --git a/app/src/main/java/com/example/markmoussa/meshchatapplication/MessageListActivity.kt b/app/src/main/java/com/example/markmoussa/meshchatapplication/MessageListActivity.kt
index 493351e..c2ffedd 100644
--- a/app/src/main/java/com/example/markmoussa/meshchatapplication/MessageListActivity.kt
+++ b/app/src/main/java/com/example/markmoussa/meshchatapplication/MessageListActivity.kt
@@ -48,6 +48,7 @@ class MessageListActivity : AppCompatActivity(), Store.Delegate {
mMessageRecycler.adapter = mMessageAdapter
// getting the messages
notifyMessageListChanged()
+ mMessageRecycler.scrollToPosition(mMessageList.size - 1)
// hackish fix at the messages not appearing when notifyDataSetChanged() called. Need to fix later
@@ -68,10 +69,10 @@ class MessageListActivity : AppCompatActivity(), Store.Delegate {
if(userIdentifier in hypeFramework.getAllMessages()) {
val store = getStore()
// debugging
- Log.d("MessageListActivity ", "Store is this: ")
- for(x in store.getMessages()) {
- Log.i("DEBUG", x.first)
- }
+// Log.d("MessageListActivity ", "Store is this: ")
+// for(x in store.getMessages()) {
+// Log.i("DEBUG", x.first)
+// }
store.delegate = this
store.lastReadIndex = store.getMessages().size
diff --git a/app/src/main/java/com/example/markmoussa/meshchatapplication/MessageListAdapter.kt b/app/src/main/java/com/example/markmoussa/meshchatapplication/MessageListAdapter.kt
index 1f87e23..61dcaf6 100644
--- a/app/src/main/java/com/example/markmoussa/meshchatapplication/MessageListAdapter.kt
+++ b/app/src/main/java/com/example/markmoussa/meshchatapplication/MessageListAdapter.kt
@@ -76,7 +76,6 @@ class MessageListAdapter(private val mContext: Context, private val mMessageList
// UserMessage is specific to SendBird, fix later
internal fun bind(message: String) {
messageText.text = message
- Log.i("DEBUG ", "Message text from adapter: ${messageText.text}")
// Format the stored timestamp into a readable String using method.
// Utils specific to SendBird, fix later
@@ -92,7 +91,6 @@ class MessageListAdapter(private val mContext: Context, private val mMessageList
internal fun bind(message: String) {
messageText.text = message
- Log.i("DEBUG ", "Message text from adapter: ${messageText.text}")
if(profileUri == null) {
profileImage.setImageResource(R.drawable.default_user_image)
} else {
diff --git a/app/src/main/res/layout/item_message_sent.xml b/app/src/main/res/layout/item_message_sent.xml
index 0c99ee1..b8dc24f 100644
--- a/app/src/main/res/layout/item_message_sent.xml
+++ b/app/src/main/res/layout/item_message_sent.xml
@@ -13,16 +13,21 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
+ android:layout_marginTop="8dp"
android:text="11:40"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/bubbleTextView"
- app:layout_constraintEnd_toStartOf="@+id/bubbleTextView" />
+ app:layout_constraintEnd_toStartOf="@+id/bubbleTextView"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_bias="1.0" />
+ app:layout_constraintTop_toTopOf="parent" />
\ No newline at end of file