Saturday, 26 November 2016

Setting up Firebase Cloud Messaging (FCM) in Android application

Background

In last post we say what FCM was and how is it better then the old GCM notifications. 
 Last post was mainly about your server configuration to send FCM notification to a single device. But that assumed that your device is already registered to FCM server and your server has that ID. In this post we will see how to create, register and setup FCM on your Android device. This can be your smart phone or your smart watch app.


Getting started with Firebase Cloud Messaging (FCM)

First of all you need to log into Firebase console -
Log in. Signup if you already don't own a account. Once done you will need to create a new project.





 Once you do that you should see following page.


 As mentioned in previous post as FCM is cross platform you can see Android/iOS/Web. We will concentrate on Android for now. So go ahead and select it. Post clicking it you have 3 steps to perform

  1. provide your android bundle iD
  2. Download google-service.json file and put it under your app folder of Android project
  3. Add dependency to classpath







In app level build.gradle add the firebase dependency you need. For eg in this case we need cloud messaging for FCM. So you can add

compile 'com.google.firebase:firebase-messaging:10.0.0'


You can see all available dependencies here -

under Available libraries section. It looks like below -




Once that is setup your configuration is more or less done. You now also see the server API id we used in previous post from  this project that you have just created. Anyway lets move on the code changes we need.

Code changes needed

Add following services in your manifest file of android module -
        <service android:name="com.osfg.android.watch.MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
        <service android:name="com.osfg.android.watch.MyFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
        </service>

These services are basically the ones which generate token (registration id we need while sending FCM from server) and receiving message from server. Code for them goes as follows -



package com.osfg.android.watch;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
/**
 * Created by athakur on 11/25/16.
 */
public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private static final String loggerName = MyFirebaseMessagingService.class.getSimpleName();

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);

        Log.d(loggerName,"From: " + remoteMessage.getFrom());

        // Check if message contains a data payload.
        if (remoteMessage.getData() != null) {
            Log.d(loggerName, "Message data payload: " + remoteMessage.getData());

            String title = remoteMessage.getData().get("messageTitle");
            String body = remoteMessage.getData().get("messageBody");

            if(StringUtils.hasText(title) && StringUtils.hasText(body))
            {
                Log.d(loggerName, "Showing notification for message");
                showNotification(title, body,this);
            }

        }

        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            Log.d(loggerName, "Message Notification Body: " + remoteMessage.getNotification().getBody());
            showNotification(remoteMessage.getNotification().getBody(),this);
        }
    }
}




MyFirebaseMessagingService class will get the  payload send by server during FCM notification. Your payload can have data or notification payload. Notification payload is directly shown as notification on android device where as data payload needs to be handle by your client application


package com.osfg.android.watch;

import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
/**
 * Created by athakur on 11/25/16.
 */
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {

    private static final String loggerName = MyFirebaseInstanceIDService.class.getSimpleName();

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

        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        sendFcmTokenToServer(refreshedToken);
    }

    private void sendFcmTokenToServer(String token) {
        Log.d(loggerName, "Sending FCM refresh token to server");
    }
}



And you should be done.  MyFirebaseInstanceIDService class will give you a callback when token is refreshed , you need to update it on your server. Once that is done your server will be able to send FCM notifications to you (exactly what we saw in last post).


Once you do this on your app start these service should automatically start. You will get token in callback and message in other callback of respective services that we have implemented. You can take actions appropriately. Sync data or show notification etc.


NOTE

I have already implemented this in a demo android app that you can refer to. Link to github project -

Related Links

Friday, 25 November 2016

How to send Firebase Cloud Messaging (FCM) notification from server to client

Background

Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably deliver messages at no cost. It is an improved version of Google Cloud Messaging (GCM). Following are some of the features that makes FCM stand out -
  1. It is cross platform so it is a natural fir for all.
  2. Using FCM you can send two types of payloads to the client
    1. Notification type in which case a notification will be directly shown on the client
    2. Data payload in which case client has to parse and act on it
  3. You can distribute message to your client app in one of the following 3 ways -
    1. Send it to a single device
    2. Send it to a group of devices
    3. Send it to devices subscribed to topics
  4. Lastly you can also send messages from client back to the server.


 I am not going to bore you with any more details here. This post is simply meant to explain server side implementation of how to deliver FCM messages to client. We will see client setup in future posts.

To view how to setup firebase project and set up a client refer -

Following in Java code to send FCM message to a single device -

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;

import javax.net.ssl.HttpsURLConnection;

import org.apache.http.HttpStatus;
import org.json.JSONException;
import org.json.JSONObject;


/**
 * @author athakur
 */
public class FCMMessageSender {
    
    public static final String FCM_URL = "https://fcm.googleapis.com/fcm/send";
    public static final String FCM_SERVER_API_KEY    = "<ADD_YOUR_SERVER_API_KEY>";
    private static final String deviceRegistrationId =  "<ADD_YOUR_DEVICE_REG_ID>";

    public static void main(String args[])
    {
        int responseCode = -1;
        String responseBody = null;
        try
        {
            System.out.println("Sending FCM request");
            byte[] postData = getPostData(deviceRegistrationId);
           
            URL url = new URL(FCM_URL);
            HttpsURLConnection httpURLConnection = (HttpsURLConnection)url.openConnection();

            //set timeputs to 10 seconds
            httpURLConnection.setConnectTimeout(10000);
            httpURLConnection.setReadTimeout(10000);

            httpURLConnection.setDoOutput(true);
            httpURLConnection.setUseCaches(false);
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setRequestProperty("Content-Type", "application/json");
            httpURLConnection.setRequestProperty("Content-Length", Integer.toString(postData.length));
            httpURLConnection.setRequestProperty("Authorization", "key="+FCM_SERVER_API_KEY);

            

            OutputStream out = httpURLConnection.getOutputStream();
            out.write(postData);
            out.close();
            responseCode = httpURLConnection.getResponseCode();
            //success
            if (responseCode == HttpStatus.SC_OK)
            {
                responseBody = convertStreamToString(httpURLConnection.getInputStream());
                System.out.println("FCM message sent : " + responseBody);
            }
            //failure
            else
            {
                responseBody = convertStreamToString(httpURLConnection.getErrorStream());
                System.out.println("Sending FCM request failed for regId: " + deviceRegistrationId + " response: " + responseBody);
            }
        }
        catch (IOException ioe)
        {
            System.out.println("IO Exception in sending FCM request. regId: " + deviceRegistrationId);
            ioe.printStackTrace();
        }
        catch (Exception e)
        {
            System.out.println("Unknown exception in sending FCM request. regId: " + deviceRegistrationId);
            e.printStackTrace();
        }
    }
    
    public static byte[] getPostData(String registrationId) throws JSONException {
        HashMap<String, String> dataMap = new HashMap<>();
        JSONObject payloadObject = new JSONObject();

        dataMap.put("name", "Aniket!");
        dataMap.put("country", "India");
        
        JSONObject data = new JSONObject(dataMap);;
        payloadObject.put("data", data);
        payloadObject.put("to", registrationId);

        return payloadObject.toString().getBytes();
    }
    
    public static String convertStreamToString (InputStream inStream) throws Exception
    {
        InputStreamReader inputStream = new InputStreamReader(inStream);
        BufferedReader bReader = new BufferedReader(inputStream);

        StringBuilder sb = new StringBuilder();
        String line = null;
        while((line = bReader.readLine()) != null)
        {
            sb.append(line);
        }

        return sb.toString();
    }

}



Output :
Sending FCM request
FCM message sent : {"multicast_id":8122119840448534941,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1480094913845339%a8fa321bf9fd7ecd"}]}


You can read about various payloads you can send to various devices/device groups/devices subscribed to topics in following link -
 As for the server api key you can get it from your project in Firebase console under Setting -> Cloud messaging.







 NOTES

  • Firebase Cloud Messaging (FCM) is the new version of GCM. It inherits the reliable and scalable GCM infrastructure, plus new features! See the FAQ to learn more. If you are integrating messaging in a new app, start with FCM. GCM users are strongly recommended to upgrade to FCM, in order to benefit from new FCM features today and in the future.  
  • When I refer to client it can be an android app or Android wear (yes it is supported from Android Wear 2.0 Developer Preview)
  • For Json library I am using - <dependency org="org.json" name="json" rev="20160810"/> [Ivy dependnecy]


Related Links

Sunday, 13 November 2016

Common Functional interfaces introduced in Java 8

Background

In series of previous posts on Java 8 features we saw Lambda expressions and how to used them.
 We saw basis of a Lambda expression is a functional interface. And then we saw a few functional interfaces as part of introduction to method references -
In this post well see some common functional interfaces that Java provides that you can use at your disposal.


Common Functional interfaces

A new package is introduced since Java 8 that holds all such common functional interfaces. This package is
  • java.util.function
 If you are using JDK 8 in your IDE do check out these classes. You can also find all these in oracle documentation -
 For now lets go over some commonly used functional interfaces from this package.

NOTE : The convention used here is generic type T for type parameter, for second type parameter the next letter U and for a distinct return type R is used as the generic type.


Predicate : Takes a single paramter of any type and returns a boolean [boolean test(T t)]

Predicate functional interface looks like - 

@FunctionalInterface
public interface Predicate<T> {
    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
    //other methods
}

It accepts a parameter of type T and returns a boolean.

Note I have skipped other methods in the interface like default and static methods (Remember default methods and static methods do not affect the functional status of an interface)

Eg.

Predicate<String> emptyPredicate = x -> x.isEmpty();
System.out.println(emptyPredicate.test(""));
System.out.println(emptyPredicate.test("abc"));

Output :
true
false

Consumer : Takes a single paramter of any type and has a void return type [void accept(T t)]

Consumer looks like below -

@FunctionalInterface
public interface Consumer<T> {
    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}

It accepts an input parameter of type T and does does not return anything (has a void return type). It consumes the input.

Eg.

Consumer<String> printFunc = x -> System.out.println(x);
printFunc.accept("Hello World!"); 

Output :
Hello World!

Supplier : Does not take any parameter and returns any type [ T get()]

Supplier looks like -

@FunctionalInterface
public interface Supplier<T> {
    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}
 
Eg.
Supplier<String> strSupplier = () -> "SOME_CONSTANT";
System.out.println(strSupplier.get());

Output :
SOME_CONSTANT

I know that a lame example :) You can simple define and use a constant. Have used this to help you understand how it works. All constructor references in method references are essentially variants of supplier.

UnaryOperator : Takes a single paramter of any type and returns of same type. [R apply(T t)]

UnaryOperator actually extends Function functional interface. Function looks like below -

public interface Function<T, R> {
    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}

So as you see it take input parameter of type T and returns a parameter of type R. UnaryOperator is a special kind of Function where T and R are same. So it take input and returns output of same type.

Eg.

UnaryOperator<String> prefixOp = (name) -> "Mr. " + name; 
System.out.println(prefixOp.apply("Aniket"));

Output :
Mr. Aniket


That's some common functional interface. Now there are "Bi" versions of above interfaces that take in 2 inputs. For eg.
  • BiConsumer<T, U> : Similar to Consumer<T> but takes two inputs of type T and consumes them i.e void return type.
  • BiPredicate<T, U> : Similar to Predicate<T> but takes 2 inputs of type T and U and returns a boolean.
  • BiFunction<T, U, R> : Similar to Function<T, R> but takes 2 inputs of type T and U and returns a parameter of type R.
  • BinaryOperator<T> :  Similar to UnaryOperator<T> but takes 2 parameters of type T and returns parameter of type T.
These functional interfaces are summarized below -

Summary


Related Links 


Sunday, 6 November 2016

How to set date and time in your Raspberry Pi

Background

If you have internet connection in your Raspberry Pi then all you need to do is set your timezone and you are all set. In this post we will see how.

How to set date and time in your Raspberry Pi

  • First open your raspi-config. To do that execute following command in your command line - 
    • sudo raspi-config
  • Once the config open select "Internationalization Options"
  • Next select "Change Timezone"

  • Next select your "Geographic Area"
  • Finally Select your "Time zone"
  • Save and Exit


And that's it your date and time should be set.

How to take screenshots in Raspberry Pi

How to take screenshots in Raspberry Pi

Raspberry Pi does not seem to have a default screenshot application like screenshot or snip. I will explain what worked for me. I am using scrot command line utility to take the screenshots.

To install scrot execute following command -
  • sudo apt-get install scrot

As you can see from screenshot above you can enter
  • scrot -s
and select the window you want to take screenshot of. If you want to take a complete screenshot with with some delay you can do -
  • sudo scrot -d5
You even have a -c option to show a countdown. You can see various options available with man command -
  • man scrot


PS : This whole post is written on my Raspberry Pi 3 Model B and have used scrot command for above screenshots :)

Related Links

t> UA-39527780-1 back to top