Monday, June 4, 2012

Google's Protocol Buffer Format - an Android app to convert GPX data to PBF...

i don’t want to give gyan on Google’s protocol buffer format. Please refer to https://developers.google.com/protocol-buffers/ for all the details.
When i studied PBF, i developed an Android app which will convert a GPX file into a PBF file. The GPX file has been downloaded from the internet and it is called fells_loop.gpx. i have put it in the asset folder of my Android app. the generated fells_loop.pbf file has been stored in the SD card in the temp folder. with that i have also created a text file called debug.txt in the same folder. this file gives an human readable form of what has been stored in the PBF file.

for simplicity i have serialized just the latitude and longitude of the GPX file into the PBF file.


please find the source code https://gitlab.com/som.mukhopadhyay/GPXToPBFConversionInAndroid

i have taken the help of a google-code project to build the Android app.

i hope this discussion will help all the programmers who are hooked to Google products and Android.

Sunday, June 3, 2012

Android graphics and animation - pendulum motion and circular motion...

Note : Based on the same animation principles, i have developed this Android game which can be found at Google Play store at
https://play.google.com/store/apps/details?id=com.somitsolutions.training.android.bouncingball

When i was given a task to simulate different functionalities of physics/mechanics, i pondered on it for sometimes. Then i thought to create a simple example app to showcase the concept. this app actually animates the simple pendulum motion on android. it was done using android canvas and sufaceview. you can download the source code from here. the apk is here.

i took the initial angle of the pendulum as PI/4. here is the screen capture of the pendulum motion in the emulator.





the entire locus of the pendulum with respect to time has been divided in 6 parts.

  • the first half of the left to right movement
  • the middle position of the pendulum while moving from left to right
  • the second half of the left to right movement
  • the first half of the right to left movement
  • the middle position of the pendulum while moving from right to left
  • the second half of the right to left movement

the formula of the simple pendulum motion that i have used to calculate the X-Y co-ordinates of the pendulum is

d⍬ = dt/squrt(l/g) where d⍬ is the delta angle shift of the pendulum in the delta time dt.

the crux of this app lies in the class called Panel which is defined as follows:


   
class Panel extends SurfaceView implements SurfaceHolder.Callback{
     
     
     public PendulamThread _thread;
     
     public Panel(Context context) {
      super(context);
       
      
      getHolder().addCallback(this);
      _thread = new PendulamThread(getHolder(), this);
     }

     public void surfaceChanged(SurfaceHolder holder, int format, int width,
       int height) {
      // TODO Auto-generated method stub
      
     }

     public void surfaceCreated(SurfaceHolder holder) {
      // TODO Auto-generated method stub
      
       _thread.setRunning(true);
             _thread.start();
      
     }

     public void surfaceDestroyed(SurfaceHolder holder) {
      // TODO Auto-generated method stub
      
       _thread.setRunning(false);
      
     }
     
     @Override
        public void onDraw(Canvas canvas) {
      
       canvas.drawColor(Color.BLACK);
       anchorX = getWidth()/2;
       
       anchorY = getHeight()/4;
       
       //if(!theCenterBeingDrawn){
       canvas.drawCircle(anchorX - 3, anchorY - 4, 7, mPaint);
        
       
       
       //First Half ... Left To Right
       if(leftToRightMovement == true &&
 rightToLeftMovement ==false && 
atTheMiddlePositionWhileLeftToRight == false &&
atTheMiddlePositionWhileRightToLeft == false &&
firstHalf == true && secondHalf == false){
       
        angleInThePreviousStep = angle;
           
                 angle = angle - dt/Math.sqrt(length/9.81);
                 
                 
           
                 if(angle >0.01){
                  ballX = anchorX - (int)length*(Math.sin(angle));
            
            ballY = anchorY + (int)length*(Math.cos(angle));
                  
            canvas.drawLine(anchorX, anchorY,(float)ballX,(float)ballY,mPaint);
                  
                  canvas.drawCircle((float)ballX , (float)ballY , 14, mPaint );
                 }
                 
                 else{
                  atTheMiddlePositionWhileLeftToRight = true;
                  atTheMiddlePositionWhileRightToLeft = false;
                  leftToRightMovement = true;
                  rightToLeftMovement = false;
                  firstHalf = false;
                  secondHalf = false;
                 }
                  
              
                 
                 return;
                 
       }
       //First Half Left To Right end
       
       //AtTheMiddle while Left To right
       if(atTheMiddlePositionWhileLeftToRight == true &&
 leftToRightMovement == true && 
rightToLeftMovement == false && 
atTheMiddlePositionWhileRightToLeft  == false &&
 firstHalf ==false && secondHalf == false){
       
        angle = 0;
        angleInThePreviousStep = 0;
        flag = true;
        angleAccel = 0;
        angleVelocity = (Math.sqrt(2*9.81*length));
        ballX = anchorX;
        ballY = anchorY + length;
        canvas.drawLine(anchorX, anchorY,(float)ballX,(float)ballY,mPaint);
                 
                 canvas.drawCircle((float)ballX ,(float)ballY , 14, mPaint );
                 
                 atTheMiddlePositionWhileLeftToRight = false;
                 leftToRightMovement = true;
                 rightToLeftMovement = false;
                 atTheMiddlePositionWhileRightToLeft = false;
                 firstHalf = false;
                 secondHalf = true;
                 
                
                 return;
       }
       //at the middle while left to right end
       
       //Left to Right second half
       if(leftToRightMovement == true &&
 rightToLeftMovement == false && 
atTheMiddlePositionWhileLeftToRight == false &&
 atTheMiddlePositionWhileRightToLeft ==false &&
 firstHalf == false && secondHalf == true){
        
        double velocityAtTheBeginning = angleVelocity;//not sure if doing the right thing... forgot mechanics
                
        
        angle += dt/(Math.sqrt(length/9.81));
        
         
        if((initialAngle- angle)>0.01){
        
           ballX = anchorX + (int) (Math.sin(angle) * length); //greater than anchorX
           ballY = anchorY + (int) (Math.cos(angle) * length);//less than anchorY
            
           canvas.drawLine(anchorX, anchorY,(float)ballX,(float)ballY,mPaint);
                     
                 canvas.drawCircle((float)ballX , (float)ballY , 14, mPaint );
                 
        }
        else{
        atTheMiddlePositionWhileLeftToRight = false;
                  leftToRightMovement = false;
                  rightToLeftMovement = true;
                  atTheMiddlePositionWhileRightToLeft = false;
                  firstHalf = true;
                  secondHalf = false;
                  angle = initialAngle;
        }
                 return;
       }
       
       //left to right second half end
       
       ////right to left first half
       if(leftToRightMovement == false &&
 rightToLeftMovement ==true && 
atTheMiddlePositionWhileLeftToRight == false && 
atTheMiddlePositionWhileRightToLeft == false && 
firstHalf == true && secondHalf == false){
        
        angleInThePreviousStep = angle;
           
                 angle = angle - dt/Math.sqrt(length/9.81);
                 
                 
           
                 if(angle >0.01){
                  ballX = anchorX + (int)length*(Math.sin(angle));
            
            ballY = anchorY + (int)length*(Math.cos(angle));
                  
            canvas.drawLine(anchorX, anchorY,(float)ballX,(float)ballY,mPaint);
                  
                  canvas.drawCircle((float)ballX , (float)ballY , 14, mPaint );
                 }
                 
                 else{
                  atTheMiddlePositionWhileLeftToRight = false;
                  atTheMiddlePositionWhileRightToLeft = true;
                  leftToRightMovement = false;
                  rightToLeftMovement = true;
                  firstHalf = false;
                  secondHalf = false;
                 }
                  
                 return;
                 
       }
       
       //Right to left first half end
             
       
       ///at the middle while right to left
       if(atTheMiddlePositionWhileLeftToRight == false && leftToRightMovement == false && 
rightToLeftMovement == true && 
atTheMiddlePositionWhileRightToLeft  == true && 
firstHalf ==false && secondHalf == false){
        
        angle = 0;
        //angleInThePreviousStep = 0;
        //flag = true;
        angleAccel = 0;
        angleVelocity = (Math.sqrt(2*9.81*length));
        ballX = anchorX;
        ballY = anchorY + length;
        canvas.drawLine(anchorX, anchorY,(float)ballX,(float)ballY,mPaint);
                 
                 canvas.drawCircle((float)ballX ,(float)ballY , 14, mPaint );
                 
                 atTheMiddlePositionWhileLeftToRight = false;
                 leftToRightMovement = false;
                 rightToLeftMovement = true;
                 atTheMiddlePositionWhileRightToLeft = false;
                 firstHalf = false;
                 secondHalf = true;
                 
                
                 return;
       }
       //at the middle while right to left end
       
       
       
      
       ///Right to left second half
       if(leftToRightMovement == false &&
 rightToLeftMovement == true && 
atTheMiddlePositionWhileLeftToRight == false && 
atTheMiddlePositionWhileRightToLeft ==false && 
firstHalf == false && secondHalf == true){
        
        double velocityAtTheBeginning = angleVelocity;//not sure if doing the right thing... forgot mechanics
                
        
        angle += dt/(Math.sqrt(length/9.81));
        
         
        if((initialAngle - angle)>0.01){
        
           ballX = anchorX - (int) (Math.sin(angle) * length); //greater than anchorX
           ballY = anchorY + (int) (Math.cos(angle) * length);//less than anchorY
            
           canvas.drawLine(anchorX, anchorY,(float)ballX,(float)ballY,mPaint);
                     
                 canvas.drawCircle((float)ballX , (float)ballY , 14, mPaint );
                 
        }
        else{
         atTheMiddlePositionWhileLeftToRight = false;
                  leftToRightMovement = true;
                  rightToLeftMovement = false;
                  atTheMiddlePositionWhileRightToLeft = false;
                  firstHalf = true;
                  secondHalf = false;
                  angle = initialAngle;
        }
                 return;
       }        
     }
     
    }//onDraw



The thread function has been defined as follows:


class PendulamThread extends Thread {
        private SurfaceHolder _surfaceHolder;
        private Panel _panel;
        private boolean _run = false;

        public PendulamThread(SurfaceHolder surfaceHolder, Panel panel) {
            _surfaceHolder = surfaceHolder;
            _panel = panel;
        }

        public void setRunning(boolean run) {
            _run = run;
        }

        public SurfaceHolder getSurfaceHolder() {
            return _surfaceHolder;
        }

        @Override
        public void run() {
            Canvas c;
            while (_run) {
                c = null;
                try {
                    c = _surfaceHolder.lockCanvas(null);
                    synchronized (_surfaceHolder) {
                        _panel.onDraw(c);
                        Thread.sleep(50);
                       //c.drawColor(Color.BLACK);
                       // _panel.postInvalidateDelayed(10);
                    }
                }
                 catch(InterruptedException e){
                         
                 }
                     
                finally {
                }
                    // do this in a finally so that if an exception is thrown
                    // during the above, we don't leave the Surface in an
                    // inconsistent state
                    if (c != null) {
                        _surfaceHolder.unlockCanvasAndPost(c);
                     }
                 }
             }
        }

And the Activity class is like the below:

package com.somitsolutions.android.pendulamsimulation;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class PendulamSimulationActivity extends Activity {
 
 //private Paint mPaint;
 private boolean leftToRightMovement = true;
 private boolean rightToLeftMovement = false;
 private boolean atTheMiddlePositionWhileLeftToRight = false;
 private boolean atTheMiddlePositionWhileRightToLeft = false;
 private boolean firstHalf = true;
 private boolean secondHalf = false;
 private volatile double ballX = 0;
 private volatile double ballY = 0;
 
 //private boolean theCenterBeingDrawn = false;
 
 double angleAccel = 0.0;
 double angleVelocity = 0;
 double dt = 0.15;
 
 private boolean flag = false;
 
 boolean flagCondition = false;
 
 private int anchorX;
 private int anchorY;
 public static double initialAngle = Math.PI/4;
 public static double angle = Math.PI/4;
 double angleInThePreviousStep = Math.PI/4;
 
 private static final int length = 150;
 
 private Paint mPaint;
 
 private Paint mRefreshPaint;
 
 //SurfaceHolder surfaceHolder;
 
 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        Panel p = new Panel(this);
       
        mPaint = new Paint();
  mPaint.setColor(Color.YELLOW);
  
  mRefreshPaint = new Paint();
  mRefreshPaint.setColor(Color.BLACK);
  
        setContentView(p);
        
    }
.......
.......
.......
    ///Panel and Pendulum Thread classes go here

i would like to share some issues that i faced while doing this animation. as all of you know that the simple animation is done by removing the trace of a moving object by repainting the previous position with the background color. i was trying to do the same thing by repainting only that part of the screen which was occupied by the pendulum before moving to a new position. however, it was not giving proper result. when i was scratching my head over the issue, suddenly i saw a simple line in android documentation that says if somebody wants to repaint only a portion of the screen, the result may be undefined. so its better to repaint the whole screen for proper animation. and it solved my problem. and hence the first line of the onDraw() is canvas.drawColor(Color.BLACK).

similarly, using the same principles, i have simulated the circular motion. the apk for the same can be download from here. the screen capture of this app is like the following:

i am also trying to do some experimentation with the simulation of different physics functionality using the game engine called Cocos2D. here is the screen capture of one of such experimentation which simulates the circular motion.

hopefully this article will be able to throw some lights on android graphics and animation. 
with this positive hope i would like to end this discussion.

Tuesday, January 17, 2012

FFT based simple Spectrum Analyzer with Source Code

i am writing this blogpost to pay homage to my alma mater... i was not at my level best to understand all aspects of Electonics & Telecommunication, the Microprocessor, the Digital Communication, the Digital Signal processing as taught by my professors... however, after so many years while playing around with different software, i understand how valuable was their contribution to make me an engineer. i remember, how important was the lesson of digital communication, and digital signal processing taught by Dr. T.K.Sen... i remember how important was the lesson of Microprocessor taught by A.R.... i remember how important was the lectures of Maths during our engineering course... i remember how important were the concepts of Fourier Transformation, FFT, DFT, Laplace Transformation, Matrix algebra and Complex Algebra...Hats off to all those professors who in spite of all odds helped a small town boy see the outer world...

i was so excited when i finished the coding part (of course with the help of Google...) and saw its working on a real device...

Here are the a screenshot i have taken from an Android device...



and here (https://gitlab.com/som.mukhopadhyay/FFTBasedSpectrumAnalyzer) goes the source code which may help someone interested in Android...

Wednesday, December 21, 2011

How to set up proxy for Android emulator behind a firewall...



Here is how i had set up my emulator's network settings for browsing the internet on a Windows 7 machine. for linux the same principle applies...
  • Make the emulator pass through the firewall
  • if you are behind a proxy go to settings and set up your proxy for the emulator through the following steps-
  1. Open the emulator and click on Menu
  2. Click on Settings
  3. Click on Wireless & Networks
  4. Go to Mobile Networks
  5. Go to Access Point Names and click on it
  6. Click on Telkila Internet
  7. In the Edit Access Point, input Proxy server and Port
  8. Also provide the User Name and Password
  9. Keep rest of the fields blank

  • Sometimes the DNS of the host PC is not recognized by the emulator...  in that case use the following command in the command prompt...emulator -avd -dns -server 8.8.8.8 (8.8.8.8 is the Googles default DNS) and change the DNS server of your machine to 8.8.8.8. otherwise you may opt for the DNS your company is using in the emulator -avd -dns -server command...
Hope this discussion comes handy for the Android newbies...

Monday, November 21, 2011

An implementation of Finite State Machine in Android using Handler...

Note: If you want to know about a full-fledged application about how a long running task in a background service has been broken into small states please have a look at this article.

As i was doing some research on different concepts in Android, i came out with this implementation of Finite State Machine using the Handler class... i would like to share it with you... the state diagram of the application will look as the following:

The main Activity class looks like the following:

package com.android.training.statepattern;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;



public class StatePatternActivity extends Activity implements View.OnClickListener{
 private Button startStatePattern;
 private MyHandler handler;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        startStatePattern = (Button)findViewById(R.id.button1);
        
        startStatePattern.setOnClickListener(this);
        handler = new MyHandler(this);
    }
    
    public void onClick(View v){
     if(v.equals(startStatePattern)){
      handler.sendEmptyMessage(1);
      }
    }  
}

And the other class is as follows;
package com.android.training.statepattern;

import android.os.Handler;
import android.os.Message;
import android.widget.Toast;

public class MyHandler extends Handler {
 private StatePatternActivity MainActivity;
 
 MyHandler(StatePatternActivity a){
  this.MainActivity = a;
 }
 //state transition logic is strongly coupled with the different states...
  public void handleMessage(Message msg){
   switch(msg.what){
   case 1:
    ////do the processing
    Toast.makeText(MainActivity.getApplicationContext(),"Inside State 1", 2000).show();
    this.sendEmptyMessage(2);
    break; 
   case 2:
    ///do the processing
    Toast.makeText(MainActivity.getApplicationContext(),"Inside State 2", 2000).show();
    this.sendEmptyMessage(3);
    break;    case 3:
    ///do the processing
    Toast.makeText(MainActivity.getApplicationContext(),"Inside State 3", 2000).show();
    this.sendEmptyMessage(4);
    break;
   case 4:
    break;
  default:
   break;   
   }
  } 
}

Let me explain the code a bit...

here the crux of the solution lies in the MyHandler class derived from Handler.. The main activity class HAS (UML term) MyHandler...

We start the State machine by sending a message (integer 1) through the function SendEmptyMessage called on MyHandler object. As a result, the callback function called handleMessage of the Handler is called and we handle this state's functionality here... The next all starte transitions happen sequentially from this callback function...
Hope this throws some lights on a specific design concept in Android...

Thursday, November 17, 2011

Robotium - automated unit test tool for Android...

the following text explains how to use Robotium in Eclipse.. Robotium is an automated unit testing tool for Android...
for this we need to download the Robotium.jar file from here...
setting up the environment is easy...

  • put the above jar in the build path’s library section...
  • add the following lines of code in the manifest.xml file in the manifest section (i.e. outside the app section)...
(instrumentation android:name="android.test.InstrumentationTestRunner"
   android:targetPackage="training.android.trainingunitconverter"
   android:label="1" /)

the below snippet of code is to test the UnitConverter app...

  • create a file(say UnitConverterTest.java) and add the following piece of code...

package training.android.trainingunitconverter;

import java.util.ArrayList;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.Smoke;
import android.widget.EditText;
import android.widget.Spinner;
import com.jayway.android.robotium.solo.Solo;

public class UnitConverterTest extends ActivityInstrumentationTestCase2{
private Solo solo;
public UnitConverterTest() {
super("training.android.trainingunitconverter", UnitConverter.class);
}
public void setUp() throws Exception {
solo = new Solo(getInstrumentation(), getActivity());
}
@Smoke
public void testUnitDropDown() throws Exception {

solo.assertCurrentActivity("Expected UnitConverter activity", "UnitConverter");
solo.pressSpinnerItem(0, 1);
solo.sleep(2000);
EditText value = (EditText)solo.getView(R.id.EditTextValue);
solo.enterText(value, "1");
solo.pressSpinnerItem(1,0);
solo.sleep(1000);
solo.pressSpinnerItem(2,1);
solo.sleep(1000);
solo.clickOnButton(0);
assertTrue(solo.searchText("1000.0"));
}
@Override
public void tearDown() throws Exception {
//Robotium will finish all the activities that have been opened
solo.finishOpenedActivities();
}
}

however, it seems that the solo.PressSpinnerItem() is not functioning properly on the emulator (either Android 2.2 or Android 1.6)... hopefully this issue will be fixed in the next release of Robotium...

to run it in the emulator, right click on the Project... go to Run As.. and press  Android JUnit Test...

the screen shot for the above test condition is 

as from the test case
@Smoke
public void testUnitDropDown() it is clear, that we are first asking the test framework to select the item having index 1 (that is Weight) from the first spinner. then we are asking the framework to put a value 1 in the edittext. we are then asking the test framework to select item with 0th index (that is Kg) from the second spinner and item with index 1 (that is gm) from the third spinner... and we are asking the framework to press Convert button... so the expected result will be 1000.0... and we search in the test case if it has the value 1000.0. then the test case will PASS
similarly we can test different scenarios automatically by having more such functions as testUnitDropDown...


note:  the source code of the UnitConverter App with the Robotium test code can be cloned from https://github.com/sommukhopadhyay/UnitConverter/tree/f349925ffbd2cccb3a0bac37c4d7b428d92b354d