Text Recognition by mobile Vision API in Android

Text Recognition by mobile Vision API in Android

    Mobile Vision is an API which help us to find objects in photos and video, using real-time on-device vision technology. I have had talked about 2 features of Vision API of Google Play Services: detecting faces on photo and scanning barcode, QR code. Now, through this tutorial, I would like to present to readers the remaining feature of this API: Text recognition in the photo.

    According the document, we know defining of this API:
Text recognition is the process of detecting text in images and video streams and recognizing the text contained therein. Once detected, the recognizer then determines the actual text in each block and segments it into lines and words. The Text API detects text in Latin based languages (French, German, English, etc.), in real-time, on device.

Text Structure

    The Text Recognizer segments text into blocks, lines, and words. Roughly speaking:
  • a Block is a contiguous set of text lines, such as a paragraph or column, 
  • a Line is a contiguous set of words on the same vertical axis, 
  • a Word is a contiguous set of alphanumeric characters on the same vertical axis.
    The image below highlights examples of each of these in descending order. The first highlighted block, in cyan, is a Block of text. The second set of highlighted blocks, in blue, are Lines of text. Finally, the third set of highlighted blocks, in dark blue, are Words.

Project configuration

    After creating a new Android Studio project, open app-level build.gradle file and add Google Play Services dependency to dependencies block:
compile 'com.google.android.gms:play-services-vision:9.8.0'
    Because you will be using the device’s camera to capture texts, please add CAMERA permission to your AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA"/>

Defining the activity layout

    The activity layout will have a SurfaceView in order to display the preview frames captured by the camera. I also add a TextView to display the contents of the recognized text:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <SurfaceView
        android:id="@+id/surface_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true" />

    <TextView
        android:id="@+id/text_value"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="No text"
        android:layout_alignParentBottom="true"
        android:textColor="@android:color/white"
        android:textSize="20sp" />

</RelativeLayout>

Capturing text with Camera device

    In our activity programmatically code, apply the layout you created in the previous step and get references to the widgets defined in the layout first:
    private SurfaceView cameraView;
    private TextView textBlockContent;
    private CameraSource cameraSource;

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_main);

        cameraView = (SurfaceView) findViewById(R.id.surface_view);
        textBlockContent = (TextView) findViewById(R.id.text_value);
    }
    Now, we're going to create a TextRecognizer object. This detector object processes images and determines what text appears within them. Once it's initialized, a Recognizer can be used to detect text in all types of images:
TextRecognizer textRecognizer = new TextRecognizer.Builder(getApplicationContext()).build();
    Just like that, the TextRecognizer is built. However, it might not work yet. If the device does not have enough storage, or Google Play Services can't download the OCR dependencies, the TextRecognizer object may not be operational. Before we start using it to recognize text, we should check that it's ready. We'll add this check after we initialized the TextRecognizer:
if (!textRecognizer.isOperational()) {
            Log.w("MainActivity", "Detector dependencies are not yet available.");
        }
    To fetch a stream of images from the device’s camera and display them in the SurfaceView, create a new instance of the CameraSource class using CameraSource.Builder. Because the CameraSource needs a TextRecognizer, initializing it with the TextRecognizer instance we've just built above:
cameraSource = new CameraSource.Builder(getApplicationContext(), textRecognizer)
                .setFacing(CameraSource.CAMERA_FACING_BACK)
                .setRequestedPreviewSize(1280, 1024)
                .setRequestedFps(2.0f)
                .setAutoFocusEnabled(true)
                .build();
    Next, add a callback to the SurfaceHolder of the SurfaceView so that you know when you can start drawing the preview frames. The callback should implement the SurfaceHolder.Callback interface. Inside the surfaceCreated() method, call the start() method of the CameraSource to start drawing the preview frames and in surfaceDestroyed(), call stop() to closes the camera and stops sending frames to the underlying frame detector:
cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    //noinspection MissingPermission
                    cameraSource.start(cameraView.getHolder());
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                cameraSource.stop();
            }
        });
    The most important work is we need to tell the TextRecognizer what it should do when it detects a text block. Create an instance of a class that implements the Detector.Processor interface and pass it to the setProcessor() method of the TextRecognizer. Inside the receiveDetections() method which we must override, displayed a SparseArray of TextBlock to a TextView like this:
textRecognizer.setProcessor(new Detector.Processor<TextBlock>() {
            @Override
            public void release() {

            }

            @Override
            public void receiveDetections(Detector.Detections<TextBlock> detections) {
                Log.d("Main", "receiveDetections");
                final SparseArray<TextBlock> items = detections.getDetectedItems();
                if (items.size() != 0) {
                    textBlockContent.post(new Runnable() {
                        @Override
                        public void run() {
                            StringBuilder value = new StringBuilder();
                            for (int i = 0; i < items.size(); ++i) {
                                TextBlock item = items.valueAt(i);
                                value.append(item.getValue());
                                value.append("\n");
                            }
                            //update text block content to TextView
                            textBlockContent.setText(value.toString());
                        }
                    });
                }

            }
        });
    The last work is you should override onDestroy() method of our Activity. In this, stops the camera and releases the resources of the camera and underlying detector:
    @Override
    protected void onDestroy() {
        super.onDestroy();
        cameraSource.release();
    }
    Running this activity, scanning a text block on the paper, you may have result like this:

Conclusions

    Now, I have presented the "official solution" to detecting text from image in Android using device decent camera. By searching on the Internet, you can find out many other third-party libraries which help us to deal with this problem but you should pay attention to this API which written by Google as apart of Google Play Services package. Moreover, To learn more about text recognition, I recommend visiting this API’s documentation.
    Read more:

Reading Barcode/QR code using mobile Vision API in Android

Reading Barcode/QR code using mobile Vision API in Android

    Reading barcode, QR code is a popular topic in mobile application development. The fact that barcodes and QR codes have become ubiquitous in recent years, it requires programmers to create applications for reading them by any smartphone with a decent camera.
    As you followed my blog, I also had 2 posts about this topic:
    Both of 2 posts above is guided about using ZXing library to create a barcode/QR code scanner. But now, the latest release of the Google Play services SDK includes the mobile vision API which, among other things, makes it very easy for Android developers to create apps capable of detecting and reading barcode, QR code in real time.
    In this tutorial, I am going to help you get started with it.

Project configurations

    After starting a new Android Studio project, adding Google Play Services dependency to dependencies scope of your app-level build.gradle:
compile 'com.google.android.gms:play-services:9.6.1'
    Add this meta-data to <application> tag in your AndroidManifest.xml:
<meta-data
            android:name="com.google.android.gms.vision.DEPENDENCIES"
            android:value="barcode" />

Reading barcode/QR code from a photo

    Let’s now write some code that can read a QR code from a photo stored in your app’s assets folder. I’m going to name the photo qr_code.png:
    Firstly, you must decode your photo to a Bitmap by using BitmapFactory, this Bitmap is needed to Vison API as input:
Bitmap myQRCode = BitmapFactory.decodeStream(getAssets().open("qr_code.png"));
    To detect QR codes(and other types of barcodes), you should use an instance of the BarcodeDetector class. The following code shows you how to create one using BarcodeDetector.Builder:
BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(PhotoActivity.this)
                            .setBarcodeFormats(Barcode.QR_CODE) // set QR code as the format type
                            .build();
    Create a Frame using the Bitmap you created:
Frame frame = new Frame.Builder().setBitmap(myQRCode).build();
    Call the detect() method of the BarcodeDetector to generate a SparseArray containing all the QR codes the BarcodeDetector detected in your photo:
SparseArray barcodes = barcodeDetector.detect(frame);
    Okey, after detecting some Barcode objects, you can get their values by call displayValue field:
                    // Check if at least one barcode was detected
                    if (barcodes.size() != 0) {
                        // Display the QR code's message
                        textView.setText("QR CODE Data: " + barcodes.valueAt(0).displayValue);
                        //Display QR code image to ImageView
                        imageView.setImageBitmap(myQRCode);
                    } else {
                        textView.setText("No QR Code found!");
                        textView.setTextColor(Color.RED);
                    }
    And this is full code for this activity:
PhotoActivity.java
package info.devexchanges.barcodescannermobilevisionapi;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.SparseArray;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.google.android.gms.vision.Frame;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;

public class PhotoActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_photo);

        View btnPhotoScan = findViewById(R.id.photo_scan);
        final ImageView imageView = (ImageView) findViewById(R.id.image);
        final TextView textView = (TextView) findViewById(R.id.qr_code_content);
        btnPhotoScan.setOnClickListener(new View.OnClickListener() {
            @SuppressLint("SetTextI18n")
            @Override
            public void onClick(View view) {
                try {
                    Bitmap myQRCode = BitmapFactory.decodeStream(getAssets().open("qr_code.png"));
                    BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(PhotoActivity.this)
                            .setBarcodeFormats(Barcode.QR_CODE)
                            .build();

                    Frame frame = new Frame.Builder().setBitmap(myQRCode).build();
                    SparseArray barcodes = barcodeDetector.detect(frame);

                    // Check if at least one barcode was detected
                    if (barcodes.size() != 0) {
                        // Display the QR code's message
                        textView.setText("QR CODE Data: " + barcodes.valueAt(0).displayValue);
                        //Display QR code image to ImageView
                        imageView.setImageBitmap(myQRCode);
                    } else {
                        textView.setText("No QR Code found!");
                        textView.setTextColor(Color.RED);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}
    Running this Activity, you can get this output:

Reading a barcode Using the Camera

    The mobile vision API also makes it very easy for you to detect and read barcodes using your device’s camera in real time. Let’s create a new Activity that does just that.
    Firstly, you must request CAMERA permission in your AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
    Creating a layout file (xml) for this Activity. I will use a SurfaceView to display the preview frames captured by the camera and a TextView to display the content barcode value:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <SurfaceView
        android:id="@+id/surface_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true" />

    <TextView
        android:id="@+id/barcode_value"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="@dimen/activity_horizontal_margin"
        android:text="No Barcode"
        android:textColor="@android:color/white"
        android:textSize="20sp" />

</RelativeLayout>
    In the activity Java code, to "stream" the camera preview scene to the SurfaceView, we'll use an instance of CameraSource, initializing it with a BarcodeDetector object:
barcodeDetector = new BarcodeDetector.Builder(this)
                .setBarcodeFormats(Barcode.ALL_FORMATS)
                .build();

cameraSource = new CameraSource.Builder(this, barcodeDetector)
                .setRequestedPreviewSize(1600, 1024)
                .setAutoFocusEnabled(true) //you should add this feature
                .build();
    As noted in code, you should use setAutoFocusEnabled(true) when creating the CameraSource instance, your "camera preview" will be auto focused, not be blurry!
    Next, add a callback to the SurfaceHolder of the SurfaceView so that you know when you can start drawing the preview frames. The callback should implement the SurfaceHolder.Callback interface. Inside the surfaceCreated() method, call the start() method of the CameraSource to start drawing the preview frames:
cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    //noinspection MissingPermission
                    cameraSource.start(cameraView.getHolder());
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                cameraSource.stop();
            }
        });
The remaining work is displaying detected barcode content to TextView. We will use setProcessor() method of BarcodeDetector with the parameter is Detector.Processor:
barcodeDetector.setProcessor(new Detector.Processor() {
            @Override
            public void release() {
            }

            @Override
            public void receiveDetections(Detector.Detections detections) {
                final SparseArray barcodes = detections.getDetectedItems();
                if (barcodes.size() != 0) {
                    barcodeValue.post(new Runnable() {
                        @Override
                        public void run() {
                            //Update barcode value to TextView
                            barcodeValue.setText(barcodes.valueAt(0).displayValue);
                        }
                    });
                }
            }
        });
    Moreover, you should override onDestroy() method of your Activity to release the CameraSource to stop drawing the preview frame. Finally, this is full code:
MainActivity.java
package info.devexchanges.barcodescannermobilevisionapi;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.SparseArray;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;

import com.google.android.gms.vision.CameraSource;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {
    private BarcodeDetector barcodeDetector;
    private CameraSource cameraSource;
    private SurfaceView cameraView;
    private TextView barcodeValue;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.activity_main);

        cameraView = (SurfaceView) findViewById(R.id.surface_view);
        barcodeValue = (TextView) findViewById(R.id.barcode_value);

        barcodeDetector = new BarcodeDetector.Builder(this)
                .setBarcodeFormats(Barcode.ALL_FORMATS)
                .build();

        cameraSource = new CameraSource.Builder(this, barcodeDetector)
                .setRequestedPreviewSize(1600, 1024)
                .setAutoFocusEnabled(true) //you should add this feature
                .build();

        cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    //noinspection MissingPermission
                    cameraSource.start(cameraView.getHolder());
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                cameraSource.stop();
            }
        });

        barcodeDetector.setProcessor(new Detector.Processor() {
            @Override
            public void release() {
            }

            @Override
            public void receiveDetections(Detector.Detections detections) {
                final SparseArray barcodes = detections.getDetectedItems();
                if (barcodes.size() != 0) {
                    barcodeValue.post(new Runnable() {
                        @Override
                        public void run() {
                            //Update barcode value to TextView
                            barcodeValue.setText(barcodes.valueAt(0).displayValue);
                        }
                    });
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        cameraSource.release();
        barcodeDetector.release();
    }
}
    Running this activity and scanning a barcode, you may get result like this:

Conclusions

    In this tutorial, you learned how to use the mobile vision API to read barcode and QR codes from static images as well as from live camera streams. To learn more about the mobile vision API, I recommend visiting the API’s documentation.
    These are posts about Mobile Vision API on my blog:

Using Nearby Connections API of Google Play Services in Android

Using Nearby Connections API of Google Play Services in Android

    One of the many APIs available in Google Play Services is the Nearby Connections API. Introduced in early 2015, this framework lets you set one device running your application as a host and have multiple other devices connect to it in order to communicate over a Local Area Network (LAN).
    In my opinion, this is very interesting and highly applicable API. Let's imagine, some Android devices which connected to the same wifi network or  Ethernet data connection can send messages to together. In this post, you will learn how to set up applications for connecting multiple devices together over a network and how to send data over that connection.

Setting up Nearby API to Android Studio Project

    Once you have your initial program created in Android Studio, you will need to import the Play Services library into your app. To do this, place the following line of code under the dependency node of the build.gradle file. At the time of writing, Nearby API 9.4.0 is the most recent release for development:
compile 'com.google.android.gms:play-services-nearby:9.4.0'
    Adding checking network state permission to your AndroidManifest.xml because this feature uses a LAN to communicate:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    Next, you will need to add a piece of meta-data in the application tag that defines a service identifier that will be used by your app so that it can discover hosts advertising with that same identifier. In this example, our service identifier is defined in strings.xml as service_id:
<meta-data
            android:name="com.google.android.gms.nearby.connection.SERVICE_ID"
            android:value="@string/service_id" />
    Now, go to your main activity Java code. This is the class where we will implement both advertising and discovery. In MainActivity, you will also control sending messages between different devices.
    Firstly, in order to start using the Nearby Connections API, you must set up and connect to the Google API Client. Implementing ConnectionCallbacks and OnConnectionFailedListener at the top of your class. While we're adding our interfaces, let's also include the three that are needed by the API and an View.OnClickListener to handle Buttons event:
public class MainActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener,
        Connections.ConnectionRequestListener, Connections.MessageListener,
        GoogleApiClient.ConnectionCallbacks,
        Connections.EndpointDiscoveryListener, View.OnClickListener {

        ... 
    Like another Google Play Services API, in Android, you work with them through a GoogleApiClient object. Initializing it in onCreate() method of MainActivity like this:
googleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(Nearby.CONNECTIONS_API)
                .build();
    Start/Stop connecting in onStart()/onStop():
    @Override
    protected void onStart() {
        super.onStart();
        googleApiClient.connect();
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (googleApiClient != null && googleApiClient.isConnected()) {
            Nearby.Connections.stopAdvertising(googleApiClient);
            googleApiClient.disconnect();
        }
    }
    Let's now create the member variables that we'll need in the MainActivity class. The most important here are two boolean flags for designating whether or not the device is connected and if it is the connection host, the GoogleApiClient that is necessary for using the Nearby Connections API:
    private String mRemoteHostEndpoint;
    private GoogleApiClient googleApiClient;
    private ListView listView;
    private View btnConnect;
    private View btnSend;
    private ArrayAdapter<String> adapter;
    private List<String> remotePeerEndpoints;
    private TextInputLayout textInputLayout;
    private View inputLayout;
    private TextView status;
    private RadioGroup radioGroup;
    private long CONNECTION_TIME_OUT = 15000;
    private boolean isConnected;
    private boolean isHost = false;

Advertising connections

    Up to now, you've just completed connecting to the Google API Client, you now can start working with nearby connections.
    With your device, there are two connecting options: advertising and discovering. We'll go over the first option(advertising), which allows a device to assume the role of host and manage connections between various peers for communication. After checking your network, start advertising by call Nearby.Connections.startAdvertising() method. Adding some proper parameters and setResultCallback() like this:
public boolean isConnectedToNetwork() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo wifiNetwork = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        if (wifiNetwork != null && wifiNetwork.isConnected()) {
            return true;
        }

        NetworkInfo mobileNetwork = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
        if (mobileNetwork != null && mobileNetwork.isConnected()) {
            return true;
        }

        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        if (activeNetwork != null && activeNetwork.isConnected()) {
            return true;
        }

        return false;
    }

    private void advertise() {
        if (!isConnectedToNetwork()) return;

        String name = "Nearby Advertising";
        Nearby.Connections.startAdvertising(googleApiClient, name, null, CONNECTION_TIME_OUT, this)
                .setResultCallback(new ResultCallback<Connections.StartAdvertisingResult>() {
                    @Override
                    public void onResult(Connections.StartAdvertisingResult result) {
                        if (result.getStatus().isSuccess()) {
                            status.setText("Advertising");
                        }
                    }
                });
    }
    Once your "host device" is advertising, it will be able to receive connection requests from peers. When a device attempts to connect, onConnectionRequest() will be called. To accept the request, you call Nearby.Connections.acceptConnectionRequest with a ResultCallback. In this example, we'll add the remote endpoint to a list to keep track of it and broadcast to any connected peers that this new device has connected. Moreover, you determine that the device should not connect to your application, you can reject it by calling Nearby.Connections.rejectConnectionRequest:
    @Override
    public void onConnectionRequest(final String remoteEndpointId, final String remoteDeviceId,
                                    final String remoteEndpointName, byte[] payload) {
        if (isHost) {
            Nearby.Connections.acceptConnectionRequest(googleApiClient, remoteEndpointId, payload, this)
                    .setResultCallback(new ResultCallback() {
                        @Override
                        public void onResult(Status status) {
                            if (status.isSuccess()) {
                                if (!remotePeerEndpoints.contains(remoteEndpointId)) {
                                    remotePeerEndpoints.add(remoteEndpointId);
                                }

                                getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                                adapter.notifyDataSetChanged();
                                sendMessage(remoteDeviceId + " connected!");
                                inputLayout.setVisibility(View.VISIBLE);
                            }
                        }
                    });
        } else {
            Nearby.Connections.rejectConnectionRequest(googleApiClient, remoteEndpointId);
        }
    }

Discovering connections

    Like the option above, you can start discovery by passing the application's service identifier into the Nearby.Connections.startDiscovery() method, which sets your user's device into discovery mode.
    When a host device is detected, onEndpointFound() will be called. Request to connect with host by calling Nearby.Connections.sendConnectionRequest(). If the connection is accepted or rejected by the host, the sendConnectionRequest() result callback will be called. If the connection is accepted, we now prepare for sending messages across the connection channel:
private void discover() {
        if (!isConnectedToNetwork())
            return;

        String serviceId = getString(R.string.service_id);
        Nearby.Connections.startDiscovery(googleApiClient, serviceId, CONNECTION_TIME_OUT, this)
                .setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        if (status.isSuccess()) {
                            MainActivity.this.status.setText("Discovering");
                        }
                    }
                });
    }

    @Override
    public void onEndpointFound(String endpointId, String deviceId, final String serviceId, String endpointName) {
        byte[] payload = null;

        Nearby.Connections.sendConnectionRequest(googleApiClient, deviceId, endpointId, payload,
                new Connections.ConnectionResponseCallback() {

                    @Override
                    public void onConnectionResponse(String s, Status status, byte[] bytes) {
                        if (status.isSuccess()) {
                            MainActivity.this.status.setText("Connected to: " + s);
                            Nearby.Connections.stopDiscovery(googleApiClient, serviceId);
                            mRemoteHostEndpoint = s;
                            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                            inputLayout.setVisibility(View.VISIBLE);

                            if (!isHost) {
                                isConnected = true;
                            }
                        } else {
                            MainActivity.this.status.setText("Connection to " + s + " failed");
                            if (!isHost) {
                                isConnected = false;
                            }
                        }
                    }
                }, this);
    }

Sending messages via the connection

    When a message is received over the API, onMessageReceived() will be called. In this application, you will use this to display the payload as a string in a ListView and, if the device is the host, rebroadcast it out to every connected device:
    @Override
    public void onMessageReceived(String s, byte[] bytes, boolean b) {
        adapter.add(new String(bytes));
        adapter.notifyDataSetChanged();

        if (isHost) {
            sendMessage(new String(bytes));
        }
    }
    And this is method that sending a message (user input) via the connection, I divided into 2 cases: host device message and client device message:
private void sendMessage(String message) {
        if (isHost) {
            Nearby.Connections.sendReliableMessage(googleApiClient, remotePeerEndpoints, message.getBytes());
            adapter.add(message);
            adapter.notifyDataSetChanged();
        } else {
            Nearby.Connections.sendReliableMessage(googleApiClient, mRemoteHostEndpoint,
                    (Nearby.Connections.getLocalDeviceId(googleApiClient) + " says: " + message).getBytes());
        }
    }

Disconnecting from the connection

    If you attempt to disconnect on a client that hasn't connected to a host yet, you simply need to stop discovery. If you've already connected to a host, you call disconnectFromEndpoint() and the API will handle severing the connection:
private void disconnect() {
        if (!isConnectedToNetwork())
            return;

        if (isHost) {
            sendMessage("Shutting down host");
            Nearby.Connections.stopAdvertising(googleApiClient);
            Nearby.Connections.stopAllEndpoints(googleApiClient);
            isHost = false;
            status.setText("Not connected");
            remotePeerEndpoints.clear();
        } else {
            if (!isConnected || TextUtils.isEmpty(mRemoteHostEndpoint)) {
                Nearby.Connections.stopDiscovery(googleApiClient, getString(R.string.service_id));
                return;
            }

            sendMessage("Disconnecting");
            Nearby.Connections.disconnectFromEndpoint(googleApiClient, mRemoteHostEndpoint);
            mRemoteHostEndpoint = null;
            status.setText("Disconnected");
        }

        isConnected = false;
    }

Running application

    I run this sample project in my 2 physically devices. This is the host device screen, when I select "Host" RadioButton and click the button to start connecting, status become "advertising":

    In the second device, choose "Client" and start connecting, the status change to "Discovering":

When the client device connected:

    Sending some messages:

Conclusions

    Through this post, you have learned how to implement communication between various Android devices over a LAN using the Nearby Connections API - a part of Google Play Services. You should now be able to enhance your own apps by connecting devices together and keeping them in sync through various updates to each other. Moreover, you can custom this project to make it become a "LAN message" application, this is not too hard!
    References:

Android Push Notification Using Firebase Cloud Messaging (FCM)

Android Push Notification Using Firebase Cloud Messaging (FCM)

    The 2016 Google I/O announced major improvements to Firebase – a cloud platform with a lot of amazing features for mobile app developers. One of them is Firebase Cloud Messaging (FCM) — a cross-platform messaging solution that lets users reliably deliver messages at no cost. Yes, FCM is a free service from Google. Comparing to the earlier Google Cloud Messaging (GCM), FCM is much more developer-friendly because you don't even need to see any of the server code involved.

    Through my previous post, you have know about Firebase authentication. So, in this is a tutorial which talking about other features: sending push notifications to Android devices, based on the new release of Firebase this year (2016). This tutorial shows how to setup the skeleton for sending and receiving push notifications via FCM with instructions on server code.

Setting up Firebase project

    Go to Firebase console page, login with your Google account and and start a new Android project by click "Create New Project". Filling your project information with appearing Dialog:
    After that, choose Android platform with your project/app:
    Filling your app information (package name, SHA-1 key (optional)):
    Now, your configuration in the console page is completed and google-service.json file have been downloaded to your computer.
    Start your Android Studio project, make sure that it has same package name with project in the console page (here is info.devexchanges.firebasenotification). Copying google-serivce.json file to app folder in your project:
    Adding this rules to your project-level build.gradle file, to include the google-services plugin:
buildscript {
    // ...
    dependencies {
        // ...
        classpath 'com.google.gms:google-services:3.0.0'
    }
}
Then, in your module Gradle file (usually the app/build.gradle), add the apply plugin line at the bottom of the file to enable the Gradle plugin:
apply plugin: 'com.android.application'

android {
  // ...
}

dependencies {
  // ...
  compile 'com.google.firebase:firebase-messaging:9.4.0'
}

// ADD THIS AT THE BOTTOM
apply plugin: 'com.google.gms.google-services'
    Up to now, the project configuration process is finished!

Creating Firebase Service

The first Java class is a Service. This class is extended from FirebaseInstanceIdService and will be used to get the refreshed token and to store it on the server if needed. Here is full code:
CustomFirebaseInstanceIDService.java
package info.devexchanges.firebasenotification;

import android.util.Log;

import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;

public class CustomFirebaseInstanceIDService extends FirebaseInstanceIdService {

    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the InstanceID token
     * is initially generated so this is where you would retrieve the token.
     */

    private static String TAG = CustomFirebaseInstanceIDService.class.getSimpleName();

    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);

        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // Instance ID token to your app server.
        sendRegistrationToServer(refreshedToken);
    }

    /**
     * Persist token to third-party servers.
     * * Modify this method to associate the user's FCM InstanceID token with any server-side account
     * maintained by your application.
     *
     * @param token The new token.
     */
    private void sendRegistrationToServer(String token) {
    }
}
    The second Serivce file is extended from FirebaseMessagingService. It will receive the messages from the firebase server and generate the notifications on the device. The notifications will be build normally by NotificationCompat.Builder:
CustomFirebaseMessagingService.java
package info.devexchanges.firebasenotification;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class CustomFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        //Calling method to generate notification
        sendNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
    }

    private void sendNotification(String title, String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(title)
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(0, notificationBuilder.build());
    }
}
The last important step is register your 2 Services to your AndroidManifest.xml. Never forget to adding Internet permission, too:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.devexchanges.firebasenotification">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <service
            android:name=".CustomFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>

        <service
            android:name=".CustomFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>

    </application>

</manifest>

Running application

    To running any application which using Firebase, you should take a glance at the prerequisites in Firebase oficial website:
  • An Android device running Google Play services 9.0.0 or later 
  •  The Google Play services SDK from the Android SDK Manager 
  •  Android Studio 1.5 or higher 
  • An Android Studio project and it's package name.
    In an understandable way, you should run this app in your real device, which usually installed Google Play services. This is output in my Asus Zenfone Go (main screen):
    Now, go to Firebase console page, select Notification entry in the left pane:
    Click at "Send your first message" and filling your message content:
    After click at "Send Message", your Android device will receive a notification:

Conclusions

    Now, I have presented all basic steps to integrating FCM to an Android application. I hope you will like the article and it will definitely help you to make your apps more productive. Now, for more details, you should read official doc of Firebase notification to deep understanding this topic.
    Some related links:

Android Getting Started with Firebase – Registration and Login (Part 1)

    Firebase is a mobile-backend-as-a-service that provides several features for building powerful mobile apps. Firebase has three core services: a realtime database, user authentication and hosting. With it's Android SDK, you can use these services to build powerful apps without writing a single line of server code.
   Firebase company was acquired by Google in October 2014 and then, at I/O 2016, Google introduced an all new & updated version of Firebase, offering a comprehensive solution for creating a back-end infrastructure for mobile and the web.

Firebase overview

    All main features of Firebase can be seen at the image below:

    All features are available for Android and iOS development, except for Test Lab which is not supported for iOS devices. Some of the features are not supported yet for web applications.
    The Firebase SDK supports programming in C++, Java, JavaScript, JavaScript/Node.js, Objective-C, and Swift. Angular, Backbone, Ember and React are supported through bindings to the database. Google added a number of helper libraries: FirebaseUI, Geofire, Firebase Queue, FirebaseJobDispatcher. Their name indicates what their purpose is. Firebase also supports importing large JSON data sets and integration with ElasticSearch.
    In this post, I will present the way to using "Authentication" feature in Android development. With it, you can create a simple application with login and registration screens and saving all user account to an online database.
    DEMO VIDEO:

Enabling Firebase Authentication

    Firstly, in order to use Firebase in your Android application, please go to it's Homepage and login with your Google account.
    After that, you will see "Get Started for free" button, click it, you will be redirected to this page:
 
    Click at "Create new project" and fill your app information to text fields (Project name, Country):
    Choose Android platform and fill your app package name and finger-print (optional):

    After this step, file named google-service.json will be downloaded to your computer and this is your project page in Firebase:
    Click "Set up Sign in method" to go to Sign In Method tab and enable "Email/Password" entry:
    And we'll have this result:

Android project configuration

    When starting a new Android project, make sure that your app package name is same as defined in the project's page on Firebase (here is info.devexchanges.firebaselogin).
    Put google-services.json file to your app folder:

    Open your project level build.gradle and add Google play services class-path:
dependencies {
        classpath 'com.android.tools.build:gradle:2.1.3'
        classpath 'com.google.gms:google-services:3.0.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
   Open application level build.gradle to adding Google play services dependency and at the bottom of file, adding apply plugin: 'com.google.gms.google-services':
dependencies {
    compile 'com.google.firebase:firebase-auth:9.4.0'
}
 
apply plugin: 'com.google.gms.google-services'
   Important Note: Make sure that you have installed Google play services packages in your Android SDK, only then you will be able to sync gradle successfully:

Building the Registration Activity

    In this post, I will present the way to make a sign up screen, users can create their own accounts in your app and data will be saved in Firebase database.
    We use Firebase authentication through FirebaseAuth class. In onCreate() of your Activity, initializing it through this code:
auth = FirebaseAuth.getInstance();
    In registration, FirebaseAuth has an important method which you'll use is createUserWithEmailAndPassword(). When called it, handling registration result (success or failed) by using OnCompleteListener<TResult> interface. Checking it's success or not, only need to override onComplete(@NonNull Task<AuthResult> task) method.
    Source code for registration activity is simple like this:
RegisterActivity.java
package info.devexchanges.firebaselogin;

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;

public class RegisterActivity extends AppCompatActivity {

    private View btnLogin;
    private View btnSignUp;
    private ProgressDialog progressDialog;
    private TextInputLayout email;
    private TextInputLayout password;
    private FirebaseAuth auth;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_register);

        //Get Firebase auth instance
        auth = FirebaseAuth.getInstance();

        btnLogin = findViewById(R.id.login);
        btnSignUp = findViewById(R.id.sign_up);
        email = (TextInputLayout) findViewById(R.id.email_field);
        password = (TextInputLayout) findViewById(R.id.password_field);

        //go to Login Activity
        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
                startActivity(intent);
                finish();
            }
        });

        //sign up a new account
        btnSignUp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!Utils.hasText(email)) {
                    Utils.showToast(RegisterActivity.this, "Please input your email");
                } else if (!Utils.hasText(password)) {
                    Utils.showToast(RegisterActivity.this, "Please input your password");
                } else {
                    //requesting Firebase server
                    showProcessDialog();
                    auth.createUserWithEmailAndPassword(Utils.getText(email), Utils.getText(password))
                            .addOnCompleteListener(RegisterActivity.this, new OnCompleteListener<AuthResult>() {
                                @Override
                                public void onComplete(@NonNull Task<AuthResult> task) {
                                    if (!task.isSuccessful()) {
                                        progressDialog.dismiss();
                                        Utils.showToast(RegisterActivity.this, "Register failed!");
                                    } else {
                                        Utils.showToast(RegisterActivity.this, "Register successful!");
                                        startActivity(new Intent(RegisterActivity.this, LoginActivity.class));
                                        progressDialog.dismiss();
                                        finish();
                                    }
                                }
                            });
                }
            }
        });
    }

    private void showProcessDialog() {
        progressDialog = new ProgressDialog(this);
        progressDialog.setTitle("Register");
        progressDialog.setMessage("Register a new account...");
        progressDialog.show();
    }
}
    And it's layout (xml) file:
activity_register.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00BCD4"
    android:orientation="vertical"
    android:padding="@dimen/activity_horizontal_margin">

    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="30dp"
        android:contentDescription="@null"
        android:src="@drawable/firebase" />

    <android.support.design.widget.TextInputLayout
        android:id="@+id/email_field"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Email"
            android:inputType="textEmailAddress"
            android:singleLine="true"
            android:textColor="@android:color/white" />

    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/password_field"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:focusableInTouchMode="true"
            android:hint="Password"
            android:imeActionId="@+id/login"
            android:inputType="textPassword"
            android:singleLine="true"
            android:textColor="@android:color/white" />

    </android.support.design.widget.TextInputLayout>

    <Button
        android:id="@+id/sign_up"
        style="?android:textAppearanceSmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:background="#FFCA28"
        android:text="Register"
        android:textColor="@android:color/black"
        android:textStyle="bold" />

    <Button
        android:id="@+id/login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dip"
        android:background="@null"
        android:text="Go To Login"
        android:textAllCaps="false"
        android:textSize="15dp" />

</LinearLayout>
    There are some necessary files in this project. Firstly is Utils.java which providing some standardized string methods:
Utils.java
package info.devexchanges.firebaselogin;

import android.content.Context;
import android.support.design.widget.TextInputLayout;
import android.widget.Toast;

public class Utils {
    public static boolean hasText(TextInputLayout inputLayout) {
        return !inputLayout.getEditText().getText().toString().trim().equals("");
    }

    public static String getText(TextInputLayout inputLayout) {
        return inputLayout.getEditText().getText().toString().trim();
    }

    public static void showToast(Context context, String msg) {
        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
    }
}
    Then, the login screen is still a blank Activity, I will complete it in Part 2 of this tutorial (coming soon).
LoginActivity.java

package info.devexchanges.firebaselogin;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

public class LoginActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_login);

        /**
         * It will be completed in nex post.
         * Coming soon!
         */
    }
}
    Important Note: Never forget to request Internet permission for your application:
<uses-permission android:name="android.permission.INTERNET" />
    I use TextInputLayout to make the text field - a widget from Design support library, so you must add this dependency to your app-level build.gradle:
compile 'com.android.support:design:24.2.0'

Running this application

     To running any application which using Firebase, you should take a glance at the prerequisites in Firebase oficial website:
  • An Android device running Google Play services 9.0.0 or later 
  • The Google Play services SDK from the Android SDK Manager 
  • Android Studio 1.5 or higher An Android Studio project and it's package name.
    In an understandable way, you should run this app in your real device, which usually installed Google Play services. This is output in my Samsung Galaxy Tab 4:
    If registration successful, you'll be redirect to Login screen and the success Toast message is shown:

    If you login to Firebase console, you can see the user created with the email id you have given the android app:
When app has just created: there is no user registered
A new user registered

Conclusions

    Through this post, I hope that you can understanding the overview of Firebase and creating a simple registering screen to get and store data in this online database. Up to next post, I will guide about login screen and get user information from Firebase to displayed it on your Android app. Project source code will also available at the next post!