Friday, October 19, 2018

[JAVA][Android] Google Nearby API - NearbyManager

Google Nearby API - NearbyManager.java

One of the coolest things I have worked on is the Nearby API.

Here's a couple of resources for you to checkout before you begin!!

  1. Google Nearby - https://developers.google.com/nearby/
  2. Android KT - Nearby API - http://androidkt.com/nearby-connections-api-2-0/
  3. Best Practices - Nearby Communications - https://developer.android.com/distribute/best-practices/engage/nearby-interations
  4. Android Bluetooth Overview - https://developer.android.com/guide/topics/connectivity/bluetooth
  5. Monzo Nearby Friends - https://monzo.com/blog/2018/05/08/nearby-friends/
  6. LinkedIn Nearby (Search or open your LinkedIn on your phone to try with someone!)
Custom made GIF -> Just for you! Download and use. FREE! (Right-Click => Save as)

Nearby Animation GIF
Custom made Nearby GIF (Download FREE)
TO use this GIF, be sure to use a lib like Bumptech Glide to set it to a ImageView in android!

Approaches/Tips

  1. Start by deciding how you want to use this API!
  2. The support for Messages is both Android and IOS, though some apps are having trouble trying to get through Apple's stricter policies when requiring microphone permissions.
  3. The support for Connections API is limited to Android only at this point.
  4. Make a mental model on how you want to build your application. Like shown below.
  5. You will need to create an API key with Google Cloud Console and enable access to Nearby API specifically.
  6. Plus at first application launch, you would have to check for the required permissions as well!
  7. To generate an API key, you would need your SHA1 Android Debug Fingerprint, which is super easy to get BTW. Steps below ->
  8. Next put together all the resources such as animations, images, layouts and strings! (cheap trick for strings: After you type the text inside a layout file, wait Android Studio to highlight it, then just press Alt+Enter and choose "Extract String resource" and voila, your life is set!)
  9. Be sure to add all the dependencies like shown below.
  10. Be sure to configure and add all the API keys and Activities to your Android Manifest as shown below!
  11. And that it you'all!!!!!!!! Now you can begin building that next cool app

Android Manifest

Manifest pt 1

Manifest pt 2


Dependencies Setup

Gradle app config
It doesn't matter if some of the dependencies are not the latest version. Here I chose 4.2.0 because I wasn't able to compile it with 4.8.0 and whatever functionality I required from Glide is working just as fine!

Basic Directory Structure

Directory Structure

Getting your Fingerprint


To get your fingerprint, just run or Double-Click on the Gradle task signingReport and it should run and show you the Fingerprint right in your Console/Debugger/Run task messages window!

Gradle Task to get Fingerprint

The Glorious supporting class

I have made a supporting class to help the new comers engage and better experiment with this API, without needing to get their hands dirty coding the nitty-gritty details!

This is a prerequisite I put together to help people get started with the Nearby API! We don't have a supporting class as such and I figured this would help anyone starting outThis could also help you to find missing pieces in your puzzle! Good luck!





[Class] NearbyManager.java (Just as promised!)

1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.nearby.Nearby;
import com.google.android.gms.nearby.messages.Message;
import com.google.android.gms.nearby.messages.MessageListener;
import com.google.android.gms.nearby.messages.MessagesClient;
import com.google.android.gms.nearby.messages.PublishCallback;
import com.google.android.gms.nearby.messages.PublishOptions;
import com.google.android.gms.nearby.messages.Strategy;
import com.google.android.gms.nearby.messages.SubscribeCallback;
import com.google.android.gms.nearby.messages.SubscribeOptions;
import com.google.android.gms.tasks.OnSuccessListener;

public class NearbyManager {
    private boolean isSubscribing = false;
    private boolean isPublishing = false;
    private Activity current;
    private MessagesClient mMessageClient;
    private MessageListener mMessageListener;
    private static final Strategy PUB_STRATEGY = new Strategy.Builder()
            .setTtlSeconds(Strategy.TTL_SECONDS_DEFAULT).build();
    private static final Strategy SUB_STRATEGY = new Strategy.Builder()
            .setTtlSeconds(Strategy.TTL_SECONDS_MAX).build();
    private String mPubMessage;


    public boolean isSubscribing() {
        return isSubscribing;
    }

    public boolean isPublishing() {
        return isPublishing;
    }

    public NearbyManager(Activity activity){
        current = activity;
        PermissionManager.checkPerms(current);
        mMessageClient = Nearby.getMessagesClient(current);
        mMessageListener = new MessageListener(){
            @Override
            public void onFound(Message message) {
                if(message != null){
                    //DO SOMETHING
                    }
                }
            }
            @Override
            public void onLost(Message message) {
                Toast.makeText(current, "Device is lost", Toast.LENGTH_SHORT).show();
            }
        };

    }
    public void publish(final String message){
        mPubMessage = message;
        PublishOptions options = new PublishOptions
                .Builder()
                .setStrategy(PUB_STRATEGY)
                .setCallback(new PublishCallback(){
                    @Override
                    public void onExpired() {
                        super.onExpired();
                        current.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                isPublishing = false;
                            }
                        });
                    }
                })
                //.setStrategy(Strategy.BLE_ONLY) <-- removed this
                .build();
        mMessageClient.publish(new Message(message.getBytes()), options).addOnSuccessListener(current, new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                Toast.makeText(current, "Publishing! Message:" + message, Toast.LENGTH_SHORT).show();
            }
        });
        isPublishing = true;
    }
    public void subscribe(){
        SubscribeOptions options = new SubscribeOptions.Builder()
                .setStrategy(SUB_STRATEGY)
                .setCallback(new SubscribeCallback(){
                    @Override
                    public void onExpired() {
                        super.onExpired();
                        Toast.makeText(current, "No longer Subscribing!", Toast.LENGTH_SHORT).show();
                        current.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                isSubscribing = false;
                            }
                        });
                    }
                })
                //.setStrategy(Strategy.BLE_ONLY) <-- removed this
                .build();
        mMessageClient.subscribe(mMessageListener, options).addOnSuccessListener(current, new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                Toast.makeText(current, "Subscribing!", Toast.LENGTH_SHORT).show();
            }
        });
        isSubscribing = true;
    }
    public void unsubscribe(){
        if(isSubscribing && mMessageClient != null)
            mMessageClient.unsubscribe(mMessageListener);
        isSubscribing = false;
    }
    public void unpublish(){
        if(isPublishing && mMessageClient != null)
            mMessageClient.unpublish(new Message(mPubMessage.getBytes()));
        isPublishing = false;
    }

}


So that's that guys! Until next, time, have fun coding!
Hopefully coming soon live demos..Unless NDA 😝

Monday, October 15, 2018

Android: 3 Way switch

Hello friends,

Today I will share with you a three-way switch that I made for my own needs!



Android doesn't provide a three way switch. However, I have created a 3 way switch, following the stack overflow page here.

XML:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="@color/md_green_100"
    android:gravity="center"
    android:orientation="horizontal">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:padding="10dp"
        android:text="@string/send"
        android:textColor="@color/colorPrimaryDark"
        android:textSize="18sp"
        android:textStyle="bold" />

    <SeekBar
        style="@style/Widget.AppCompat.SeekBar.Discrete"
        android:layout_width="150dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:backgroundTint="@color/md_green_100"
        android:id="@+id/transferSwitch"
        android:elevation="5dp"
        android:foregroundTint="@color/md_green_100"
        android:indeterminateTint="@color/md_green_100"
        android:max="2"
        android:padding="5dp"
        android:progress="1"
        android:progressBackgroundTint="@color/md_green_100"
        android:progressTint="@color/md_green_100"
        android:secondaryProgressTint="@color/md_green_100"
        android:thumb="@android:drawable/presence_online"
        android:thumbTint="@color/md_green_800"
        app:tickMarkTint="@color/md_green_800" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center|end"
        android:gravity="center"
        android:padding="10dp"
        android:text="@string/receive"
        android:textColor="@color/colorPrimaryDark"
        android:textSize="18sp"
        android:textStyle="bold" />

</LinearLayout>


There you go! That's it,
To use it, try something like


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
SeekBar seekBar = findViewById(SEEKBAR);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
       //Do something here!
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }
});


That's all for now! Thank you!

Wednesday, August 8, 2018

Cool CSS loading animations

SCSS tricks

Check out these cool new loading animations I created using only codepen and SCSS!



Wednesday, July 11, 2018

[JAVASCRIPT] Binary Search Tree, Overloading prototype and implementing a map function

BST - Binary Search Tree

Hello, today I will show you how to develop the binary tree class and how to add a map method, along with the other common methods. We use the map method very frequently with JS Arrays. So I thought we can add it to the BST class we create. 

What is the map method?

The JS Array provides many intersting methods, that take as parameter a function and apply it over the data. We have map, filter etc. which are very useful for Array mutation.
Let us see the map method in action:

Consider this code snippet

var vals = [5, 6, 7, 8];
vals.map(val => val = val * val);

So what is the output ?

console.log(vals);

// You get [25, 36, 49, 64]

Do you see what happened?

val => val = val * val;

Breaking it down,

for every val in vals{
    val = val * val;
} //Not actual JS syntax


So we just saved ourselves from writing the for loop. And since this map function takes a function as a parameter, we can mutate the array however we need to.

I personally am trying to make this post a little easier to comprehend as I too was really confused with the syntax of JS and usage of => , but now I know to use it well and it helps me arrive at solutions much quicker. Filter works in a similar manner.

Now let us get our hands dirty with the code for BSTs:

First we need the Node class, defined by this function.

function Node(val){
  this.val = val;
  this.left = null;
  this.right = null;
}

Next we need the BST class, defined like so.

function BinSearchTree(){
  this.root = null;
}

Next, we overload all the functions we need like so.

push to add values to the BST

BinSearchTree.prototype.push = (val) => {
  var root = this.root;
  if(!root){
    this.root = new Node(val);
    return;
  }
  var currentNode = root;
  var newNode = new Node(val);
  while(currentNode){
    if(val < currentNode.val){
      if(!currentNode.left){
        currentNode.left = newNode;
        break;
      }
      else{
        currentNode = currentNode.left;
      }
    }
    else{
      if(!currentNode.right){
        currentNode.right = newNode;
        break;
      }
      else{
        currentNode = currentNode.right;
      }
    }
  }
}

toString using in-order traversal.

BinSearchTree.prototype.toString = () =>{
  var cur = this.root;
  var s = [];
  var done = false;
  while(!done){
    if(cur){
      s.push(cur);
      cur = cur.left;
    }
    else{
      if(s.length > 0){
        cur = s.pop();
        console.log(cur.val);
        cur = cur.right;
      }
      else{
        done = true;
      }
    }
  }
}


find to search for a key element

BinSearchTree.prototype.find = (key) =>{
  var cur = this.root;
  var s = [];
  while(1){
    if(cur){
      s.push(cur);
      cur = cur.left;
    }
    else{
      if(s.length > 0){
        cur = s.pop();
        if(cur.val == key){
          return true;
        }
        cur = cur.right;
      }
      else{
        return false;
      }
    }
  }
}

map applies a function over the array extended to BST

BinSearchTree.prototype.map = (d) =>{
  var cur = this.root;
  var s = [];
  var done = false;
  while(!done){
    if(cur){
      s.push(cur);
      cur = cur.left;
    }
    else{
      if(s.length > 0){
        cur = s.pop();
        cur.val = d(cur.val);
        cur = cur.right;
      }
      else{
        done = true;
      }
    }
  }
}


So these are the methods I developed. If you notice, the methods have a very similar structure with minor changes to the core operation. If you have any comments, please be sure to leave them below!

Here is some starter code to test the Implementation.

var bst = new BinSearchTree();
for(let i=0; i < 10; i ++){
  bst.push(parseInt(Math.random()*10));
}
bst.toString();

console.log(bst.map(x => x = x* x));
bst.toString();

Sunday, June 24, 2018

Rotate Left function in JAVA

Here is an interesting way to solve the problem of Array Left Rotation function:

The left rotation problem as shown on HackerRank:
left rotation operation on an array shifts each of the array's elements  unit to the left. For example, if  left rotations are performed on array , then the array would become .


static int[] rotLeft(int[] a, int d) {
   int[] b = new int[a.length];
   System.arraycopy(a, d, b, 0, (a.length - d));
   System.arraycopy(a, 0, b, (a.length - d), d);
   return b;
}



What happens here is:

  • First, we initialize a new array to hold our shifted values.
  • We then decide where to split the array using the d value, 
  • Then, you copy the old array part by part to the new array and you have a solution.