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.

Monday, June 23, 2014

How to Access $scope Variable Outside AngularJs Controller

Recently I was working with AngularJs and there was a requirement to call a AngularJs controller function forcefully from other events.  So for that we have to access $scope variable of a controller. This short blog is about accessing $scope variable.

In AngularJs all the scopes are bound to DOM so to access $scope first we have to get the HTML element. You can either use jQuery selectors to get elements or you can use standard document.getElementById method. For example.

var scope= angular.element($(".classselector")[0]).scope();

This gives you the scope of the the element. Once you have the scope you can call respective method of controller.  There is also other way to find out the scope if you don't have reference to element. You can find scope by name of controller.

var scope = angular.element($('[ng-controller=myController]')).scope();

After you make changes to variables of scope you have to call apply method so the AngularJs framework is notified about changes.

scope.$apply();

Hope this helps you.


Saturday, June 21, 2014

AngularJs Communicate Between Directives and Controllers

Hello,

Recently in one of my project we were using AngularJs and created a directive for timepicker where user can enter timer in hh:mm AM/PM format. Now on one of the HTML form we have a button. When the button is clicked we have to disable the input for the timepicker. For that we have to access scope of directive from scope of AngularJs controller so that se can disable the respective field. In this blog I am going to explain how to do this.

AngularJs allows you to create directives with isolated scope which has some binding to parent scope. Bindings are defined by specifying attributes in HTML.  In some cases it may not be good as it's hard to synchronize both the scopes. So ideally parent and directive scope should be maintained separately. Better way to communicate between directives and controllers is through directive attributes. Let's see and example.  I have defined my HTML as follow for my timepicker directive.

<timepicker is-not-open="notOpen" hour-step="1" minute-step="30" show-meridian="true"></timepicker>

As you can see above is-not-open is the attribute defined for directive and it is bind to notOpen variable in my controller.

$scope.notOpen = false;

Now lets see how to mention attribute in directive scope.

angular.module('ui.bootstrap.timepicker', [])
.directive('timepicker', ['timepickerConfig', function (timepickerConfig) {
  return {
    restrict: 'EA',
    require:'?^ngModel',
    replace: true,
    scope: { isNotOpen: "=" },
    templateUrl: 'template/timepicker/timepicker.html',
    link: function(scope, element, attrs, ngModel) {
     
    }
  };
}]);

As you can see in above code we have defined attribute with scope: { isNotOpen: "=" }. Now you can define a function to watch this variable in directives. For example there is a method in parent controller which sets notOpen variable to true.

$scope.setNotOpenStatus = function(){
      $scope.notOpen = true;
}

Once it is set here, the directive is notified about the change and as I mentioned you can keep watch on the attribute.

scope.$watch('isNotOpen', function (newValue, oldValue) {
          if(newValue == true){
              //do something
          }
});

Same way you can have watch function in parent controller which would be notified if attribute value is changed inside directive.

Hope this helps you.

Tuesday, June 3, 2014

Introduction to Swift - the latest programming language from Apple

So Apple stunned all the developers around the globe by introducing new language instead of new iPhones, iPhones or iWatches. Let's see what exactly is the Swift.



Apple says the following about the release of Swift:

"Swift is a powerful new programming language for iOS and OS X® that makes it easier than ever for developers to create incredible apps. Designed for Cocoa® and Cocoa Touch®, Swift combines the performance and efficiency of compiled languages with the simplicity and interactivity of popular scripting languages. By design, Swift helps developers write safer and more reliable code by eliminating entire categories of common programming errors, and coexists with Objective-C® code, so developers can easily integrate Swift into their existing apps. Xcode® Playgrounds make writing Swift code incredibly interactive by instantly displaying the output of Swift code."

Swift code can live right besides C and Objective-C code in the same app. The syntax is quite similar to JavaScript. Here are some of the features of it.


  • Closures (similar to blocks in C and Objective-C) unified with function pointers
  • Tuples and multiple return values
  • Generics
  • Fast and concise iteration over a range or collection
  • Structs that support methods, extensions, protocols.
  • Functional programming patterns, e.g.: map and filter

Here is the first lesson of Swift. How to define a variable and a constant. Constants and variables must be defined before they are used. You can define constants with let keyword and variable with var keyword. For example

let maximumLoginAttemptsAllowed = 10
var currentLoginAttempt = 0

So here is a constant maximumLoginAttemptsAllowed which has a value 10 and a variable currentLoginAttempt which has value 0. 

Saturday, May 31, 2014

Sencha Touch Create Navigation Drawer (Slide Navigation Like Gmail)

Recently in one of our sencha touch project we have created Navigation Drawer for sencha touch. In this blog I will explain how to create it.

Let's first understand what is navigation drawer. We are all familiar with Facebook slide navigation. It has button on top left corner of toolbar, when you tap on it, the content in center slide to right and menu opens with left to right animation. When you again tap on that menu is closed with right to left navigation and center content slides to left. Navigation drawer is introduced in Android 4.0. It's  slight variation of slide menu. Here the center content does not slide left or right but the menu comes on top of slide content. However the top toolbar is still accessible so user can still close the menu. Now lets see how to create this in sencha touch. Please note that this is the one way we used to create navigation drawer, there could be other options as well.

First lets create a list which will act as navigation menu.

Ext.define('SlideNav.view.Navigation', {
    extend: 'Ext.List',
    xtype: 'navigation',
    modal: true,
    hideOnMaskTap: false,
    requires : ['Ext.data.Store'],
    config: {
        width: 250,
        itemTpl : '{title}',
        data : [
            {
                title : 'Item 1'
            },
            {
                title : 'Item 2'
            },
            {
                title : 'Item 3'
            }
        ]
    }
});

As you can see in above code we created a list and set it as modal element with modal config. List extends Ext.container so we can open it as modal element. This is our navigation menu. Now lets add a button on top left corner of our toolbar and create the main view.

Ext.define('SlideNav.view.Main', {
    extend: 'Ext.Container',
    xtype: 'main',
    config: {
        style: {
            zIndex: -1,
            position: 'absolute'
        },
        layout:{
            type: 'card',
            align: 'stretch'
        },
        items: [
            {
                xtype: 'toolbar',
                docked: 'top',
                title: 'Slide Navigation',
                items: [
                    {
                        xtype: 'button',
                        iconCls: 'list',
                        ui: 'plain',
                        itemId: 'slideNavBtn',
                        id: 'slideNavBtn'
                    }
                ]
            },
            {
                xtype: 'panel',
                itemId: 'slideContainer',
                layout: 'card',
                id: 'slideContainer',
                items: [
                    {
                        xtype: 'panel',
                        html: 'Hello Welcome to The Design Shop.Sencha Touch is very good framework.'
                    }
                ]
            }
        ]
    }
});

So this is our main view and it has toolbar with top navigation button. Now lets add tap event for it in controller and add logic to open and close the menu.

Ext.define('SlideNav.controller.App',{
    extend: 'Ext.app.Controller',
    config:{
        refs:{
            main : 'main',
            navigation : 'navigation',
            navBtn : '#slideNavBtn'
        },
        control : {
            navBtn : {
                tap : 'toggleNav'
            }
        }
    },
    init: function() {
        this.toggle = 0;
    },
    toggleNav : function(){
        var me = this;
        if(!me.getNavigation()) {
            Ext.create('SlideNav.view.Navigation');
            Ext.Viewport.add(me.getNavigation());
            me.getNavigation().show();
        }
        if(this.toggle == 0) {
            Ext.Animator.run({
                        element: me.getNavigation().element,
                        duration: 500,
                        easing: 'ease-in',
                        preserveEndState: true,
                        from: {
                            left: -250
                        },
                        to: {
                           left: 0
                        }
        });
        this.toggle = 1;
        }
        else {
        Ext.Animator.run({
                            element: me.getNavigation().element,
duration: 500,
easing: 'ease-in',
preserveEndState: true,
from: {
left: 0
},
to: {
left: -250
}
});
            this.toggle = 0;
        }
    }
});

As you can see in above code we are using one controller variable toggle to know the state of menu and and on tap of it first we create the navigation and menu and add it to viewport and then we are using Ext.Animator to open it with animation. So basically we are setting left property from -250 to 0 as 250 is the width of the menu. You can change it according to your requirement or set dynamic width here.

Wednesday, May 28, 2014

AngularJs and $scope.$apply - When and How to use $apply for AngularJs scope

In this blog I will explain when to use $apply for AngularJs $scope and how to use it. You may have encountered the situation where you update the variables bind to AngularJs view but it does not update views. So here I will explain why it happens and how to resolve it. Also you need to know how to use $apply carefully else it may give you error that $apply is already in progress.

First lets understand how the AngularJs data binding works.AngularJs framework monitors data changes with the digest cycles. That means it checks it frequently in digest cycle then framework will be notified if you have made any changes in managed code. But there are chances that you have some external events like Ajax callbacks or some native click events. These event runs outside the scope of AngularJs digest cycles. So the framework does not know about any changes made during this events. You have to tell the framework that there are changes. Here $apply comes to the picture. It lets you start digest cycle explicitly. So that your frameworks knows that there are changes. Lets assume that you have variable $scope.myVar and you changed its value in native click event. So you need to tell Framework that it is changed. So if you simply use,

$scope.myVar = 'New Value';

It will not work. Instead of this you have to use

$scope.$apply(function(){
      $scope.myVar = 'New Value';
});

or you can use this syntax.

$scope.myVar = 'New Value';
$scope.$apply();


This shall notify the framework that the value is changed. It's not always safe to use $apply as I mentioned earlier. If the digest cycle is already in progress and you try to set it and with $apply it will give you an error. So if you have condition like your variable is updated at common function which you calls from AngularJs managed code and outside events. you have to first check it digest cycle is already in progress. If not then only use $apply. You can check it with following code.

if ($scope.$root.$$phase != '$apply' && $scope.$root.$$phase != '$digest') {
       $scope.myVar = 'New Value';
       $scope.$apply();
}

This will be the safe apply and it will not give you any error .


Friday, May 23, 2014

Make Sencha Touch Site With Routes SEO Friendly

Recently in one of our project which was a sencha touch app we faced an issue with SEO. As far as I know a site should have all the unique URLs for better SEO. With unique url Google crawler can crawl your URLs more efficiently. Now this could be the issue with Sencha Touch app as we know. We open sencha touch app with our domain URL and then we don't have any URL changes. All our views are loaded locally. So our url will stay like http://mydomain.com/app/index.html.

Now this is not good for SEO as your URL is not changing so google can not index your site. Now this is not good if you are selling your products on your site as normally people search with product name and they can not find your site urls in Google. So what to do? To resolve this issue sencha has introduced routes and history support. So what it does is it changes your URL as and when you navigate through sencha app. Something like

http://mydomain.com/app/index.html#productlist/cat1name
http://mydomain.com/app/index.html#productdetail/product-name

So now you have all the unique urls on your site so those urls can be indexed by Google and can be displayed in search result. But wait we have another problem here. Google ignores all the content of the url after hash tag. So after using routes we are back to the same problem again.  Still our sencha touch app is not SEO friendly. So what to do now. Google suggest to use Hash Bangs(#!) instead of Hash tag (#) So if use this our routes will not work as it works only on has tag so what to do? We have to modify our sencha touch routes logic to work with Hash Bangs (#!) For that if you are manually adding history as follow, you have to override add history function.

MyAppName.app.getHistory().add(new Ext.app.Action({
            'key': 'value'
}), true);

It will convert your url as follow.

http://mydomain.com/app/index.html#key/value

You have manually insert exclamation mark (!) here.

MyAppName.app.getHistory().add(new Ext.app.Action({
            '!key': 'value'
}), true);

Now your url looks like below.

http://mydomain.com/app/index.html#!key/value

So it's a Hash Bangs and now this URL can be indexed by Google. But that will break your routes logic as now your key would be !key. To make it working you have to change your root definition and add you have to prefix it with . See the example below.

routes: {
            '! productlist/: text': 'goToProductList',
            '! productdetail/:text' : 'goToProductDetail'
}

That's it and your routes will work as usual. So with this trick a developer is happy, a customer is happy and a SEO guy is happy.

Passing Variables to Laravel View Blades from Controllers

Hello,

This is my first blog on Laravel. I have been working with Laravel since last few weeks. It's a nice and flexible framework. In this blog I am going to explain how you can pass variables to Laravel view blade from controllers.

This will help you when you want to pass some variables that may have boolean values using which you want to show hide some part of UI or you want to pass arrays to view and iterate through it and create dynamic html. So first we are going to create views inside controller as follow.

$this->layout->content = View::make('Views.View1');

This will call Views.View1.blade.php file and render it's layout.

Now lets assume we want to pass variables to it as we have following code in view.

 @if ($showDiv == true)
<div> This div will only be visible if $showDiv variable is set to true </div&gt
@endif

Also lets assume we want to iterate through and array and create dynamic list.

<ul class="dropdown-menu">
      @foreach ($names as $name)
               <li>{{$name}}</li>
      @endforeach
</ul>

Now lets see how to pass this.

In your controller create variables as folllow

$showDiv = true;
$names = array("John", "Jack", "Smith", "James");

Now we will share this variable with view using share function.

View::share('showDiv', $showDiv);
View::share('names', $names);

That's it, now these variables are available in view and views will be rendered according to logic. So key thing is to use share function of view to share variables with view. If you don't share like this you may get an error that variable in blade undefined.



Thursday, May 22, 2014

Add Buttons on Headings of AngularJs BootstrapAccordion

Recently in one of my projects we were using AngularJs and Bootstrap UI. We have a layouts where we have buttons on heading of accordion and we have to add click events for it.



So we know the behavior of accordion. When we click on headings of accordion it actually expands it. In My case I have to stop and that and invoke button click function. In this blog I will explain this.

Basic idea is to stop event propagation. So when we click on button it will invoke handler for it and and if we stop propagation of event in that function it will not expand the accordion view. Lets assume we have following delete button on accordion heading.

So when I click on delete it should actually remove that record instead of opening the accordion. For that add click handler for the buttons as follow.

<accordion-heading>
     <div>
          Options
     </div>
     <div style="float:right">
          <button ng-click="deleteItem(item, $event)" type="button" class="btn" style="color: #000"               >Delete</button>
     </div>
</accordion-heading>

As you can see in above code we have added click event handle with ng-click and we are passing item and event as parameter. Now in controller add the event handler.

$scope.deleteItem = function(item, $event){
      $event.stopPropoagation();
}

As you can see in above code we are using stopPropagation method of event object to stop event propagation. Hence the event does not propagated and accordion will not expand. If you click anywhere else it will open it but if you click on delete button it will not invoke it. Hope this helps you.

Friday, May 16, 2014

Ad hoc App Installation Failed in iOS Devices

This blog post is about the recent problem I faced in installing Ad Hoc application in iOS devices. Recently I was working with a app where I generated add hoc iPA file for the distribution on registered devices. But some how it was not installed on registered devices. When you try installing application with iTunes, it starts installations and after couple of minutes it stuck and never finish installation. It took some time to figure out the issue so here in this blog I will explain this.

So when you face this situation and if you see the device log you will find following error in it.

install_application: Could not preflight application install

That means something is wrong with installation and most probably it's the issue of the provisioning profile you are using. For that first clean the build from Xcode. Check the device id in list of the registered devices. If it's not there add it and regenerate your distribution profile. Now go to Xcode and select the project and go to general tab. Make sure you have added the apple developer account and selected the correct team.
 Now go to Build Settings tab and go to Code Signing section. Make sure you have selected correct distribution certificate for release and selected correct distribution profile. See the screenshot attached below.


Here if you have selected development provisioning profile and then it will not work so right selection for code signing identity and provisioning profile is must. Now you can generate archive and export the iPA file when you sync it with iTunes it will get installed properly.  Hope this will help you.

Monday, May 12, 2014

iOS 7 Phonegap Change Background Color of Status Bar

Hello,

Recently I was working on Sencha Touch, Phonegap application where we have a requirement to change background color of top status bar of iPhone where we have carrier, wifi and battery symbols. There are two ways to do it. In this blog I will explain both the steps.

First Step

In iOS 7 if you have status bar visible your UI will overlap the status bar and we will take advantage of it. First select your project and go to Deployment info. Make sure you have Hide during application launch checkbox and set status bar style as default.

Now your webview will overlap the UI and the status bar will be transparent. So we can add a component on top of our page with height 20 pixel and preferred background color so your status bar will have same background color. For example I added docked panel in Sencha Touch with fixed height and background color in my main container. 

Ext.define('MyApp.view.LaunchView', {
    extend : 'Ext.Panel',
    xtype : 'launchmain',

    config : {
        layout : 'card',
        
           items : [{
                    xtype: 'panel',
                    docked: 'top',
                    style: {
                        'background-color': '#34495E',
                        'color':'#ffffff'
                    },
                    height: 20
                    
           }]
    }
});

Since this is may main container all the views added in this container will have this panel and top. Now issue could be if you have some external pages loaded in app on which you don't have control then this panel will not be there you can not have top component with background color. For that follow step 2

Second Step

Here in this step we will add component on top of our webview in our main iOS 7 view. Hence it will be available throughout the app. For that add following code in didFinishLaunchingWithOptions method of AppDelegate.m

 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        UIView *topView = [[UIView alloc] init];
CGRect screenRect = [[UIScreen mainScreen] bounds];
        topView.frame = CGRectMake(0, 0, screenRect.size.width, 20);
        topView.backgroundColor = [UIColor colorWithRed:52/255. green:73/255. blue:94/255. alpha:1];
        [self.window.rootViewController.view addSubview: topView];
    }

Here we are added another view with required background color on top of webview. Now we have to shift down webview for 20 pixel so that this view would be visible. For that add following code to viewDidLoad function of your MainViewController.m file. 

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
        CGRect viewBounds = [self.webView bounds];
        viewBounds.origin.y = 20;
        viewBounds.size.height = viewBounds.size.height - 20;
        self.webView.frame = viewBounds;
    }

As you can see in above code we are changing the origin of webview and shift it 20 pixel down. You can simply add above code to avoid overlapping of UI.


Saturday, April 26, 2014

AngularJs Pass Data Between Controllers

Hello,

This is my first blog on AngularJs. I have been working with AngularJs since last three or four weeks and I am very excited about this Framework. It has nice features like two way data binding, templates, MVVM model, directives. That makes this framework super cool. I will be adding more blogs in future for AngularJs. In this blog I will explain how to pass data between controllers.

For this first we have to understand $rootScope. Every AngularJs application has one root scope and all other scopes are children of root scope. It's like application wide global variable.

Now lets see how we can use this to share data between controllers. First we need a service which is common in both controllers. We will invoke a service function from a controller which wants to send data. Service will broadcast it and using $rootScope. While the receiver controller will listen to the broadcast event and receives that data. First lets crete a service and function.

var servicesModule = angular.module('myapp.broadcastservice', []);

servicesModule.factory('BroadcastService', ['$http', '$rootScope', function ($http, $rootScope) {

   var service = {};
   service.sendData = function(data){

      $rootScope.$broadcast('message', data);
   }

}

Now lets create sender controller.

appRoot.controller('SenderController', ['$scope', 'BroadcastService',
   function ($scope, BroadcastService) {
        $scope.sendData = function(){
              BroadcastService.sendData("My Message");
        }
   }
]);

Now lets create a receiver controller

appRoot.controller('ReceiverController', ['$scope', 'BroadcastService',
    function ($scope, BroadcastService) {
        $scope.$on('message', function(response, data) {
            console.log(data);
       });
    }
]);

As you can see from sender controller we invoke service function and broadcast message with event message and in receiver controller we receive it by listening to message event using $scope.$on.

This way you can pass data between AngularJs controllers. Hope this post helps you.   

Android Slide Menu like Facebook With Effect Like Navigation Drawer

Recently in one our project we have to build slide out menu like Facebook but with some difference. In Facebook app when slide menu opens the main content screen also goes left or right. While in our case main content should stat and menu should come over the content like Navigation Drawer. For certain reasons we could not use Navigation Drawer class as we have the fragments in the application.

So we accomplished it with some different manner. In this blog I will explain you how to do this. First lets see our Main Layout XML file.

&ltcom.myapp.layout.MainLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#221010" >

<!-- This holds our content -->
    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

         <FrameLayout
                android:id="@+id/activity_main_content_fragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/white" >
         </FrameLayout>
         <RelativeLayout
                android:layout_width="fill_parent"
                android:layout_height="70dip"
                android:alpha="0.9"
                android:background="#d84047"
                android:orientation="horizontal" >

                <Button
                    android:id="@+id/activity_main_content_button_menu"
                    android:layout_width="30dip"
                    android:layout_height="30dip"
                    android:layout_marginBottom="10dip"
                    android:layout_marginTop="18dip"
                    android:background="@drawable/menu"
                    android:onClick="toggleMenu" />
         </RelativeLayout>
    </FrameLayout>

 <!-- This holds our menu -->

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >
    </LinearLayout>

</com. myapp.layout.MainLayout>

So in our layout we have FrameLayout with top toolbar with menu button which will open our menu. and a content layout which holds out main content. Now our menu should occupy 70% of available space when it opens so for that we have to set width and height for it. Lets create MainLayout class in app and configure this.

package com. myapp.layout;

import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Interpolator;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import android.widget.Scroller;


public class MainLayout extends LinearLayout {

int mainLayoutWidth;
private View menu;
private View content;
private int contentXOffset;
private MenuState currentMenuState = MenuState.HIDDEN;
private enum MenuState {
        HIDING,
        HIDDEN,
        SHOWING,
        SHOWN,
};
public MainLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
}

public MainLayout(Context context) {
        super(context);
}

// Overriding LinearLayout core methods
   
   
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);      
        mainLayoutWidth = MeasureSpec.getSize(widthMeasureSpec);
    }
   
    // This is called when MainLayout is attached to window
    // At this point it has a Surface and will start drawing.
    // Note that this function is guaranteed to be called before onDraw
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
       
        // Get our 2 child View
        menu = this.getChildAt(1);
        content = this.getChildAt(0);  
       
        // Initially hide the menu
        menu.setVisibility(View.GONE);

    }
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
     
        if(changed) {
            LayoutParams contentLayoutParams = (LayoutParams)content.getLayoutParams();
            contentLayoutParams.height = this.getHeight();
            contentLayoutParams.width = this.getWidth();

            // menu View occupies the full height, but certain width
            LayoutParams menuLayoutParams = (LayoutParams)menu.getLayoutParams();
            menuLayoutParams.height = this.getHeight();
            menuLayoutParams.width = mainLayoutWidth;
        }
        // Layout the child views  
       
        menu.layout(left, top, mainLayoutWidth*0.7 , bottom);
        content.layout(left, top, right , bottom);
       
    }

    public void toggleMenu() {
    this.calledFromToggleMenu = true;
        // Do nothing if sliding is in progress
        if(currentMenuState == MenuState.HIDING || currentMenuState == MenuState.SHOWING)
            return;
       
        switch(currentMenuState) {
        case HIDDEN:
        //show menu here
        Log.v("log","current state is hidden");
       
        TranslateAnimation moveLefttoRight = new TranslateAnimation(menu.getWidth()*-1, 0, 0, 0);
       
        moveLefttoRight.setAnimationListener(new Animation.AnimationListener(){
           @Override
           public void onAnimationStart(Animation arg0) {
            menu.setVisibility(View.VISIBLE);
            menu.bringToFront();
           }          
           @Override
           public void onAnimationRepeat(Animation arg0) {
           }          
           @Override
           public void onAnimationEnd(Animation arg0) {
           
           }
        });
       
            moveLefttoRight.setDuration(300);
            moveLefttoRight.setFillAfter(true);
            menu.startAnimation(moveLefttoRight);
            currentMenuState = MenuState.SHOWN;
            break;
        case SHOWN:
        //hide menu here
        Log.v("log","current state is visible");
        TranslateAnimation moveRightoLeft = new TranslateAnimation(0, menu.getWidth()*-1, 0, 0);
        moveRightoLeft.setDuration(300);
        moveRightoLeft.setFillAfter(true);
            menu.startAnimation(moveRightoLeft);
            currentMenuState = MenuState.HIDDEN;
            moveRightoLeft.setAnimationListener(new Animation.AnimationListener(){
           @Override
           public void onAnimationStart(Animation arg0) {
           
           }          
           @Override
           public void onAnimationRepeat(Animation arg0) {
           }          
           @Override
           public void onAnimationEnd(Animation arg0) {
            Log.v("log","hiding menu");
            content.bringToFront();
           }
        });
            break;
        default:
            break;
        }
        // Begin querying
        //menuHandler.postDelayed(menuRunnable, QUERY_INTERVAL);
       
        // Invalite this whole MainLayout, causing onLayout() to be called
        //this.invalidate();
    }

}

As you can see in above class we have extended LinearLayout and it's core method and created an extended class. Where onLayout method we are hiding the menu and setting it's width to 70% width of the screen. Key function here is toggleMenu. It identifies the state of the menu and based on that show animation and show/hide the menu. You just have to call toggleMenu function when users taps on button. To close the menu user has to swipe left on the screen and it will close the menu. See the below code.

package com.myapp;
import com.myapp.layout.MainLayout;

public class MainActivity extends FragmentActivity implements
OnTouchListener{
public static MainLayout mainLayout;
      protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_market_place);
mainLayout = (MainLayout) this.getLayoutInflater().inflate(
R.layout.activity_main, null);
setContentView(mainLayout);
                btMenu = (Button) findViewById(R.id.activity_main_content_button_menu);
btMenu.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Show/hide the menu
mainLayout .toggleMenu(v);
}
});
      }

      @Override
       public boolean dispatchTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
super.dispatchTouchEvent(ev);

switch (ev.getAction()) {

case MotionEvent.ACTION_DOWN: {
// store the X value when the user's finger was pressed down
downXValue = ev.getX();
downYValue = ev.getY();
Log.v("", "= " + downYValue);
break;
}

case MotionEvent.ACTION_UP: {
// Get the X value when the user released his/her finger
float currentX = ev.getX();
float currentY = ev.getY();
// check if horizontal or vertical movement was bigger

if (Math.abs(downXValue - currentX) > Math.abs(downYValue
- currentY)) {
Log.v("", "x");
// going backwards: pushing stuff to the right

Log.v("log", " downXvalue - currentX "
+ (downXValue - currentX));

if (downXValue < currentX) {
Log.v("", "right");
if (-150 > (downXValue - currentX)) {
Log.v("log", "right if");
mainLayout.toggleMenu("OPEN");
} else {
Log.v("log", "right else");
}
}

// going forwards: pushing stuff to the left
if (downXValue > currentX) {
mainLayout. toggleMenu("CLOSE");

}

} else {
Log.v("", "y ");

if (downYValue < currentY) {
Log.v("", "down");

}
if (downYValue > currentY) {
Log.v("", "up");

}
}
break;
}

}
return true;
}
}

As you can see in above code we are setting MainLayout as content layout for the activity added on click listener for menu button. Which invokes toggleMenu function of mainLayout and toggles the menu. Also we have added dispatchTouchEvent method where we tracking user motion and invoke toggle menu method.

Hope this helps.

Android Use FrameLayout for Overlapping Items

Hello,

Recently in one of my project we have a layout where we have transparent top and bottom bar and which overlaps content of the screen. Content was the list view so when you scroll up or down the list view content goes under overlapping top and bottom bar where we can see it as the both top and bottom bars were transparent. Something like this.


So in this blog I am going to explain how to do this type of layout. I have used FrameLayout for this. As FrameLayout automatically sets the z-index for all it's child items as per the order. So following is our layout XML for this.

 <!-- Main frame layout -->
<FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

<!-- Main Content layout -->
<LinearLayout
            android:layout_width="fill_parent"
            android:id="@+id/contentPane"
            android:layout_height="wrap_content"
            android:layout_weight="1" >
</LinearLayout>

<!-- Relative Layout for top and bottom bar -->
<RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" >

<!-- top bar -->
<RelativeLayout
                android:layout_width="fill_parent"
                android:layout_height="70dip"
                android:alpha="0.9"
                android:orientation="horizontal" >
 </RelativeLayout>

<!-- Bottom bar -->
<RelativeLayout
                android:layout_width="fill_parent"
                android:layout_alignParentBottom="true"
                android:layout_height="70dip"
                android:alpha="0.9"
                android:orientation="horizontal" >
 </RelativeLayout>

</RelativeLayout>

</FrameLayout>

As you can see in above XML first we have frame layout inside frame layout we have linear layout as our content layout where we have set layout weight property as 1 so this component will take whole space for the frame layout.  After that we have used Relative layout and inside it we have or top and bottom bar as relative layout for bottom bar we are using android:layout_alignParentBottom config and set is true so it will go to bottom.  This is how you can have overlapping views in android.  Hopw this helps you.



Monday, April 21, 2014

Cordova build JAR File From Source Code (For MAC OSX only)

As we know that now Cordova only support command line interface. Earlier with download you get cordova.jar file, that you can directly import to eclipse project and create android cordova file. Now with new download you only get source code, you have to manually generate cordova.jar file and import to eclipse. In this blog I will explain you the steps. First download Cordova source code from the Download.

Extract the content on the desktop. Now you will need following two things.

Apache Ant 1.8.0 or greater
Android SDK which you can download from Android Developer Portal

Download and extract SDK to desktop. Now we will install apache ant. Open the terminal and run following command.

ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"

After homebrew is installed we will install ant.

brew install ant

Now ant is installed, we will configure modify paths in bash profile file for android SDK. Run following command in terminal

nano ~/.bash_profile

Go to and of the file and paste following code.


export PATH=/Users/yourusername/Desktop/adtdirectotyname/sdk/tools:$PATH

Click Control+X, Y, Enter. It will save your new file. Now go to your Cordova source code and go to cordova-android/framework and run following command.

android update project -p . -t android-19
ant jar

And it will generate cordova .jar file in the framework folder, you can use that file in your eclipse.

Saturday, April 19, 2014

How to solve MySql errorno : 150 "Can't Create Table"

Recently I faced one issues while creating tables in database. I was adding primary and foreign key in tables and I get errorno : 150 "Can't Create Table" I took almost couple of hours to resolve that error so in this blog I am going to explain what could be possible cause for this error. If you get this error check following possible cause.

1) The two tables must have same storage ENGINE

As we know we can configure storage engines like MyISAM, InnoDB. When you add foreign key to the table both parent and reference table should have same storage engine.

2) The two tables must have the same charset.

MySql supports more than 30 character sets. Both parent and reference table should have the same charset.

3) Primary key and Foreign key column must have same datatype.

When you add a foreign key, the primary key in parent table must have the same datatype as foreign key. For example if you have following definition of primary key

id INT UNSIGNED NOT NULL AUTO_INCREMENT

then you must define foreign key as

pk_id INT UNSIGNED NOT NULL

Else it will give you an error and will not work.

4) Primary key and Foreign key column must have same collation type

MySql supports more than 70 collation type. To define primary key and foreign key both columns should have same collation type

5) If there is already data is must match 

If there are already data in both the tables it should match otherwise MySql will not allow to add foreign key. If there is data inconsistency, first delete the inconsistent data and then add primary key.

6) If the reference column is part of composite primary key, it may not work.

If the referenced column is part of composite primary key it may not work so if it's not required to have composite primary key, just define single column as primary key.

Hope this helps you.

Add Tap Hold Event in Sencha Touch panel

Recently in one of my project, requirement was to display context menu when user tap and hold on sencha touch panel. We all know we can add itemtphold event on sencha touch list. But in my case I have to use panel. In this blog I will explain how to add tap hold event to sencha touch list.

The logic is simple , first of all we have to bind touchstart and touchend event on panel. When touch starts we will check after some interval if touchend event is fired or not. If there is no touch event fired that means user is still holding tap. See the code below.

{
      xtype: 'panel',
      html: 'tap and hold',
     listeners: {
                            painted: function(element){
                            var isTouch = false;
                            element.on({
                            touchstart: function(){
                            isTouch = true;
                            setTimeout(function(){
                            if(isTouch == true){
                                 //There is a tap hold
                            }
                            }, 2000);
                            },
                            touchend: function(){
                            isTouch = false;
                            }
                            });
                            }
                            }
}

As you can see in above code after touch start event we are setting timeout to check isTouch variable after two seconds. You can change the interval according to your need. If touch ends before two seconds we set isTouch to false. So after timeout when this variable is checked you will get false and tap hold event is not fired.  This way you can add tap hold event to any of the sencha touch component.