├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── libraries │ ├── animated_vector_drawable_23_4_0.xml │ ├── firebase_common_9_0_2.xml │ ├── hamcrest_core_1_3.xml │ ├── json_simple_1_1.xml │ ├── junit_4_12.xml │ ├── play_services_base_9_0_2.xml │ ├── play_services_basement_9_0_2.xml │ ├── play_services_gcm_9_0_2.xml │ ├── play_services_iid_9_0_2.xml │ ├── play_services_tasks_9_0_2.xml │ ├── support_annotations_23_4_0.xml │ ├── support_v4_23_4_0.xml │ └── support_vector_drawable_23_4_0.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml ├── vcs.xml └── workspace.xml ├── LICENSE ├── MessagingAndroidChat.iml ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── co │ │ └── realtime │ │ └── messagingandroidchat │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ ├── co │ │ │ └── realtime │ │ │ │ └── messagingandroidchat │ │ │ │ ├── ChatRoomActivity.java │ │ │ │ ├── ComposeActivity.java │ │ │ │ ├── MainActivity.java │ │ │ │ ├── MessageActivity.java │ │ │ │ └── NotificationActivity.java │ │ ├── config │ │ │ └── Config.java │ │ ├── domains │ │ │ ├── Channel.java │ │ │ └── Message.java │ │ ├── handlers │ │ │ └── OrtcHandler.java │ │ ├── interfaces │ │ │ └── InterfaceRefresher.java │ │ ├── preferences │ │ │ └── PreferencesManager.java │ │ ├── receiver │ │ │ └── GcmReceiver.java │ │ └── ui │ │ │ ├── CustomTableRow.java │ │ │ └── MessageTableRow.java │ └── res │ │ ├── drawable-hdpi │ │ ├── background.png │ │ ├── ballon_left.png │ │ ├── ballon_right.png │ │ ├── btn_add.png │ │ ├── btn_del.png │ │ ├── ic_action_rt.png │ │ ├── speech_bubble_green.9.png │ │ └── speech_bubble_orange.9.png │ │ ├── layout │ │ ├── activity_chat_room.xml │ │ ├── activity_compose.xml │ │ ├── activity_main.xml │ │ ├── activity_message.xml │ │ ├── activity_notification.xml │ │ ├── addchannel.xml │ │ ├── cellreceive.xml │ │ ├── cellsend.xml │ │ ├── channel.xml │ │ └── delchannel.xml │ │ ├── menu │ │ ├── menu_chat_room.xml │ │ ├── menu_compose.xml │ │ ├── menu_main.xml │ │ └── menu_message.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── co │ └── realtime │ └── messagingandroidchat │ └── ExampleUnitTest.java ├── build.gradle ├── example1.png ├── example2.png ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | ### Android template 2 | # Built application files 3 | *.apk 4 | *.ap_ 5 | 6 | # Files for the Dalvik VM 7 | *.dex 8 | 9 | # Java class files 10 | *.class 11 | 12 | # Generated files 13 | bin/ 14 | gen/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Created by .ignore support plugin (hsz.mobi) 33 | 34 | .idea/libraries/ 35 | build/intermediates/ -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | MessagingAndroidChat -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/libraries/animated_vector_drawable_23_4_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/firebase_common_9_0_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/hamcrest_core_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/json_simple_1_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/junit_4_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/play_services_base_9_0_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/play_services_basement_9_0_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/play_services_gcm_9_0_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/play_services_iid_9_0_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/play_services_tasks_9_0_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/support_annotations_23_4_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/support_v4_23_4_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/support_vector_drawable_23_4_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Realtime Framework 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /MessagingAndroidChat.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## The Realtime Framework Pub/Sub messaging system 2 | Part of the [The Realtime® Framework](http://framework.realtime.co), Realtime Cloud Messaging (aka ORTC) is a secure, fast and highly scalable cloud-hosted Pub/Sub real-time message broker for web and mobile apps. 3 | 4 | If your website or mobile app has data that needs to be updated in the user’s interface as it changes (e.g. real-time stock quotes or ever changing social news feed) Realtime Cloud Messaging is the reliable, easy, unbelievably fast, “works everywhere” solution. 5 | 6 | ## The Android + FCM Push Notifications sample app 7 | This sample app uses the Realtime® Framework Pub/Sub Android library to connect, send and receive messages through a Realtime® Server in the cloud. Through the integrated use of Firebase Cloud Messaging (FCM) messages are delivered to users as push notifications when the app is not running. 8 | 9 | ![ScreenShot](http://messaging-public.realtime.co/screenshots/2.1.0/Android/example1.png) ![ScreenShot](http://messaging-public.realtime.co/screenshots/2.1.0/Android/example2.png) 10 | 11 | ###This app is compatible with the iOS sample. See [https://github.com/realtime-framework/MessagingObjectivecChat](https://github.com/realtime-framework/MessagingObjectivecChat) 12 | 13 | 14 | > NOTE: For simplicity these samples assume you're using a Realtime® Framework developers' application key with the authentication service disabled (every connection will have permission to publish and subscribe to any channel). For security guidelines please refer to the [Security Guide](http://messaging-public.realtime.co/documentation/starting-guide/security.html). 15 | > 16 | > **Don't forget to replace `YOUR_APPLICATION_KEY` with your Realtime application key and `YOUR_FIREBASE_SENDER_ID` with your Firebase Sender ID in the [Config.java](https://github.com/realtime-framework/MessagingAndroidChat/blob/master/app/src/main/java/config/Config.java) file. If you don't already have a free Realtime® Framework application key, [get one now](https://accounts.realtime.co/signup/).** 17 | 18 | ## Prerequisites 19 | 20 | * [Download Android Studio](http://developer.android.com/sdk/installing/studio.html). 21 | 22 | * Under Tools / Android / Android SDK Manager make sure "Extras/Google Repository","Extras/Google Play services","Extras/Android Support Repository" and "Extras/Android Support Library", are installed. 23 | 24 | ## Documentation 25 | The Mobile Push Notifications Starting Guide can be found [here](http://messaging-public.realtime.co/documentation/starting-guide/mobilepush.html) 26 | 27 | The complete Realtime® Cloud Messaging reference documentation is available [here](http://framework.realtime.co/messaging/#documentation) 28 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion '25.0.0' 6 | 7 | defaultConfig { 8 | applicationId "co.realtime.messagingandroidchat" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'co.realtime:messaging-android:2.1.+' 26 | } 27 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/admin/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/co/realtime/messagingandroidchat/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package co.realtime.messagingandroidchat; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 37 | 38 | 41 | 42 | 45 | 46 | 47 | 50 | 51 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /app/src/main/java/co/realtime/messagingandroidchat/ChatRoomActivity.java: -------------------------------------------------------------------------------- 1 | package co.realtime.messagingandroidchat; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.ActionBarActivity; 5 | import android.view.Menu; 6 | import android.view.MenuItem; 7 | import android.view.View; 8 | import android.widget.Button; 9 | import android.widget.TableLayout; 10 | 11 | import java.util.List; 12 | 13 | import config.Config; 14 | import domains.Message; 15 | import handlers.OrtcHandler; 16 | import interfaces.InterfaceRefresher; 17 | import preferences.PreferencesManager; 18 | import ui.CustomTableRow; 19 | 20 | 21 | public class ChatRoomActivity extends ActionBarActivity implements InterfaceRefresher { 22 | private Boolean editing; 23 | private List channels; 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_chat_room); 29 | 30 | 31 | OrtcHandler.selfHandler.chatRoom = this; 32 | 33 | editing = false; 34 | 35 | channels = PreferencesManager.getInstance(ChatRoomActivity.this).loadChannels(); 36 | 37 | setChannels(); 38 | 39 | Button btEdit = (Button) this.findViewById(R.id.chatEditButton); 40 | btEdit.setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View v) { 43 | editing = !editing; 44 | 45 | Button btEdit = (Button) findViewById(R.id.chatEditButton); 46 | if (editing) { 47 | btEdit.setText(getString(R.string.doneLabel)); 48 | } else { 49 | PreferencesManager.getInstance(ChatRoomActivity.this).saveChannels(channels); 50 | btEdit.setText(R.string.editLabel); 51 | } 52 | clearChannelsList(); 53 | setChannels(); 54 | } 55 | }); 56 | } 57 | 58 | @Override 59 | protected void onResume(){ 60 | super.onResume(); 61 | clearChannelsList(); 62 | setChannels(); 63 | } 64 | 65 | @Override 66 | public boolean onCreateOptionsMenu(Menu menu) { 67 | getMenuInflater().inflate(R.menu.menu_chat_room, menu); 68 | return true; 69 | } 70 | 71 | @Override 72 | public boolean onOptionsItemSelected(MenuItem item) { 73 | int id = item.getItemId(); 74 | if (id == R.id.action_settings) { 75 | return true; 76 | } 77 | return super.onOptionsItemSelected(item); 78 | } 79 | 80 | @Override 81 | public void refreshData(Message msg) { 82 | runOnUiThread(new Runnable() { 83 | @Override 84 | public void run() { 85 | clearChannelsList(); 86 | setChannels(); 87 | } 88 | }); 89 | 90 | } 91 | 92 | public void addChat(String chatName) { 93 | channels.add(chatName); 94 | clearChannelsList(); 95 | setChannels(); 96 | } 97 | 98 | public void delChat(String chatName) { 99 | OrtcHandler.unsubscribeChannel(chatName); 100 | int index = this.channels.indexOf(chatName); 101 | channels.remove(index); 102 | 103 | clearChannelsList(); 104 | setChannels(); 105 | } 106 | 107 | private void setChannels() { 108 | TableLayout chatRoomsTable = (TableLayout) findViewById(R.id.chatRoomTable); 109 | if(channels.size() == 0) 110 | { 111 | editing = true; 112 | new CustomTableRow(this, chatRoomsTable, 113 | Config.CHANNEL_ADD, null); 114 | return; 115 | } 116 | if (editing) { 117 | for (String channel : channels) { 118 | new CustomTableRow(this, 119 | chatRoomsTable, Config.CHANNEL_DEL, channel); 120 | } 121 | CustomTableRow newRow = new CustomTableRow(this, chatRoomsTable, 122 | Config.CHANNEL_ADD, null); 123 | } else { 124 | for (String channel : channels) { 125 | new CustomTableRow(this, 126 | chatRoomsTable, Config.CHANNEL_NAME, channel); 127 | } 128 | } 129 | } 130 | 131 | private void clearChannelsList() { 132 | TableLayout chatRoomsTable = (TableLayout) findViewById(R.id.chatRoomTable); 133 | chatRoomsTable.removeAllViews(); 134 | } 135 | 136 | } 137 | -------------------------------------------------------------------------------- /app/src/main/java/co/realtime/messagingandroidchat/ComposeActivity.java: -------------------------------------------------------------------------------- 1 | package co.realtime.messagingandroidchat; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.ActionBarActivity; 5 | import android.text.Editable; 6 | import android.text.TextWatcher; 7 | import android.view.Menu; 8 | import android.view.MenuItem; 9 | import android.view.View; 10 | import android.widget.Button; 11 | import android.widget.EditText; 12 | import android.widget.TextView; 13 | 14 | import java.util.Date; 15 | 16 | import config.Config; 17 | import domains.Message; 18 | import handlers.OrtcHandler; 19 | import preferences.PreferencesManager; 20 | 21 | public class ComposeActivity extends ActionBarActivity { 22 | 23 | private String channel; 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_compose); 29 | 30 | this.channel = getIntent().getStringExtra("channel"); 31 | this.setTitle(this.channel); 32 | 33 | 34 | final TextView charNumber = (TextView) findViewById(R.id.charNumber); 35 | charNumber.setText( String.valueOf(Config.MSG_SIZE)); 36 | 37 | final EditText text = (EditText) this.findViewById(R.id.editMessage); 38 | 39 | text.addTextChangedListener(new TextWatcher(){ 40 | public void afterTextChanged(Editable s) { 41 | charNumber.setText(String.valueOf(Config.MSG_SIZE - text.getText().toString().length())); 42 | } 43 | public void beforeTextChanged(CharSequence s, int start, int count, int after){} 44 | public void onTextChanged(CharSequence s, int start, int before, int count){} 45 | }); 46 | 47 | Button save = (Button) this.findViewById(R.id.save); 48 | 49 | save.setOnClickListener(new View.OnClickListener() { 50 | 51 | @Override 52 | public void onClick(View v) { 53 | OrtcHandler.selfHandler.sendMsg(new Message(PreferencesManager.getInstance(ComposeActivity.this).loadUser(), text.getText().toString(), new Date().toString()), channel); 54 | finish(); 55 | } 56 | }); 57 | 58 | } 59 | 60 | @Override 61 | public boolean onCreateOptionsMenu(Menu menu) { 62 | getMenuInflater().inflate(R.menu.menu_compose, menu); 63 | return true; 64 | } 65 | 66 | @Override 67 | public boolean onOptionsItemSelected(MenuItem item) { 68 | int id = item.getItemId(); 69 | if (id == R.id.action_settings) { 70 | return true; 71 | } 72 | return super.onOptionsItemSelected(item); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/co/realtime/messagingandroidchat/MainActivity.java: -------------------------------------------------------------------------------- 1 | package co.realtime.messagingandroidchat; 2 | 3 | import android.content.Intent; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.support.v7.app.ActionBarActivity; 7 | import android.view.KeyEvent; 8 | import android.view.Menu; 9 | import android.view.MenuItem; 10 | import android.view.View; 11 | import android.view.inputmethod.EditorInfo; 12 | import android.widget.Button; 13 | import android.widget.EditText; 14 | import android.widget.TextView; 15 | 16 | import domains.Message; 17 | import handlers.OrtcHandler; 18 | import interfaces.InterfaceRefresher; 19 | import preferences.PreferencesManager; 20 | 21 | 22 | public class MainActivity extends ActionBarActivity implements InterfaceRefresher { 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_main); 28 | 29 | OrtcHandler.prepareClient(getApplicationContext(), this); 30 | 31 | EditText inputUser = (EditText) this.findViewById(R.id.nickNameInput); 32 | 33 | final Button bt = (Button) findViewById(R.id.chatRooms); 34 | bt.setEnabled(false); 35 | bt.setOnClickListener(new View.OnClickListener() { 36 | @Override 37 | public void onClick(View v) { 38 | Intent myIntent = new Intent(MainActivity.this, ChatRoomActivity.class); 39 | MainActivity.this.startActivity(myIntent); 40 | } 41 | }); 42 | 43 | String user = PreferencesManager.getInstance(this).loadUser(); 44 | 45 | if(user != null){ 46 | String welcomeLabel = String.format(getString(R.string.welcomeLabel), user); 47 | inputUser.setText(welcomeLabel); 48 | inputUser.setEnabled(false); 49 | }else{ 50 | inputUser.setOnEditorActionListener(new TextView.OnEditorActionListener() { 51 | @Override 52 | public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 53 | if (actionId == EditorInfo.IME_ACTION_DONE) { 54 | PreferencesManager.getInstance(MainActivity.this).saveUser(v.getText().toString()); 55 | v.setEnabled(false); 56 | 57 | if(OrtcHandler.selfHandler.isConnected){ 58 | bt.setEnabled(true); 59 | bt.setBackgroundColor(Color.WHITE); 60 | return true; 61 | } 62 | } 63 | return false; 64 | } 65 | 66 | }); 67 | } 68 | } 69 | 70 | @Override 71 | public boolean onCreateOptionsMenu(Menu menu) { 72 | getMenuInflater().inflate(R.menu.menu_main, menu); 73 | return true; 74 | } 75 | 76 | @Override 77 | public boolean onOptionsItemSelected(MenuItem item) { 78 | int id = item.getItemId(); 79 | if (id == R.id.action_settings) { 80 | return true; 81 | } 82 | return super.onOptionsItemSelected(item); 83 | } 84 | 85 | @Override 86 | public void refreshData(Message msg) { 87 | runOnUiThread(new Runnable() { 88 | @Override 89 | public void run() { 90 | TextView connectionLabel = (TextView)findViewById(R.id.connectionLabel); 91 | connectionLabel.setText(getString(R.string.ortcConnected)); 92 | Button chatRooms = (Button)findViewById(R.id.chatRooms); 93 | if(PreferencesManager.getInstance(MainActivity.this).loadUser() != null){ 94 | chatRooms.setEnabled(true); 95 | chatRooms.setBackgroundColor(Color.WHITE); 96 | } 97 | } 98 | }); 99 | 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /app/src/main/java/co/realtime/messagingandroidchat/MessageActivity.java: -------------------------------------------------------------------------------- 1 | package co.realtime.messagingandroidchat; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.ActionBarActivity; 6 | import android.view.Menu; 7 | import android.view.MenuItem; 8 | import android.view.View; 9 | import android.widget.Button; 10 | import android.widget.TableLayout; 11 | 12 | import java.util.List; 13 | 14 | import domains.Channel; 15 | import domains.Message; 16 | import handlers.OrtcHandler; 17 | import interfaces.InterfaceRefresher; 18 | import preferences.PreferencesManager; 19 | import ui.MessageTableRow; 20 | 21 | public class MessageActivity extends ActionBarActivity implements InterfaceRefresher { 22 | 23 | private String channel; 24 | private boolean pause; 25 | private static boolean mIsInForegroundMode; 26 | 27 | 28 | public String getChannel(){ 29 | return channel; 30 | } 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_message); 36 | 37 | Button composeBtn = (Button) findViewById(R.id.btCompose); 38 | composeBtn.setOnClickListener(new View.OnClickListener() { 39 | @Override 40 | public void onClick(View v) { 41 | Intent messages = new Intent(MessageActivity.this, 42 | ComposeActivity.class).putExtra("channel", channel); 43 | startActivity(messages); 44 | } 45 | }); 46 | } 47 | 48 | @Override 49 | protected void onResume() { 50 | super.onResume(); 51 | pause = false; 52 | mIsInForegroundMode = true; 53 | OrtcHandler.selfHandler.messagesView = this; 54 | channel = getIntent().getStringExtra("channel"); 55 | setTitle(channel); 56 | TableLayout tableMessages = (TableLayout) findViewById(R.id.tableMessages); 57 | tableMessages.removeAllViews(); 58 | loadMsg(); 59 | 60 | } 61 | 62 | @Override 63 | protected void onPause() { 64 | super.onPause(); 65 | pause = true; 66 | mIsInForegroundMode = false; 67 | } 68 | 69 | // Some function. 70 | public static boolean isInForeground() { 71 | return mIsInForegroundMode; 72 | } 73 | 74 | @Override 75 | public boolean onCreateOptionsMenu(Menu menu) { 76 | getMenuInflater().inflate(R.menu.menu_message, menu); 77 | return true; 78 | } 79 | 80 | @Override 81 | public boolean onOptionsItemSelected(MenuItem item) { 82 | int id = item.getItemId(); 83 | if (id == R.id.action_settings) { 84 | return true; 85 | } 86 | return super.onOptionsItemSelected(item); 87 | } 88 | 89 | private void loadMsg() { 90 | List messages = OrtcHandler.selfHandler.messages.get(channel).getMessages(); 91 | for (Message msg : messages) { 92 | setmsg(msg); 93 | } 94 | } 95 | 96 | private void setmsg(Message msg) { 97 | if(pause == false){ 98 | Channel cn = OrtcHandler.selfHandler.messages.get(channel); 99 | cn.setUnRead(0); 100 | } 101 | 102 | TableLayout tableMessages = (TableLayout) findViewById(R.id.tableMessages); 103 | 104 | if (msg.user.equals(PreferencesManager.getInstance(MessageActivity.this).loadUser())) { 105 | new MessageTableRow(this, tableMessages, true, msg); 106 | } else { 107 | new MessageTableRow(this, tableMessages, false, msg); 108 | } 109 | } 110 | 111 | @Override 112 | protected void onDestroy() { 113 | super.onDestroy(); 114 | } 115 | 116 | @Override 117 | public void refreshData(final Message msg) { 118 | runOnUiThread(new Runnable() { 119 | @Override 120 | public void run() { 121 | setmsg(msg); 122 | } 123 | }); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /app/src/main/java/co/realtime/messagingandroidchat/NotificationActivity.java: -------------------------------------------------------------------------------- 1 | package co.realtime.messagingandroidchat; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.ActionBarActivity; 5 | import android.text.Editable; 6 | import android.text.TextWatcher; 7 | import android.util.Log; 8 | import android.view.View; 9 | import android.view.inputmethod.InputMethodManager; 10 | import android.widget.Button; 11 | import android.widget.EditText; 12 | import android.widget.TableLayout; 13 | import android.widget.TextView; 14 | 15 | import java.text.SimpleDateFormat; 16 | import java.util.Date; 17 | 18 | import config.Config; 19 | import domains.Message; 20 | import ibt.ortc.api.Ortc; 21 | import ibt.ortc.extensibility.OnConnected; 22 | import ibt.ortc.extensibility.OnDisconnected; 23 | import ibt.ortc.extensibility.OnException; 24 | import ibt.ortc.extensibility.OnMessage; 25 | import ibt.ortc.extensibility.OnReconnected; 26 | import ibt.ortc.extensibility.OnReconnecting; 27 | import ibt.ortc.extensibility.OnSubscribed; 28 | import ibt.ortc.extensibility.OnUnsubscribed; 29 | import ibt.ortc.extensibility.OrtcClient; 30 | import ibt.ortc.extensibility.OrtcFactory; 31 | import preferences.PreferencesManager; 32 | import ui.MessageTableRow; 33 | 34 | 35 | public class NotificationActivity extends ActionBarActivity { 36 | 37 | private OrtcClient client; 38 | private String channel; 39 | private static boolean mIsInForegroundMode; 40 | final public static String ORTC_TAG = "ORTC"; 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | setContentView(R.layout.activity_notification); 46 | 47 | channel = getIntent().getStringExtra("channel"); 48 | setTitle(channel); 49 | 50 | String message = getIntent().getStringExtra("message"); 51 | String user = getIntent().getStringExtra("user"); 52 | refreshUI(user+":"+message); 53 | 54 | final TextView charNumber = (TextView) findViewById(R.id.charNumber); 55 | charNumber.setText( String.valueOf(260)); 56 | 57 | final EditText text = (EditText) this.findViewById(R.id.editMessage); 58 | 59 | text.addTextChangedListener(new TextWatcher(){ 60 | public void afterTextChanged(Editable s) { 61 | charNumber.setText("" + (260 - text.getText().toString().length())); 62 | } 63 | public void beforeTextChanged(CharSequence s, int start, int count, int after){} 64 | public void onTextChanged(CharSequence s, int start, int before, int count){} 65 | }); 66 | 67 | final Button saveBtn = (Button) findViewById(R.id.btnSave); 68 | saveBtn.setOnClickListener(new View.OnClickListener() { 69 | @Override 70 | public void onClick(View v) { 71 | String user = PreferencesManager.getInstance(NotificationActivity.this).loadUser(); 72 | String msg = text.getText().toString(); 73 | SimpleDateFormat sdf = new SimpleDateFormat(Config.DATE_FORMAT); 74 | client.send(channel,new Message(user,msg,sdf.format(new Date())).toString()); 75 | text.clearFocus(); 76 | InputMethodManager imm = (InputMethodManager)getSystemService( 77 | INPUT_METHOD_SERVICE); 78 | imm.hideSoftInputFromWindow(text.getWindowToken(), 0); 79 | } 80 | }); 81 | 82 | try { 83 | Ortc ortc = new Ortc(); 84 | 85 | OrtcFactory factory; 86 | 87 | factory = ortc.loadOrtcFactory("IbtRealtimeSJ"); 88 | 89 | client = factory.createClient(); 90 | 91 | client.setHeartbeatActive(true); 92 | 93 | } catch (Exception e) { 94 | } 95 | 96 | if (client != null) { 97 | try { 98 | 99 | client.onConnected = new OnConnected() { 100 | 101 | public void run(final OrtcClient sender) { 102 | runOnUiThread(new Runnable() { 103 | 104 | public void run() { 105 | Log.i(ORTC_TAG, "Connected"); 106 | client.subscribe(channel,true,new OnMessage() { 107 | @Override 108 | public void run(OrtcClient ortcClient, String channel, final String message) { 109 | runOnUiThread(new Runnable() { 110 | @Override 111 | public void run() { 112 | refreshUI(message); 113 | } 114 | }); 115 | 116 | } 117 | }); 118 | } 119 | }); 120 | } 121 | }; 122 | 123 | client.onDisconnected = new OnDisconnected() { 124 | 125 | public void run(OrtcClient arg0) { 126 | runOnUiThread(new Runnable() { 127 | 128 | public void run() { 129 | Log.i(ORTC_TAG, "Disconnected"); 130 | } 131 | }); 132 | } 133 | }; 134 | 135 | client.onSubscribed = new OnSubscribed() { 136 | 137 | public void run(OrtcClient sender, final String channel) { 138 | runOnUiThread(new Runnable() { 139 | 140 | public void run() { 141 | Log.i(ORTC_TAG, "Subscribed to " + channel); 142 | saveBtn.setEnabled(true); 143 | } 144 | }); 145 | } 146 | }; 147 | 148 | client.onUnsubscribed = new OnUnsubscribed() { 149 | 150 | public void run(OrtcClient sender, final String channel) { 151 | runOnUiThread(new Runnable() { 152 | 153 | public void run() { 154 | Log.i(ORTC_TAG, "Unsubscribed from " + channel); 155 | } 156 | }); 157 | } 158 | }; 159 | 160 | client.onException = new OnException() { 161 | 162 | public void run(OrtcClient send, final Exception ex) { 163 | runOnUiThread(new Runnable() { 164 | 165 | public void run() { 166 | Log.e(ORTC_TAG, "Exception " + ex.toString()); 167 | } 168 | }); 169 | } 170 | }; 171 | 172 | client.onReconnected = new OnReconnected() { 173 | 174 | public void run(final OrtcClient sender) { 175 | runOnUiThread(new Runnable() { 176 | 177 | public void run() { 178 | Log.i(ORTC_TAG, "Reconnected"); 179 | } 180 | }); 181 | } 182 | }; 183 | 184 | client.onReconnecting = new OnReconnecting() { 185 | 186 | public void run(OrtcClient sender) { 187 | runOnUiThread(new Runnable() { 188 | 189 | public void run() { 190 | Log.i(ORTC_TAG, "Reconnecting"); 191 | 192 | } 193 | }); 194 | } 195 | }; 196 | } catch (Exception e) { 197 | Log.e("Exception ",e.toString()); 198 | } 199 | 200 | client.setConnectionMetadata(Config.METADATA); 201 | 202 | if(Config.CLUSTERURL != null){ 203 | client.setClusterUrl(Config.CLUSTERURL); 204 | } else { 205 | client.setUrl(Config.CLUSTERURL); 206 | } 207 | client.connect(Config.APPKEY, Config.TOKEN); 208 | } 209 | 210 | 211 | } 212 | 213 | @Override 214 | protected void onPause() { 215 | super.onPause(); 216 | mIsInForegroundMode = false; 217 | } 218 | 219 | @Override 220 | protected void onResume() { 221 | super.onResume(); 222 | mIsInForegroundMode = true; 223 | } 224 | 225 | public static boolean isInForeground() { 226 | return mIsInForegroundMode; 227 | } 228 | 229 | private void refreshUI(String message){ 230 | String[] parts = message.split(":"); 231 | Message newMsg = new Message(parts[0], parts[1], new Date().toString()); 232 | 233 | TableLayout tableMessages = (TableLayout) findViewById(R.id.tableMessages); 234 | 235 | if (newMsg.user.equals(PreferencesManager.getInstance(NotificationActivity.this).loadUser())) { 236 | new MessageTableRow(NotificationActivity.this, tableMessages, true, newMsg); 237 | } else { 238 | new MessageTableRow(NotificationActivity.this, tableMessages, false, newMsg); 239 | } 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /app/src/main/java/config/Config.java: -------------------------------------------------------------------------------- 1 | package config; 2 | 3 | public final class Config { 4 | 5 | final public static String CLUSTERURL = "http://ortc-developers.realtime.co/server/2.1/"; 6 | final public static String URL = null; 7 | final public static String METADATA = "androidApp"; 8 | final public static String TOKEN = "token"; 9 | final public static String APPKEY = "YOUR_APPLICATION_KEY"; 10 | final public static String PROJECT_ID = "YOUR_FIREBASE_SENDER_ID"; 11 | 12 | 13 | final public static int CHANNEL_NAME = 1; 14 | final public static int CHANNEL_ADD = 2; 15 | final public static int CHANNEL_DEL = 3; 16 | final public static int MSG_SIZE = 260; 17 | 18 | final public static String DATE_FORMAT = "yyyy-MM-dd HH:mm"; 19 | 20 | private Config() throws InstantiationException { 21 | throw new InstantiationException("This class is not created for instantiation"); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/domains/Channel.java: -------------------------------------------------------------------------------- 1 | package domains; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Channel { 7 | private final String name; 8 | private final List messages; 9 | private int unRead; 10 | 11 | public Channel(String name) { 12 | this.name = name; 13 | this.messages = new ArrayList<>(); 14 | this.unRead = 0; 15 | } 16 | 17 | public void addMessage(Message msg) 18 | { 19 | this.messages.add(msg); 20 | } 21 | 22 | public List getMessages(){ 23 | return this.messages; 24 | } 25 | 26 | public int getUnRead() { 27 | return unRead; 28 | } 29 | 30 | public void setUnRead(int unRead) { 31 | this.unRead = unRead; 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/domains/Message.java: -------------------------------------------------------------------------------- 1 | package domains; 2 | 3 | public class Message { 4 | public String user; 5 | public String content; 6 | public String date; 7 | 8 | public Message(String user, String content, String date) { 9 | this.user = user; 10 | this.content = content; 11 | this.date = date; 12 | } 13 | 14 | @Override 15 | public String toString(){ 16 | return this.user + ":" + this.content; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/handlers/OrtcHandler.java: -------------------------------------------------------------------------------- 1 | package handlers; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import java.text.SimpleDateFormat; 7 | import java.util.*; 8 | 9 | import co.realtime.messagingandroidchat.MessageActivity; 10 | import config.Config; 11 | import domains.Channel; 12 | import domains.Message; 13 | import ibt.ortc.api.Ortc; 14 | import ibt.ortc.extensibility.OnConnected; 15 | import ibt.ortc.extensibility.OnDisconnected; 16 | import ibt.ortc.extensibility.OnException; 17 | import ibt.ortc.extensibility.OnMessage; 18 | import ibt.ortc.extensibility.OnReconnected; 19 | import ibt.ortc.extensibility.OnReconnecting; 20 | import ibt.ortc.extensibility.OnSubscribed; 21 | import ibt.ortc.extensibility.OnUnsubscribed; 22 | import ibt.ortc.extensibility.OrtcClient; 23 | import ibt.ortc.extensibility.OrtcFactory; 24 | import interfaces.InterfaceRefresher; 25 | import preferences.PreferencesManager; 26 | 27 | public class OrtcHandler{ 28 | 29 | public static OrtcHandler selfHandler; 30 | 31 | public static OrtcClient client = null; 32 | public Map messages; 33 | public Boolean isConnected; 34 | public InterfaceRefresher rootView; 35 | public Context context; 36 | public InterfaceRefresher chatRoom; 37 | public InterfaceRefresher messagesView; 38 | 39 | final public static String ORTC_TAG = "ORTC"; 40 | 41 | public static void subscribeChannel(String channel) 42 | { 43 | selfHandler.messages.put(channel, new Channel(channel)); 44 | 45 | client.subscribeWithNotifications(channel, true, new OnMessage() { 46 | public void run(OrtcClient sender, String channel, String message) { 47 | selfHandler.handleMessage(message, channel); 48 | } 49 | ; 50 | }); 51 | } 52 | 53 | 54 | public static void unsubscribeChannel(String channel) 55 | { 56 | client.unsubscribe(channel); 57 | } 58 | 59 | public static void prepareClient(Context context, InterfaceRefresher rootView){ 60 | selfHandler = new OrtcHandler(); 61 | selfHandler.context = context; 62 | selfHandler.rootView = rootView; 63 | selfHandler.messages = new HashMap<>(); 64 | 65 | Ortc api = new Ortc(); 66 | OrtcFactory factory; 67 | try { 68 | factory = api.loadOrtcFactory("IbtRealtimeSJ"); 69 | client = factory.createClient(); 70 | client.setConnectionMetadata(Config.METADATA); 71 | 72 | if(Config.CLUSTERURL != null){ 73 | client.setClusterUrl(Config.CLUSTERURL); 74 | } else { 75 | client.setUrl(Config.URL); 76 | } 77 | 78 | client.setApplicationContext(selfHandler.context); 79 | client.setGoogleProjectId(Config.PROJECT_ID); 80 | 81 | client.onConnected = new OnConnected(){ 82 | @Override 83 | public void run(OrtcClient sender) { 84 | selfHandler.isConnected = true; 85 | 86 | List channels = PreferencesManager.getInstance(selfHandler.context).loadChannels(); 87 | for (String channel : channels) { 88 | subscribeChannel(channel); 89 | } 90 | selfHandler.rootView.refreshData(null); 91 | } 92 | }; 93 | client.onDisconnected = new OnDisconnected(){ 94 | @Override 95 | public void run(OrtcClient sender) { 96 | Log.i(ORTC_TAG, "Disconnected"); 97 | 98 | } 99 | }; 100 | client.onSubscribed = new OnSubscribed(){ 101 | @Override 102 | public void run(OrtcClient sender, String channel) { 103 | Log.i(ORTC_TAG, "Subscribed to " + channel); 104 | } 105 | }; 106 | client.onUnsubscribed = new OnUnsubscribed(){ 107 | @Override 108 | public void run(OrtcClient sender, String channel) { 109 | Log.i(ORTC_TAG, "Unsubscribed from " + channel); 110 | } 111 | }; 112 | client.onException = new OnException(){ 113 | @Override 114 | public void run(OrtcClient sender, Exception exc) { 115 | Log.e(ORTC_TAG, "Exception " + exc.toString()); 116 | } 117 | }; 118 | client.onReconnected = new OnReconnected(){ 119 | @Override 120 | public void run(OrtcClient sender) { 121 | Log.i(ORTC_TAG, "Reconnected"); 122 | } 123 | }; 124 | client.onReconnecting = new OnReconnecting(){ 125 | @Override 126 | public void run(OrtcClient sender) { 127 | Log.i(ORTC_TAG, "Reconnecting"); 128 | } 129 | }; 130 | 131 | client.connect(Config.APPKEY, Config.TOKEN); 132 | 133 | } catch (Exception e) { 134 | Log.e("Exception ",e.toString()); 135 | } 136 | } 137 | 138 | public void sendMsg(Message msg, String channel) { 139 | OrtcHandler.client.send(channel, msg.toString()); 140 | } 141 | 142 | public void handleMessage(String msg, String channel){ 143 | SimpleDateFormat sdf = new SimpleDateFormat(Config.DATE_FORMAT); 144 | Message newMsg = null; 145 | if(msg.contains(":")) 146 | { 147 | newMsg = new Message(msg.substring(0, msg.indexOf(':')), msg.substring(msg.indexOf(':') + 1), sdf.format(new Date())); 148 | } 149 | else { 150 | newMsg = new Message("Unknown user", msg, sdf.format(new Date())); 151 | } 152 | 153 | Channel list = messages.get(channel); 154 | list.setUnRead(list.getUnRead() + 1); 155 | list.addMessage(newMsg); 156 | 157 | if(messagesView != null && ((MessageActivity)messagesView).getChannel().equals(channel)) 158 | messagesView.refreshData(newMsg); 159 | 160 | if(chatRoom != null) 161 | chatRoom.refreshData(newMsg); 162 | 163 | } 164 | 165 | } 166 | -------------------------------------------------------------------------------- /app/src/main/java/interfaces/InterfaceRefresher.java: -------------------------------------------------------------------------------- 1 | package interfaces; 2 | 3 | import domains.Message; 4 | 5 | public interface InterfaceRefresher { 6 | void refreshData(Message msg); 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/preferences/PreferencesManager.java: -------------------------------------------------------------------------------- 1 | package preferences; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.preference.PreferenceManager; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class PreferencesManager { 11 | 12 | private final SharedPreferences settings; 13 | 14 | public static String USER = "USER"; 15 | public static String CHANNELS = "CHANNELS"; 16 | 17 | private static PreferencesManager preferencesManagerManager; 18 | 19 | private PreferencesManager(SharedPreferences sp) { 20 | settings = sp; 21 | } 22 | 23 | public static PreferencesManager getInstance(Context ctx) { 24 | if (preferencesManagerManager == null) { 25 | preferencesManagerManager = new PreferencesManager(PreferenceManager.getDefaultSharedPreferences(ctx)); 26 | } 27 | return preferencesManagerManager; 28 | } 29 | 30 | public String loadUser(){ 31 | return settings.getString(USER,null); 32 | } 33 | 34 | public void saveUser(String novaVersao){ 35 | SharedPreferences.Editor e = settings.edit(); 36 | e.putString(USER,novaVersao); 37 | e.commit(); 38 | } 39 | 40 | public List loadChannels(){ 41 | String channels = settings.getString(CHANNELS,null); 42 | if(channels == null) 43 | { 44 | return new ArrayList<>(); 45 | } 46 | 47 | String[] parts = channels.split(","); 48 | 49 | List list = new ArrayList<>(); 50 | 51 | for (String channel : parts) { 52 | list.add(channel); 53 | } 54 | return list; 55 | } 56 | 57 | public void saveChannels(List channels){ 58 | SharedPreferences.Editor e = settings.edit(); 59 | StringBuilder channelsString = new StringBuilder(); 60 | 61 | for (String channel : channels) { 62 | channelsString.append(channel).append(","); 63 | } 64 | 65 | e.putString(CHANNELS,channelsString.toString()); 66 | e.commit(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/receiver/GcmReceiver.java: -------------------------------------------------------------------------------- 1 | package receiver; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationManager; 5 | import android.app.PendingIntent; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.os.Bundle; 9 | import android.support.v4.app.NotificationCompat; 10 | import android.util.Log; 11 | 12 | import java.util.regex.Pattern; 13 | 14 | import co.realtime.messagingandroidchat.MessageActivity; 15 | import co.realtime.messagingandroidchat.NotificationActivity; 16 | import co.realtime.messagingandroidchat.R; 17 | import ibt.ortc.extensibility.GcmOrtcBroadcastReceiver; 18 | import ibt.ortc.plugins.IbtRealtimeSJ.OrtcMessage; 19 | 20 | 21 | public class GcmReceiver extends GcmOrtcBroadcastReceiver { 22 | 23 | private static final String TAG = "GcmReceiver"; 24 | private static final String MESSAGE_PATTERN = "^(.[^_]*)_(.[^-]*)-(.[^_]*)_([\\s\\S]*?)$"; 25 | private static final Pattern messagePattern = Pattern.compile(MESSAGE_PATTERN); 26 | 27 | public GcmReceiver() { 28 | } 29 | 30 | @Override 31 | public void onReceive(Context context, Intent intent) { 32 | Log.d(TAG, "Received message"); 33 | Bundle extras = intent.getExtras(); 34 | if (extras != null && !MessageActivity.isInForeground() && !NotificationActivity.isInForeground()) { 35 | createNotification(context, extras); 36 | } 37 | } 38 | 39 | public void createNotification(Context context, Bundle extras) 40 | { 41 | String message = extras.getString("M"); 42 | String channel = extras.getString("C"); 43 | String payload = extras.getString("P"); // this is only used by custom notifications 44 | 45 | if (message != "") { 46 | 47 | String parsedMessage = OrtcMessage.parseOrtcMultipartMessage(message); 48 | 49 | 50 | if(payload != null) { 51 | Log.i(TAG, String.format("Custom push notification on channel: %s message: %s payload: %s", channel, parsedMessage, payload)); 52 | }else{ 53 | Log.i(TAG, String.format("Automatic push notification on channel: %s message: %s ", channel, parsedMessage)); 54 | } 55 | 56 | try { 57 | 58 | // parsed message format: : 59 | String user = null; 60 | String chatMessage = null; 61 | if(parsedMessage.contains(":")) 62 | { 63 | user = parsedMessage.substring(0, parsedMessage.indexOf(':')); 64 | chatMessage = parsedMessage.substring(parsedMessage.indexOf(':') + 1); 65 | } 66 | else { 67 | user = "Unknown user"; 68 | chatMessage = parsedMessage; 69 | } 70 | 71 | 72 | NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 73 | Intent notificationIntent = new Intent(context, NotificationActivity.class); 74 | 75 | notificationIntent.putExtra("channel", channel); 76 | notificationIntent.putExtra("message", chatMessage); 77 | notificationIntent.putExtra("user", user); 78 | 79 | String appName = getAppName(context); 80 | 81 | notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 82 | PendingIntent pendingIntent = PendingIntent.getActivity(context, 9999, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); 83 | 84 | Notification notification = new NotificationCompat.Builder(context).setContentTitle(channel).setContentText(chatMessage).setSmallIcon(R.drawable.ic_launcher) 85 | .setContentIntent(pendingIntent).setAutoCancel(true).build(); 86 | notificationManager.notify(appName, 9999, notification); 87 | 88 | } catch (Exception e) { 89 | e.printStackTrace(); 90 | } 91 | 92 | } 93 | } 94 | 95 | private String getAppName(Context context) 96 | { 97 | CharSequence appName = 98 | context 99 | .getPackageManager() 100 | .getApplicationLabel(context.getApplicationInfo()); 101 | 102 | return (String)appName; 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/ui/CustomTableRow.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.graphics.Color; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.widget.Button; 9 | import android.widget.EditText; 10 | import android.widget.TableLayout; 11 | import android.widget.TableRow; 12 | import android.widget.TextView; 13 | 14 | import co.realtime.messagingandroidchat.ChatRoomActivity; 15 | import co.realtime.messagingandroidchat.MessageActivity; 16 | import co.realtime.messagingandroidchat.R; 17 | import config.Config; 18 | import domains.Channel; 19 | import handlers.OrtcHandler; 20 | 21 | public class CustomTableRow extends TableRow { 22 | 23 | private final String content; 24 | private final TableLayout container; 25 | private final Context context; 26 | 27 | public CustomTableRow(Context context, TableLayout container, int type,String content) { 28 | super(context); 29 | 30 | this.content = content; 31 | this.container = container; 32 | this.context = context; 33 | 34 | switch (type) { 35 | case Config.CHANNEL_NAME: 36 | setChannelName(); 37 | break; 38 | 39 | case Config.CHANNEL_ADD: 40 | setChannelAdd(); 41 | break; 42 | 43 | case Config.CHANNEL_DEL: 44 | setChannelDel(); 45 | break; 46 | default: 47 | break; 48 | } 49 | } 50 | 51 | private void setChannelDel() { 52 | LayoutInflater inflater = (LayoutInflater) context 53 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 54 | View tr = inflater.inflate(R.layout.delchannel, null, false); 55 | TextView text = (TextView) tr.findViewById(R.id.delLabel); 56 | text.setText(content); 57 | Button delBt = (Button) tr.findViewById(R.id.delButton); 58 | delBt.setTextColor(Color.WHITE); 59 | delBt.setOnClickListener(new OnClickListener() { 60 | 61 | @Override 62 | public void onClick(View v) { 63 | ChatRoomActivity chatController = (ChatRoomActivity) context; 64 | chatController.delChat(content); 65 | } 66 | }); 67 | 68 | container.addView(tr); 69 | } 70 | 71 | private void setChannelAdd() { 72 | LayoutInflater inflater = (LayoutInflater) context 73 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 74 | View tr = inflater.inflate(R.layout.addchannel, null, false); 75 | Button addBt = (Button) tr.findViewById(R.id.addButton); 76 | addBt.setTextColor(Color.WHITE); 77 | final EditText newChannel = (EditText) tr.findViewById(R.id.addEdit); 78 | 79 | addBt.setOnClickListener(new OnClickListener() { 80 | 81 | @Override 82 | public void onClick(View v) { 83 | if (!newChannel.getText().toString().equals("")) { 84 | OrtcHandler.subscribeChannel(newChannel.getText() 85 | .toString()); 86 | ChatRoomActivity chatController = (ChatRoomActivity) context; 87 | chatController.addChat(newChannel.getText().toString()); 88 | } 89 | } 90 | }); 91 | container.addView(tr); 92 | } 93 | 94 | private void setChannelName() { 95 | LayoutInflater inflater = (LayoutInflater) context 96 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 97 | View tr = inflater.inflate(R.layout.channel, null, false); 98 | tr.setOnClickListener(new OnClickListener() { 99 | 100 | @Override 101 | public void onClick(View v) { 102 | Intent messages = new Intent(context, MessageActivity.class) 103 | .putExtra("channel", content); 104 | context.startActivity(messages); 105 | } 106 | }); 107 | TextView text = (TextView) tr.findViewById(R.id.channelName); 108 | text.setText(this.content); 109 | container.addView(tr); 110 | setUnread(tr); 111 | } 112 | 113 | private void setUnread(View tr) { 114 | TextView unRead = (TextView) tr.findViewById(R.id.unRead); 115 | Channel channelRef = OrtcHandler.selfHandler.messages.get(content); 116 | if (channelRef.getUnRead() > 0) 117 | unRead.setText( String.valueOf(channelRef.getUnRead()) ); 118 | else { 119 | unRead.setText(""); 120 | } 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /app/src/main/java/ui/MessageTableRow.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.widget.TableLayout; 7 | import android.widget.TableRow; 8 | import android.widget.TextView; 9 | 10 | import co.realtime.messagingandroidchat.R; 11 | import domains.Message; 12 | 13 | public class MessageTableRow extends TableRow { 14 | 15 | private final Boolean isFromUser; 16 | private final Context context; 17 | private final Message msg; 18 | private final TableLayout tableMessages; 19 | 20 | public MessageTableRow(Context context, TableLayout tableMessages, Boolean fromUser, Message msg) { 21 | super(context); 22 | this.msg = msg; 23 | this.context = context; 24 | this.isFromUser = fromUser; 25 | this.tableMessages = tableMessages; 26 | 27 | this.setMessage(); 28 | } 29 | 30 | private void setMessage() { 31 | if (isFromUser) { 32 | setFromUserCell(); 33 | } else { 34 | setFromOtherCell(); 35 | } 36 | } 37 | 38 | private void setFromUserCell() { 39 | LayoutInflater inflater = (LayoutInflater) context 40 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 41 | View tr = inflater.inflate(R.layout.cellsend, null, false); 42 | TextView user = (TextView)tr.findViewById(R.id.user); 43 | user.setText(msg.user +": "+ msg.date); 44 | TextView text = (TextView)tr.findViewById(R.id.text); 45 | text.setText(msg.content); 46 | tableMessages.addView(tr); 47 | } 48 | 49 | private void setFromOtherCell() { 50 | LayoutInflater inflater = (LayoutInflater) context 51 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 52 | View tr = inflater.inflate(R.layout.cellreceive, null, false); 53 | TextView user = (TextView)tr.findViewById(R.id.user); 54 | user.setText(msg.user +": "+ msg.date); 55 | TextView text = (TextView)tr.findViewById(R.id.text); 56 | text.setText(msg.content); 57 | tableMessages.addView(tr); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/realtime-framework/MessagingAndroidChat/bd5270fe87451345442b30c8670e775166f30b64/app/src/main/res/drawable-hdpi/background.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ballon_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/realtime-framework/MessagingAndroidChat/bd5270fe87451345442b30c8670e775166f30b64/app/src/main/res/drawable-hdpi/ballon_left.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ballon_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/realtime-framework/MessagingAndroidChat/bd5270fe87451345442b30c8670e775166f30b64/app/src/main/res/drawable-hdpi/ballon_right.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/btn_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/realtime-framework/MessagingAndroidChat/bd5270fe87451345442b30c8670e775166f30b64/app/src/main/res/drawable-hdpi/btn_add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/btn_del.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/realtime-framework/MessagingAndroidChat/bd5270fe87451345442b30c8670e775166f30b64/app/src/main/res/drawable-hdpi/btn_del.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_action_rt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/realtime-framework/MessagingAndroidChat/bd5270fe87451345442b30c8670e775166f30b64/app/src/main/res/drawable-hdpi/ic_action_rt.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/speech_bubble_green.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/realtime-framework/MessagingAndroidChat/bd5270fe87451345442b30c8670e775166f30b64/app/src/main/res/drawable-hdpi/speech_bubble_green.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/speech_bubble_orange.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/realtime-framework/MessagingAndroidChat/bd5270fe87451345442b30c8670e775166f30b64/app/src/main/res/drawable-hdpi/speech_bubble_orange.9.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_chat_room.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 |