Build a Real-Time Chat Application With Pusher and Laravel 5.1

To build a real-time chat application on laravel, we decided to use Pusher. Unfortunately Pusher isn’t open source but it does have a reasonable free package. We will implement a real-time chat application with Laravel, Mysql and Pusher.

The Scenario
1. A user will open the chat application in a browser and provides a nickname to continue the chat.
2. The user will enter some text and clicks the Send button.
3. The message will be handled by a service written using Laravel 5.1.
4. The message will be sent to Pusher in order to trigger a new message event to broadcast that message to connected clients.
5. The new message will be acquired by the clients, and the chat message list will be sent to all connected clients.

Laravel Project Setup

Of course, first we will need a fresh installation of the Laravel framework. You may install the Laravel framework using Composer:

composer create-project laravel/laravel laravel-pusher 5.1

Database
Our application will interact with a database, and it will be Mysql. Create a database with any name here we have created with name laravel_pusher. And create a table for users to store nickname of users and handle authentication.
Edit the users migration file and add some additional fields for our channel :

$table->increments('id');
$table->string('name');
$table->integer('chat_room_id')->unsigned();
$table->foreign('chat_room_id')->references('id')->on('chat_rooms')- >onDelete('CASCADE');
$table->timestamps();

Create another table ‘chat_rooms’ to handle channels from our database. Let’s use the make:migration command to generate a new database migration for our ‘chat_rooms’ table:

php artisan make:migration create_chat_rooms_table --create=chat_rooms

Now edit this file and add an additional string column for the name of our channels :

$table->increments('id');
$table->string('name');
$table->timestamps();

Model
We have to create models to access tables in our database. We will create two models User.php and ChatRoom.php in App/Http folder.
Edit User model with following code :

protected $table = 'users';
protected $fillable = array('name','chat_room_id');
public function chat_rooms()
{
return $this->belongsTo('App\ChatRoom', 'chat_room_id');
}

And ChatRoom model with following code:

protected $table = 'chat_rooms';
protected $fillable = array('name');

Pusher

Pusher provides a service to trigger events for real-time communication. You can go the Pusher Website to get one.

After successful account and application creation, you will be able to get some credentials like App ID, App Secret, and App Key. For this application we’ll use package vinkla/pusher. In order to install this package and use Pusher class in your Laravel project, you have to do the following:

1. Run following  command in your terminal to install vinkla/pusher pakage :

composer require vinkla/pusher

2. Add the following Pusher package to the config/app.php :

Vinkla\Pusher\PusherServiceProvider::class,

3. Add the reference in config/app.php to your aliases array as

'LaravelPusher' => Vinkla\Pusher\Facades\Pusher::class

Note that we have aliased facades as LaravelPusher instead of Pusher.
4. In your terminal publish the Pusher configuration file with this command

 php artisan vendor:publish

This command will create a config file config/pusher.php, and you need to provide the required credentials that you can find in your Pusher dashboard. The config file will be like below:

'connections' => [

'main' => [
'auth_key' => env('PUSHER_KEY'),
'secret' => env('PUSHER_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [],
'host' => null, %MCEPASTEBIN%
'port' => null,
'timeout' => null,
],

'alternative' => [
'auth_key' => 'your-auth-key',
'secret' => 'your-secret',
'app_id' => 'your-app-id',
'options' => [],
'host' => null,
'port' => null,
'timeout' => null,
],

Route

You can add your route configurations to the file app/Http/Route.php as below :

Route::get('/', 'ChatController@index');
Route::get('chat', 'ChatController@index');
Route::get('chat/chat', 'ChatController@chat');
Route::post('/chat/subscribe', 'ChatController@store');
Route::post('chat/getMessage', 'ChatController@getMessage');
Route::get('auth/logout', 'Auth\AuthController@getLogout');

Controller

In order to create a controller, simply create a file ChatController.php in App/Controllers folder and make that class extend a Laravel-specific class Controller which exists in App\Http\Controllers.

When you request the /chat endpoint, they will render their own templates under resources/views. You can do that by using the following actions:

public function index(){
return view('chat.index');
}

public function chat(){
$user = Auth::user();
return view('chat.chat',compact('user'));
}

This methods will render specific pages.

Now we need to save the nickname by entered by user and authenticate. If the nickname exists we will authenticate by using that nickname for chat perticular channel.

public function store(Request $request)
{
$pusher_user['name'] = $request->name;
$pusher_user['chat_room_id'] = $request->chat_room_id;
$user = User::firstOrCreate($pusher_user);
Auth::loginUsingId($user->id);
return redirect('/chat/chat');
}

This method will authenticate user’s based on thier nickname and channel name.

When we authenticate user and redirect user to the chat view. User will enter message and send to the user. For this we need to send message to the pusher first by triggering the event.

public function getMessage(Request $request)
{
$user = Auth::user();
$channel = $user->chat_rooms['name'];

LaravelPusher::trigger($channel, 'message', array('message'=>$request->msj,'sender_name'=>$user->name),$request->socket_id);
echo json_encode(array('message'=>$request->msj));
}

This method method will trigger the event with the message by the user and we are also sending user name to display in application and socket_id. Note that this method will be called by an ajax call.

View

we have used the Blade template engine provided by Laravel. We have two view pages: index.blade.php and chat.blade.php in resources/views/chat folder.

First we create simple login page using html form in index.blade.php asking for user’s nickname and select channel like this :

Screenshot from 2016-03-16 16:52:02

Assign action as action=”{{url(‘/chat/subscribe’)}}” and method as method=”POST”.

Now create a view for real-time chatting with users logged in with specific channel in chat.blade.php like this:

Screenshot from 2016-03-16 17:10:49

In this page to send messages create a html form with action as action=”” and method method=”POST” and we will submit this form with ajax.
Now, We have a chat form to send messages, and Laravel puts a meta description in the page:

<meta name="csrf-token" content="{{ csrf_token() }}">

However, we are sending a chat message via AJAX, and there are no tokens in the AJAX request headers. We provide a solution by using the following code snippet:

$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});

Whenever you send an AJAX request, this token will be put inside the header.

To submit this form we will make ajax call as follows :

$('form').submit(function(){
$.post('getMessage', { msj: $('#enter_message').val(),soket_id: pusher.connection.socket_id}, function(response){

$("#comments").animate({ scrollTop: $(document).height() }, 0);
}, 'json');
document.getElementById('enter_message').value = "";

return false;
});

This will make an ajax call to getMessage method in ChatController.

In order to listen to the message channel in real time, we have used the following:

$(function(){
Pusher.log = function(message) {
if (window.console && window.console.log) {
window.console.log(message);
}
};
var pusher = new Pusher('54333db710da73106b7c', {
encrypted: true
});

var channel = pusher.subscribe();

channel.bind('message', function(response) {

$('#comments').append('

'+response.message+'
');

var sender_name = response;

if ( == sender_name.sender_name)
{
$('#comments').append('

-'+response.sender_name+'
');
}
else
$('#comments').append('

-'+response.sender_name+'
');

$("#comments").animate({ scrollTop: $(document).height() }, 0);

});

Here, we have pusher object with appId. And then, a client is subscribed to the channel. Whenever a new event with the name message and specific channel name arrives, a callback function will be executed inside the bind() function. The message list area will be appended with the new messages and the sender name also be appended below it as we are sending sender name from controller by triggering pusher event.

Why we used Pusher

Pusher has a nice channel/event model where you can subscribe to a channel, and then bind callbacks to specific events over that channel. This is a pretty natural way to implement message events.
Pusher supports SSL and SSL provides client to server encryption.
Overall, We’ve found that Pusher has better documentation/examples, a better API, and better backend/debug tools.

Limitations

  • Pusher has no server-side caching. This means that missed messages remained missed, there is a much higher chance of messages not getting through.
  • Pusher’s limits are 10kb per message as part of their normal offering. They offer larger message sizes for enterprise plans.

Conclusion

In this tutorial we have shown you how to setup Pusher with Laravel 5.1. We have used pusher to send realtime notifications.
We have focused on the real-time chat application in Laravel and saw that the Pusher libraries are very easy to handle thanks to Pusher.

How to use ProGuard – Android

One of the biggest challenges we found while developing Android Applications is the ease with which they can be decompiled. There are many tools available today in the market, which let you decompile an APK and allow you to peek into internal classes, methods and APIs. Such information in the hands of an intruder can cause serious damage to your application.

Luckily, the solution to fix this is a quick 5-minute fix – Using Proguard.

About ProGuard :

The ProGuard tool is essentially a Java class that obfuscates your code and makes it tough to reverse engineer your app. It also renames your classes and fields using short meaningless names, thereby making no sense to anyone peeking into the code.

Finally, it pre-verifies the processed code and as a result, we get a smaller sized apk that is difficult to reverse engineer.

Outlined uses for ProGuard:

  • Create code with low impact on memory and faster loading of application.
  • Make programs and libraries harder to reverse-engineer.
  • Leave out the dead and unused code.

Using ProGuard

Enabling Proguard in Gradle is as simple as setting the value of minifyEnabled as true

For ex :

release  {
            	minifyEnabled true
            	shrinkResources true
            	proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
           }

debug  {
            	minifyEnabled true
            	shrinkResources true
            	proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }

The above code simply tells the SDK to enable proguard for the release ( as well as debug ) configurations.

By default, the rules are loaded from proguard-android.txt. But you can specify an additional file, in this case ‘proguard-rules.pro’ to add some additional rules specific to your project.

Understanding ProGuard Rules

ProGuard can sometimes be annoying with errors and warnings of some external libraries added in your project. At times like these, you can use a custom proguard rule file to manage this.
This is how one of our proguard rule file usually looks like.

-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }
-keep public class android.support.v7.widget.** { *; }
-keep public class android.support.v7.internal.widget.** { *; }
-keep public class android.support.v7.internal.view.menu.** { *; }

-keep public class * extends android.support.v4.view.ActionProvider {
    public <init>(android.content.Context);
}
-keep class * extends java.util.ListResourceBundle {
    protected Object[][] getContents();
}
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
    public static final *** NULL;
}
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
    @com.google.android.gms.common.annotation.KeepName *;
}
-keepnames class * implements android.os.Parcelable {
    public static final ** CREATOR;
}

Some of the most important commands in ProGuard rules are keep, keepclassmembernames, keepnames and dontwarn.

keep specifies which class and class members are to be preserved during the entry point.

keepclassmembernames specifies which members of the class are to be preserved, if their classes are preserved as well.

keepnames preserves classes and class members whose names are to be preserved.

dontwarn specifies not to warn about unresolved references.

For a complete list of proguard rules – refer here

Using Multiple ProGuard files

Multiple ProGuard files can be kept under the release section. The code could be written in the following manner :

release {
            debuggable false
            minifyEnabled true
            proguardFile 'proguard-bugsense.txt’
            proguardFile 'proguard-google-play-services.txt'
            proguardFile 'proguard-gson.txt'
            proguardFile 'proguard-project.txt'
            proguardFile getDefaultProguardFile('proguard-android.txt')
        }

For projects containing a lot of libraries and source code, proguard can be written in multiple files and these files can then be imported.
For the sake of better project management and code readability, it is suggested to put all your rules files inside the same folder. Then the imports can be further simplified like this

FileCollection proGuardFileCollection = files { file('./proguard').listFiles() }
proguardFiles(proGuardFileCollection)

Mapping :

After you create a release version with proguard, and your app has been in production for quite some time – You will start getting crash reports with the class names chosen by ProGuard. As such, refer to the file mapping.txt – which is created by Proguard. This file maps the obfuscated name to the original names and can be used for reference purposes.

Do keep the file for every version separately as the files are overwritten every time a release build is generated.

Behind the Scenes

While building, this is what actually happens on using Proguard.

  • Shrink
    • Proguard determines which classes and members are used, and discards the ones that are not used.
  • Optimize
    • Further optimization happens in this step where methods that are not entry points, are made private, static or final.
  • Obfuscate
    • In this important step, the code is then obfuscated. Again, the entry points are left untouched. By obfuscating, it essentially renames the class names and methods.
  • Preverify
    • At this step, ProGuard will notify if any of the changes it brought upon has caused any errors.

In the end we receive output jars and classes file, which have less memory overhead and run at better speed. And all this with more secure code.