Showing posts with label Google. Show all posts
Showing posts with label Google. Show all posts

Wednesday, June 20, 2018

Switched to Project Fi and Save Some Money!

For the longest time until October 2017, I was a faithful T-Mobile subscriber for my mobile phone. They offered the perfect combination of package that I need: 5 GB of high-speed data (it was 3G, 4G, and then LTE over-time), unlimited SMS, and some non-unlimited voice (100 minutes) - all for $30 per month. I was on that plan for years (along with my wife's phone). So we are paying around $64 per month for our cellphone bills combined. We both rarely talk over the phone, most of our communication is happening via data (SMS, WhatsApp, Slack, Skype, etc), and we also have a home phone (VOIP) that we use for long-calling (like calling family members, customer supports, etc etc that are minutes intensive).

I have heard about Project Fi when it came out - somehow it was not that attractive for me at the time. Until I have to buy a new phone ...

So what is Project Fi? It is basically Google's phone carrier - but instead of using their own towers etc, Google uses three existing providers (T-Mobile, Sprint, US Cellular) to provide the subscribers their mobile data services. Project Fi approved devices will be able to switch among all the providers seamlessly. Regular GSM devices will be able to use T-Mobile service only. Project Fi is also a PREPAID service - so there is no contract, no cancellation fee, etc. Which is awesome!

How does it save me money? I thought paying ~$30 per month is cheap already!? Project Fi simplifies your billing - so basically the main account holder must pay $20 per month for the main line - which includes unlimited talk and text. Now on top of it, you only pay for the data that you use with rate $10 per GB. So if I am only using .5GB this month, I will only billed for ~$25 before tax. I don't know about you - but in my day-to-day, 80-90% of the time I am always connected to WiFi (home, office, my friend's house, free WiFi at a coffee shop/restaurant, etc) - and I have my stats too from the last year of my T-Mobile which shows that on average that I only use around 0.7GB of LTE data per month. With that, I am potentially saving $5-$7 per month - not much, I know - but I gain so much more (better coverage, unlimited call, better support, and simplified billing).

Then ... Google released this app call Datally. You can read more about it here. Which basically allows you to control data usage on an app-by-app. The default setting is to not allow data if the app is not on the foreground. So by installing this app, my LTE data usage actually goes down from ~0.7GB to ~0.5GB per month.

Better with more people! It gets better! I switched my wife's provider from T-Mobile to Project Fi - now because she is not the main account holder (her account is working under my account), she is only billed $15 per month (for unlimited calls and text) instead of $20 (like me because I am the main/primary account). Then our data usage is combined and billed together. So what this means is that if we are assuming that her data usage is similar like me (between 0.5-0.7GB of LTE data per month), at the end of the month our combined cell phone bill is ~$49 ($20 + $15 + $7 + $7) before tax - which is ~$12-$14 saving per month. Not much, but we'll take it.

Bill Protection Benefit! Project Fi has other advantages - such as: "Bill Protection" - which is a cap of your bill (not your data usage), but a cap of actually how much Google can actually bill you. The cap is $60 for your LTE data. So if you are on a single account plan, that would $80 total ($20 phone & text + $60 data). Or a different way to look at it is this is the "Unlimited Plan" for Project Fi subscriber.

Free International SMS & Data! With Project Fi, you can use SMS and data freely (already included) in around 170 countries. You can also make or receive phone calls, but it is not free.

You can read more about Project Fi here.
-- read more and comment ...

Sunday, June 17, 2018

Drawing Multiple Routes In One Map with Google Map

Lots of examples in Google Map tutorials and examples are about drawing directions, markers, searches - and all of them typically involve only drawing one set of markers into a "route". An example of this will be going from Boston, MA to Seattle, WA via Cleveland, OH then Chicago, IL. But I need to be make Google Map to draw multiple routes in a single map.

The purpose of this task is to compare the routes. Assuming, like the example above, I am going from Boston to Seattle - which route will be better? Or maybe closer to passing Detroit?

Or another use case: if my friend and I are both traveling out of NYC on 2 separate cars, I am going to Columbus, OH and my friend is going to Detroit, MI - and another friend needs to be dropped off in State College, PA - so which car should this friend join - my car or the other car?

So here is how you do it.
FIRST - you will need to get Google Map Javascript API Key - you can get it here. Once you get it and enable the needed APIs, you will need to use it in your script reference below.

SECOND - in your HTML markup - add script reference Google Map and substituting the YOUR_API_KEY with your real API key from above.
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
    #map {
        margin-top: 10px;
        height: 750px;
        width: 100%;
    }
</style>
</head>
<body>
 <div id="map"></div>
 <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" type="text/javascript"></script>
</body>
</html>
THIRD - initialize several global variables and create a javascript method called "initMap" - this is to initialize your map once the script from Google is loaded.
var routeMapArray = [];
var map;
var defaultZoom = 11;
var directionsService;
var directionDisplayRenderEngineArray = [];
var iconColor = '';

function initMap() {
  routeMapArray = [];
  directionsService = new google.maps.DirectionsService();

  // center initially on NYC
  loadMap(new google.maps.LatLng(40.7128, -74.0060));
}
FOURTH - Create a method called "loadMap" that takes 1 parameter and create a json payload for your routes.
var loadMap = function(center) {
  var mapOptions = {
    zoom: 11,
    mapTypeControl: false,
    streetViewControl: false,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };

  if (center !== undefined && center !== null) {
    mapOptions.center = center;
  }

  // Some basic map setup (from the API docs)
  map = new google.maps.Map(document.getElementById('map'), mapOptions);

  // Start the request making
  var requestArray = [{
      "origin": "New York, NY",
      "destination": "Seattle, WA",
      "waypoints": [{
          "location": "Detroit, MI",
          "stopover": true
        },
        {
          "location": "Denver, CO",
          "stopover": true
        }
      ],
      "travelMode": "DRIVING"
    },
    {
      "origin": "Boston, MA",
      "destination": "San Diego, CA",
      "waypoints": [{
          "location": "Dayton, OH",
          "stopover": true
        },
        {
          "location": "Las Vegas, NV",
          "stopover": true
        }
      ],
      "travelMode": "DRIVING"
    }
  ];
  processRequests(requestArray);
};
FIFTH - We need to process the requests in order, one by one - using different renderer each time on the same map (this is the key).
var processRequests = function(requestArray) {
  var bounds = new google.maps.LatLngBounds();
  var infoWindow = new google.maps.InfoWindow();

  // Counter to track request submission and process one at a time;
  var i = 0;
  var position = "";

  // Used to submit the request 'i'
  var submitRequest = function() {
    if (requestArray.length === 0) return;
    directionsService.route(requestArray[i], processDirectionResults);
  };

  // Used as callback for the above request for current 'i'
  function processDirectionResults(result, status) {
    if (status === google.maps.DirectionsStatus.OK) {
      // Create a unique DirectionsRenderer 'i'
      directionDisplayRenderEngineArray[i] = new google.maps.DirectionsRenderer();
      directionDisplayRenderEngineArray[i].setMap(map);

      if (i == 0) {
        bounds = new google.maps.LatLngBounds();
      }
      iconColor = "#000000";

      directionDisplayRenderEngineArray[i].setOptions({
        preserveViewport: true,
        polylineOptions: {
          strokeWeight: 5,
          strokeOpacity: 0.8,
          strokeColor: iconColor
        },
        markerOptions: {}
      });

      // Use this new renderer with the result
      directionDisplayRenderEngineArray[i].setDirections(result);

      // adjust zooming
      if (i === 0) {
        bounds = directionDisplayRenderEngineArray[i].getDirections().routes[0].bounds;
      } else {
        bounds.union(directionDisplayRenderEngineArray[i].getDirections().routes[0].bounds);
      }

      map.fitBounds(bounds);
      if (map.zoom > defaultZoom) {
        map.setZoom(defaultZoom);
      }

      // and start the next request
      setTimeout(function() {
        nextRequest();
      }, 500);
    }
  }

  function nextRequest() {
    // increment counter
    i++;

    // next request if any
    if (i >= requestArray.length) {
      // No more to do
      return;
    }

    // submit next request
    submitRequest();
  }

  // begin processing
  submitRequest();
};
SIXTH - Done. Make. profit. Here is a working JSFiddle for it.
-- read more and comment ...

Monday, August 20, 2012

Installing Jelly Bean ROM to Galaxy Tab 10.1

Samsung is taking its time in making ICS available for Galaxy Tab 10.1. Since JellyBean has come out since June 2012, it will probably taking another year to get a JellyBean update from Samsung. Looking in the internet, there are JB (JellyBean) custom ROMs available for the Tab. Since running Honeycomb is really aggravating, lagging, and quite a pain - I decided to take the plunge, root, and install custom ROM. Another option is to just get a Nexus 7 device - which will cost $200 more than installing custom ROM.

So in this post, I will describe the step by step process in installing JB ROM into my Tab (from stock Honeycomb). Please note that there are risks involved when one is doing this - that one may "brick" the device, or the installation may fail and require further troubleshooting etc. So do it on your own risk - no guarantees from me. My experience was that the installation was smooth and without any glitch whatsoever. Please do not skip any steps - also make sure your battery is full or almost full. Part of the steps is wiping the data. So if you do not want to lose any data, make sure you back it up first. 


1. ROOT (if yours is already rooted, you can skip this step)
Follow the steps from xda-developers here for rooting your device. The link above even has a video step-by-step guide.

2. OPTIONAL
At this point, I purchased ROM Manager App from the Google Play and update Clockwork Recovery to the latest version. 

3. INSTALL JB
  1. Download 2 sets of files from xda-developers, look for the section like the image on the right:
    1. The custom ROM (select the one that applies to you)
    2. Google Apps
  2. Copy the JB package (both the ROM and the Google Apps zip files) to your tablet’s internal Tab memory
  3. Turn off Tab.
  4. Go to ClockworkMod Recovery by turn on the Tab while holding the Volume Up button. 
  5. When the screen turns on, release the Power button but hold the Volume Up button until a menu shows up on the screen. 
  6. Press Volume Down to select the recovery mode icon and then, press the Volume Up button to enter recovery.
  7. Create a backup of your current ROM. Select "backup and restore". Select "backup" again. This will initiate the backup process. Once it's done, select "go back" to go back to main menu.
  8. Select "wipe data/factory reset" (and confirm)
  9. Select "wipe cache partition" (and confirm)
  10. Select "advanced" -- "wipe dalvik cache" (and confirm)
  11. Select "mounts and storage" -- "format / system" (and confirm). Once done, go back to main menu
  12. Select "install zip from sd card" -- "choose zip from sd card" and select the JB zip file and then confirm selection. The ROM installation will start. 
  13. Select "install zip from sd card" -- "choose zip from sd card" and select the Google Apps zip file and then confirm selection. The Apps installation will start
  14. Once done, select "go back" to the main menu and then select "reboot system now". DONE!
-- read more and comment ...

Monday, May 23, 2011

Web Fonts - Why Haven't I Heard About This Before?

Most of the web only uses selective number of fonts, such as: Arial, Verdana, Sans, Times New Romans. But, what if we want to display certain text with certain fonts other than those - to convey some emotion maybe, or to portray certain values, etc? Are we stuck with those selective fonts?

It's true we can make the text to be bold, underlined, italics, etc. But I want to use "waiting for the sunrise" as my font type instead of "Verdana"! This is not easy to achieve because of several reasons:

  1. We are putting stuff on the web, so if the machine where the browser is running has the font that we want, it will display it. What if it doesn't? Then it will revert to the "default" font. 
  2. All machines or computers have those basic selective fonts - that is why people are mostly sticking with them, so they can be sure that whatever they put on the web will be displayed as intended on the browser.
  3. So far people have been working around this by using images - so if I want a menu or a logo with some font type that is not among the standard, I can make it an image using my image editor and include that in my web site as an asset/image file. This then ensures that it will preserve my intended design of the logo or menu or whatever. 
  4. But of course, making everything an image is a pain. It's hard to modify, it is not searchable by default, people cannot select/highlight from it, and it's bandwidth consuming. But we kinda stuck with it. 
Aren't there any other alternatives? 

-- read more and comment ...

Thursday, July 31, 2008

Google Visualization

Google Visualization is an API where you can feed your data to it and it will produce for you a "visualization" of your data; such as in a pie-chart, bar-chart, line-chart, and even some more complex visualization rendering. In other words, if you have structured data (dynamic or static), you can let Google handle the rendering of its visualization for you (instead of making a screen capture/image in a desktop app and including it in your web app/site).


Here is an example (taken from Google pie-chart code example) on how to render a pie chart about daily activities. From this basic code, we can customize the code to our liking, including displaying dynamic data.


<html>
<head>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["piechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Task');
data.addColumn('number', 'Hours per Day');
data.addRows(5);
data.setValue(0, 0, 'Work');
data.setValue(0, 1, 11);
data.setValue(1, 0, 'Eat');
data.setValue(1, 1, 2);
data.setValue(2, 0, 'Commute');
data.setValue(2, 1, 2);
data.setValue(3, 0, 'Watch TV');
data.setValue(3, 1, 2);
data.setValue(4, 0, 'Sleep');
data.setValue(4, 1, 7);

var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, {width: 400, height: 240, is3D: true, title: 'My Daily Activities'});
}
</script>
</head>

<body>
<div id="chart_div"></div>
</body>
</html>

The result (you can click on the chart btw - and get some details):


As I mentioned above, customization is easy. With dynamic data that comes from the server, as long as you can form your data to conform with the javascript data.addColumn format, you are set! Here is an example using data coming from ASP.NET MVC ... (or using JSON is also very easy)

<script type="text/javascript">
google.load("visualization", "1", {packages:["piechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Task');
data.addColumn('number', 'Hours per Day');
data.addRows(<%=(ViewData["MyTasks"] as List<Task>).Count() %>);
<%
int i = 0;
foreach (var task in (ViewData["MyTasks"] as List<Task>))
{
int j = 0;
%>
data.setValue(<%=i %>, <%=j %>, "<%=task.TaskName.Length > 15 ? task.TaskName.Substring(0, 15) + " ..." : task.TaskName%>");
<%j++; %>
data.setValue(<%=i %>, <%=j %>, <%=task.Hours %>);
<%i++; %>
<%
}
%>
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, {width: 400, height: 240, is3D: true, title: 'My Daily Activities'});
}
</script>

Now, if you are using ASP.NET web-form, is it not that easy to get your data out from your code-behind and expose it to the javascript api of Google Visualization. In this case you may need to expose your object as a protected property of your control/page so it can be accessible.

Nevertheless, once you are at the point where your data is accessible, sending your data to Google and getting a visualization back is a breeze (and fast too).

Cool, huh? Now, let's look at the code in more detail:

<html>
<head>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
...
This part of the code is where you reference Google's API in your code. There is no javascript to download etc, and this is all you need to do to make the API available for you. Now, in a way this is cool, because you don't need to worry about the javascript itself, less file to maintain, etc. But, it also means that there is no intellisense. I don't think it is that big of a deal, since the code you are writting will be pretty concise anyway.


...
google.load("visualization", "1", {packages:["piechart"]});
google.setOnLoadCallback(drawChart);
...
This section of code is what telling the API about what visualization you want to use (such as "piechart") and instantiate it, then it calls the method "setOnLoadCallback" passing in a method "drawChart"; which that puts the data together send it to the API to be drawn. The method "drawChart" is not a Google method. It is a regular javascript method and you can call it whatever you want (such as "myMethod" or "whatever") and as long as it is consistent in its uses, you will be fine.


...
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Task');
data.addColumn('number', 'Hours per Day');
data.addRows(5);
data.setValue(0, 0, 'Work');
data.setValue(0, 1, 11);
...
The example we are looking at is using a "DataTable" type to hold our data. This is probably the simplest way of holding our data to be sent to the visualization engine. I am not sure if there are any other data structure available from Google, but so far I have not had any needs to go beyond what DataTable has been able to provide. Anyway, this section of code is basically for putting our data together into the DataTable object "data". DataTable is basically an array. So when we are setting the values using setValue method, we are setting the data based on a specifiec coordinate (row/column). The method setValue takes in these parameters: row, column, value. You can have as many columns as you want as long as you define them - using addColumn method - before putting data into the DataTable.

...
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
...
This code is pointing out to Google Visualization on where to draw the chart. I created a div space in my HTML and gave it an id ("chart_div").

Click here to go to Google Visualization Gallery.

-- read more and comment ...