Deals

Thursday, January 1, 2015

Android Geofence Stop Getting Transition Events After Some Time

And here comes the first technical blog of 2015, Recently in one of our android application we have used Geofences in Android application. The app needs to track entry and exit of device in Geofence. After implementing and configuring Geofences by help of the sample code from android developer site, it worked good for some time but after the app is running for long time suddenly no transitions were recorded even though the device was in Geofence. After looking for the reason for few hours, I finally found a solution, in this blog I am going to mention that.

The issue was with IntentService mentioned in example code. When your device enters into Geofence, this intent service gets called with pending intent. It works good if your app is in foreground but when the app is in background, this IntentService is never called. So to overcome with this shortcomings, we have used Broadcast receiver in stead of IntentService.

So first define BroadcastReceiver in Manifest file.

<receiver
            android:name="com.app.appname.GeofenceReceiver"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.tracksum.vehicletrack.GeofenceReceiver.ACTION_RECEIVE_GEOFENCE" />
            </intent-filter>

        </receiver>

Now create this class in your package. 

public class GeofenceReceiver extends BroadcastReceiver {

   public void onReceive(Context context, Intent intent) {
       if (LocationClient.hasError(intent)) {
           handleError(intent);
       } else {
           handleEnterExit(intent);
       }
   }

    private void handleError(Intent intent){
       
    }

   private void handleEnterExit(Intent intent) {
       int transition = LocationClient.getGeofenceTransition(intent);
       if (transition == Geofence.GEOFENCE_TRANSITION_ENTER){
           Log.v("geofence","entered");
       }else if(transition == Geofence.GEOFENCE_TRANSITION_EXIT){
           Log.v("geofence","exited");
       }
   }
}

This is your broadcast receiver. Now create an intent and pending intent with this.

Intent intent = new Intent("com.app.appname.GeofenceReceiver.ACTION_RECEIVE_GEOFENCE");

PendingIntent geoFencePendingIntent = PendingIntent.getBroadcast( getApplicationContext(), 0,                                                                             intent, PendingIntent.FLAG_UPDATE_CURRENT);

Add this to location client while adding geofences.

mLocationClient.addGeofences(geofenceList, geoFencePendingIntent, this);

That's it and now you will get all the transitions of Geofence if your app is not in foreground.

Introducing Adsum

Hello,

This is my first blog post of 2015 and this time it's not technical blog. I would like to introduce a product built by our team. Since last few moths we were building this product and finally it's here so here we are introducing our milestone product "ADSUM"

Adsum as the name suggests means "I am present".   Briefly, Adsum is an app on your phone that keeps track of your attendance on day to day basis. It makes the life of the employee and HR easier by creating monthly charts of attendance, absenteeism, leave and sick day and linking it to the employees payroll and has many other benefits.

It's a GPS based attendance & leave management system that helps the Organizations & Managers to manage the resource on the fly. Output from this system can be linked to payroll, expense management system etc. Data is accessible real time and helps you to reduce the conflicts amongst the workforce on attendance and leave management. System can be customized based on your needs and reporting requirements. Following are few screenshots of the application.






It comes with two different views for employees and managers. Managers has extra views like dashboard and activities. App has real time notifications which is sent to managers as soon as employee marks attendance and apply for leaves. Managers can approve leave and attendance form the app it self.This makes their life so easy. 

It's an ideal app for organizations who has staffs which are paid on hourly basis. Using Adsum app you can precisely calculate number of hours worked and you can have monthly and weekly report for payroll. 

In short this is an awesome application for any business who want to automate their attendance management system. If you want this app for your organizations or want to know more about it, kindly contact us. Following are our contact details.

Vibhay Vaidya : +919920465555
Rinkal Shah : +919898171728

Also drop us an email on following email ids.

info@novustouch.com
info@thedesignshop.co.in

Thank you.

Thursday, December 25, 2014

Android Application Get GPS ON/OFF Notification

Hello,

Recently in one of my project we had location service which is used send locations to server and draw a path on map of travel. As we know to get accurate location from the device we need GPS turned on and we wanted to track event and log event on server if user turn off GPS purposefully. In this blog I am going to explain how to do this.

First of all you need to add following permissions to your android manifest file so that your app can access users location.

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

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

Now create an instance of location manager which receives location updates from GPS. 

locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);

As you can see in above code we are creating location manager instance and set it to receive updates from GPS. Now we will add GPS status listener.

locationManager.addGpsStatusListener(new android.location.GpsStatus.Listener()
  {
    public void onGpsStatusChanged(int event)
    {
        switch(event)
        {
        case android.location.GpsStatus.GPS_EVENT_STARTED:
            Log.v("gps","gps is on");
            break;
        case android.location.GpsStatus.GPS_EVENT_STOPPED:
            Log.v("gps","gps is off");
            break;
        }
    }
});

As you can see in above code we have added GPS status listener to location manager. When either GPS is turned on or off onGpsStatusChanged event callback will be called and you can check case as shown in above code and do the stuff in there.

Hope this helps you.

Tuesday, December 23, 2014

Restart Android Service on Reboot of Phone

Recently in one of our project we have an android background service. Which we used to send some periodic updates to server. Later we identified an issue that the service was not restarted when phone restarts or switched off by low battery and power on again. In this blog I will explain you how to restart background service.

First of all you have to register a receiver for the device boot and power on action in your Android manifest file. This broadcast receiver will be invoked when this action happens. Following is the example code.

<receiver android:name=".BootCompletedIntentReceiver">
  <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
    <action android:name="android.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE" />
  </intent-filter>

</receiver>

As you see above we have added BootCompletedIntentReceiver which is our broadcast receiver and added three actions.

BOOT_COMPLETED
QUICKBOOT_POWERON
ACTION_EXTERNAL_APPLICATIONS_AVAILABLE

BOOT_COMPLETED and QUICKBOOT_POWERON actions are invoked when phone powers on. ACTION_EXTERNAL_APPLICATIONS_AVAILABLE is required if your application is installed in external memory.

After that add following class to your project.

package com.mypackage.app;

import java.util.Calendar;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import com.mypackage.app.BackGroundService;

public class BootCompletedIntentReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Intent serviceIntent = new Intent(context,
BackGroundService.class);
PendingIntent pintent = PendingIntent.getService(context, 0,
                                serviceIntent, 0);
                Calendar cal = Calendar.getInstance();
                int interval = 5;
                interval = interval * 60 * 1000;
                PendingIntent pintent = PendingIntent.getService(getBaseContext(), 0,
                               serviceIntent, 0);
                AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
                               alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
                                interval, pintent);
}
}


As you can see in above code. We have added BootCompletedIntentReceiver which extends broadcast receiver. onReceive event is called when there is an action and in that event we are creating pending and service intent for our background service and set alarm to invoke service at regular interval. 

Hope this posts help you.

Tuesday, September 2, 2014

Showing Multiple Routes on Map with Google Direction Services

Recently in one of our project we have to show routes between two points on map. Those two points can be on same way or can be on different ways. So there were multiple routes. There are ways to do that with Google direction service. One way is that you set way points while plotting routes on the map. But in our case points were random so that would be possible. So in this blog I am going to mention trick I have used.

For showing multiple paths we have to create separate DirectionsRenderer for each route. So first we get latitude and longitude each points in an array. For example I have 4 lat longs in an array that means there will be three paths. From point 0 to point 1, point 1 to point 2 and point 2 to point 3. So we have to create three separate requests and three separate DirectionsRenderer. You can not simply use for loop here as route API has callback functions when it receives routes. So here I have used recursion function. For example you have all the points in an array called markers.  First we will generate Google Map LatLong.

for (i = 0; i < markers.length; i++) {
      var data = markers[i];
      var myLatlng = new google.maps.LatLng(data.lat, data.lng);
      lat_lng.push(myLatlng);
}

Now we will create request for each path separately.

var requestArray = [], renderArray = [];
var cur = 0;
var service = new google.maps.DirectionsService();
for (var i = 0; i < lat_lng.length  -1; i++) {
     var request = {
  origin: lat_lng[i],
           destination: lat_lng[i+1],
   travelMode: google.maps.DirectionsTravelMode.DRIVING
     };
     requestArray.push(request);
 }

So now we have all the requests created we will start with first request.

if(requestArray.length > 0){
     service.route(requestArray[cur], directionResults);
}
   
function directionResults(result, status) {
   if (status == google.maps.DirectionsStatus.OK) {
          renderArray[cur] = new google.maps.DirectionsRenderer();
          renderArray[cur].setMap(map);
          renderArray[cur].setDirections(result);
   }
   cur++;
   if(cur < requestArray.length){
    service.route(requestArray[cur], directionResults);
   }
}

As you see in above code we have variable named cur which is initialized with zero. We start with first request. directionResults is our callback function. Inside direction function we are creating a DirectionsRenderer and setting map and result to it. After that we increase the count and go to next request. Once all the requests are completed you stop the recursion. Using this you can achieve following result.


Hope this helps you.

Monday, September 1, 2014

Sencha Touch - One Way to Implement Autosuggest Textbox

Hello,

Recently in one of our Sencha Touch project there was a requirement to add autosuggest textbox. As user starts typing there should be some suggestions and user should be able to either select one of the option or type in the value. In this blog I am going to explain the approach I used for that. Please note that there could be other ways to implement this.

First lets create a store that has the options for auto suggestions. For that here is the model definition.

Ext.define('MyApp.model.Option', {
    extend:'Ext.data.Model',
    config:{
        fields:[
            { name:'id', type:'int' },
            { name:'text', type:'string' },
        ],
        idProperty: 'id'
    }
});

Now lets create a store which holds the data.

Ext.define('MyApp.store.Option', {
  extend: 'Ext.data.Store',
  config: {
    model: 'MyApp.model.Option',
    autoLoad: true,
    proxy: {
      type: 'memory'
    },
    data : [
        {id: 1,    text: "Option 1"},
        {id: 2, text: "Option 2"},
        {id: 3, text: "Option 3"},
        {id: 4, text: "Option 4"}
    ]
  }
});

Now our approach is quite simple we will create a floating panel with list and assign this store to it and as soon as user starts typing in textbox, we will show this panel near to textbox and filter store with what is typed in textbox. So lets create a floating panel.

Ext.define('MyApp.view.Traffic.AutoSuggestPanel', {
extend: 'Ext.Panel',
xtype: 'autosuggestpanel',
config: {
modal: true,
hideOnMaskTap: true,
hidden: true,
height: '180px',
width: '94%',
layout: 'fit',
margin: '-9px 0 0 0',
items: [
{
xtype: 'list',
id: 'autoSuggestList',
itemId: 'autoSuggestList',
itemHeight: 30,
itemTpl: '<div style="font-size: 13px">{name}</div>',
store: 'Option'
}
]
}
});

We will add this panel to viewport when app launches, as you see it's hidden initially so it will not be visible.

Ext.Viewport.add(Ext.create('MyApp.view.Traffic.AutoSuggestPanel'));

Now lets add keyup event to textfield on which we want to show this suggestions. Also we will add our floating panel as reference to controller.

 config: {
        refs: {
              autoSuggestPanel: 'autosuggestpanel'
              autoSuggestList: '#autoSuggestList',
              autoSuggestTextField: '#autoSuggestTextField'
       }
}

autoSuggestTextField: {
            keyup: 'onAutoSuggestTextFieldKeyUp'
            },
autoSuggestList: {
            itemtap: 'onAutoSuggestListItemTap'
            },

And define it's handler in controller.

onAutoSuggestTextFieldKeyUp: function(text){
        if( this.getAutoSuggestPanel().isHidden( ) ) {
            this. getAutoSuggestPanel().showBy(text,'bc-tc' );
        }

        Ext.getStore('Option').clearFilter();
        Ext.getStore('Option').filter('text',text.getValue());
}


Above code will show auto suggest list next to textfield. Now we have to add itemtap event for the list and set it's value in textbox. Here is handler for it.

onAutoSuggestListItemTap: function(list, index, target, record){
        var name = record.get('text');
this. getAutoSuggestPanel().hide();

       this.getAutoSuggestTextField().setValue(name);
}

That's it and you have autosuggest textbox ready.

Tuesday, August 12, 2014

Sencha Touch List Set Dynamic Height

Hello,

Recently in one of my project, there was a requirement to create a list which has items of different height and we have to set height of the list as per number of items. For example one item has height 80 pixel and other two items have height 100 pixel so list height should be set to 280 pixels. In this blog I will explain how to do this.

As we all now list needs a container with fit or card layout so inside that list can be scrollable based on number of items While in our case we have to make complete panel scrollable along with list so we have to list height as per number of items. For that there is one simple way if items height is fixed. For example if item height is 20 pixel and list has 10 items you can set list height to 200 so all the items would be visible. But in case you have variable heights in items you can use following approach. We will loop through each items in the list and get item element client height. Add it together and set list height to sum of all the item heights.

For example we have list with following config

{
      xtype: 'list',
      itemId: 'myList',
      id: 'myList',
      scrollable: false,
      itemHeight: 80,
      store: 'myStore',
      itemTpl: '<div>{longOrShortText}</div>'
}

And we have added reference in controller.

myList : '#myList'

Now in controller when your store is loaded you can add following logic

var totalHeight = 0;
var items = this.getMyList().getViewItems();
var itemsLn = items.length;
for (i = 0; i < itemsLn; i++) {
     item = items[i];
     totalHeight = totalHeight + item.element.dom.clientHeight;
}
this.getMyList().setHeight(totalHeight);

So here we are looping through all the items, find out item client height and add it together and set list height. Hope this helps you.